Um cacoete que reconheço em mim mesmo, e possivelmente afeta muitos veteranos da profissão de informata, é a tendência de abordar os problemas de forma puramente "algorítmica".
Por exemplo, num controlador de caixa de água, procurei prever todas as situações possíveis e imagináveis, dentro do que é possível vislumbrar com base nos sensores disponíveis, e então codifiquei toda essa "inteligência" precozida numa máquina de estado. Qualquer mudança ou melhoria implica num update de firmware.
Já a abordagem "Big Data" é, num primeiro momento, apenas coletar as séries de dados dos sensores. Então, cria-se regras de funcionamento, unicamente com base nos dados, usando fórmulas ou expressões no estilo SQL (nada de linguagem Turing-completa). As regras são inseridas no controlador usando alguma ferramenta low-code. Fazer alterações posteriores é tão fácil quanto editar uma planilha.
De alguma forma, meu cérebro de programador considera a primeira abordagem como "correta", e a segunda abordagem como "impura", até preguiçosa — pois em vez de fritar código como um louco, tenho de analisar, experimentar e ajustar.
Depois de décadas trabalhando em times pequenos estilo skunkworks, empresas pequenas, e programando coisas pequenas (IoT, celular, firmware de roteador), nos últimos meses estou tendo a experiência de ser uma pequena engrenagem numa Big Tech. Obviamente não trabalho de graça, porém o maior incentivo na hora de aceitar este trampo foi justamente mudar de ares, aprender coisas novas.
As coisas que mais me impressionaram foram:
a) o investimento em "observabilidade", ou seja, logs e métricas. Parece que a cada 3 linhas de código-fonte, há um log ou uma métrica sendo registrado. Naturalmente, isso gera uma enorme quantidade de dados, que precisam ser saneados, tratados e armazenados. Pelo menos 15% do custo de infraestrutura são dedicados à observabilidade.
b) o acesso a essas informações é surpreendentemente rápido, prático e aberto a todos os colaboradores. Gente muito boa quebrou a cabeça para que essa enorme torrente de dados de observabilidade flua de forma rápida e confiável para os serviços de consulta.
c) uso pervasivo de logs e métricas para monitorar a saúde do sistema. É fácil criar métricas novas, e as ferramentas no-code tornam fácil criar ou melhorar alarmes de monitoramento. Processos de integração contínua baseiam-se fortemente em métricas, tanto ou mais que em testes automatizados, para determinar bugs ou regressões.
É óbvio que, para usar essa abordagem, é preciso existir um sistema em funcionamento, de onde se coleta dados. Quando estamos criando algo do zero absoluto, precisamos fazer ilações, que mais tarde serão confirmadas ou refutadas pelos dados.
Mas é importante assegurar que código novo produza logs e métricas para que seu desempenho possa ser aferido — analogamente ao que acontece com testes, se não fizer logo no início, o débito técnico vai ficando pesado.
Segundo a Wikipedia, Big Data é a ciência da manipulação de volumes de dados grandes demais para a utilização de técnicas convencionais. Esqueça arquivos de log, esqueça bancos de dados SQL monolíticos.
Bancos relacionais presumem leitura frequente e escrita infrequente. Em Big Data, é o contrário. Esta é uma razão legítima para adotar-se NoSQL, cuja implementação exige técnicas especiais. Em particular, dados no estilo time series (séries de dados indexadas por data/hora, muito comuns em observabilidade) não casam bem com banco de dados relacional.
Se o volume de dados tende ao infinito, extrair informação e valor da massa de dados nos força a usar agregadores o tempo todo. No mínimo absoluto, o básico da estatística: média, mediana, desvios, máximos, mínimos, quantis (p50, p90, p99). Fazer uso efetivo de big data implica em estar afiado em estatística, e saber qual agregador usar com qual métrica.
Mesmo que as amostras individuais ainda sejam relevantes no curto prazo, é provável que não o sejam no longo prazo. Ademais, capacidade de processamento e armazenamento não são infinitos nem são de graça. Novamente, a solução é usar agregadores para "comprimir" dados antigos. Bancos de dados para time series fazem isso automaticamente.
Não é possível usar uma linguagem Turing-completa para consultar os dados, uma vez que se o volume tende ao infinito, não é razoável forçar a CPU do servidor a analisar cada amostra. Por outro lado, os agregadores são (ou espera-se que sejam) otimizados na origem, de modo que não há penalidade em usá-los.
As consultas podem ser otimizadas tanto do lado do banco de dados (ou serviço que faça as vezes de), como localmente. Ferramentas como Python Pandas fazem uso de vetorização, então mesmo o tratamento local de dados é beneficiado pelo uso dos idiomas do Pandas (que lembram algo entre SQL, Excel e low-code) no lugar dos velhos métodos.
O big data é viabilizado pelo estado atual da tecnologia de nuvem: processamento e armazenamento baratos, abundantes e escaláveis à vontade. A abordagem é relativamente nova, mas não porque fôssemos burros e tapados há 30 anos atrás. Simplesmente não havia como armazenar e processar tantos dados. Destilar e condensar os dados na forma de algoritmos era o único jeito de fazer tudo caber num computador da época.
Voltando ao exemplo do controlador de caixa de água: faz sentido implementá-lo à moda do big data? Talvez não, porque a) a caixa de água é um sistema simples, é possível usar uma máquina de estado para cobrir todas as situações possíveis; b) o controlador é um Arduino, que não possui abundância de recursos e deve operar desconectado da nuvem, então seria difícil usar uma abordagem big data.
Mas ainda seria válido usar big data para detectar certas anomalias da caixa de água, como por exemplo consumo anormalmente alto (indício de vazamento). Isso também poderia ser previsto na máquina de estado, mas começa a ficar enrolado. Não há como definir a priori o que é consumo anormal de água; é preciso deixar a família morar na casa, coletar dados e aí definir o que é normal/anormal. E certamente essa definição terá de ser ajustada de quando em vez por conta de alarmes falsos. Ninguém tem bola de cristal, afinal de contas.
De certa forma, existia e existe essa expectativa em cima dos desenvolvedores de software: ter bola de cristal e antever todas as possibilidades de um sistema. Até certa medida faz parte do trabalho, como no caso da caixa de água num sistema hidráulico sem vazamentos. Porém muitas vezes é uma exigência sobrehumana e injusta. O cliente exigente que quer tudo barato, perfeito e para ontem é apenas um cliente com bolsos vazios e ignorante acerca dos seus próprios processos.
Olhando em retrospecto, vejo que muitas tentativas de "prever o futuro" algoritmicamente são um tipo de otimização prematura.
A abordagem Big Data tem ainda a vantagem do fácil reuso. É verdade que estabelecer a estrutura para controlar uma caixa de água usando Big Data seria custosa e trabalhosa, num primeiro momento. Porém, uma vez estabelecida, serve para muitíssimas outras coisas. Em vez de construir um software novo para o aquecedor, para o ar-condicionado, para o alarme, para as luzes externas, etc.
Em vez de fazer um sistema fim-a-fim do zero, cheio de código, podemos usar protocolos e serviços prontos, complementado com um pouquinho de código aqui e ali. MQTT para sensores e atuadores, InfluxDB para armazenar as séries, Telegraf para copiar dados do MQTT para InfluxDB, Grafana para criar gráficos, dashboards e alertas.
Existem precedentes históricos da abordagem Big Data, não é algo que surgiu anteontem. Um exemplo é a "calculadora de marés", uma máquina que calcula tábuas de marés. Ela literalmente prevê o nível da maré no futuro. A primeira calculadora desse tipo foi inventada em 1872.
Há duas formas de prever as marés. Uma é modelar todo o sistema solar, com Sol, Lua, Terra e seus continentes e oceanos, e finalmente modelar o movimento das águas reagindo a todos esses elementos. Esta seria a forma "bonita" de fazer a coisa, e permitiria prever a maré de qualquer ponto desejado, porém seria extremamente complicada e custosa.
A outra forma, típica, é coletar uma série de dados medindo o nível real da maré. Então, calcula-se a série de Fourier, e usa-se engrenagens de tamanhos correspondentes. A calculadora fica simples e barata, sem prejuízo da precisão. Porém ela só pode prever a maré daquele ponto onde houve a coleta de dados.
Considero a calculadora de maré um precursor do Big Data. Primeiro, porque a máquina é construída em função do que diz a série de dados, ela não tenta modelar o processo físico subjacente, nem explicar por que as marés acontecem assim ou assado. Segundo, por fazer uso de um método avançado de análise de dados (série de Fourier), que consegue "prever o futuro" à moda das redes neurais, e que vai muito além de métodos típicos de guarda-livros e.g. correlação linear.
A linguagem SQL, tão odiada pelo desenvolvedor típico, também é um precursor do Big Data. Além de ela já possuir GROUP BY e agregadores, no SQL você diz "o que" deseja obter dos dados, não "como" vai fazer isso. A otimização é problema do servidor. É o mesmo que acontece com linguagens de query em Big Data.
Outro paralelo entre SQL e Big Data são os triggers, onde uma ação algorítmica é disparada com base no que diz a série de dados.
Acredito que o desenvolvedor típico fica nervoso ao usar SQL justamente porque ele oculta o algoritmo exato de busca e processamento dos dados. Claro, às vezes acontece de uma consulta SQL ser acidentalmente muito pesada e demorada. Otimização SQL perfeita é um problema intratável, afinal de contas. Mas o desenvolvedor não escapará de usar consultas estilo SQL ao lidar com Big Data. E sim, também acontece de consultas Big Data ficarem acidentalmente pesadas.
Mais um precursor: controladores PID, baseados em feedback. Em vez de tentar modelar à perfeição o processo físico de uma caixa de água ou aquecedor, o controlador PID simplesmente responde às métricas reportadas pelos sensores. Repare que integral e derivada (que correspondem ao "I" e ao "D" da sigla PID) são agregadores de pleno direito. Controladores mais avançados podem usar filtro de Kalman, que é simplesmente um agregador estilo média móvel, otimizado para o nível de ruído dos sensores.
O que todos esses exemplos têm em comum, é o foco no "o quê", em detrimento do "como" e do "por quê". É uma acusação frequente contra redes neurais e deep learning: ninguém sabe como elas funcionam, ou como chegaram a certa conclusão, ou quais as causas subjacentes.
Uma rede neural é, no fundo, apenas uma ferramenta estatística, que detecta tendências e padronagens — assim como média móvel, correlação linear, autocorrelação, análise de Fourier, etc. Apenas calha de ser mais poderosa. Mas nenhuma delas explica o "como", assim como a calculadora de marés não explica como as marés acontecem.
Como dito antes, em Big Data o volume de dados é presumido tão grande que os pontos individuais são inacessíveis e irrelevantes. Se ingerimos 1 bilhão de amostras por segundo, somos obrigados a lançar mão de agregação para obter um valor humanamente legível, que condense de forma efetiva o significado desse bilhão de pontos de dados.
Estamos todos acostumados com média, desde a escola, onde a média das notas definia se ficaríamos em exame. Mas este é um agregador inadequado para muitas métricas. Por exemplo, é válido fazer média de uma métrica de latência? De que adianta uma média boa, se 10% dos seus clientes são atendidos com uma latência inaceitavelmente grande?
Por outro lado, sempre haverá um punhado de requisições cuja latência será muito alta; não há como exigir que 100% delas tenha latência baixa. Sempre haverá um cliente tentando acessar seu site roubando a Internet do vizinho do outro quarteirão usando uma antena de lata de Pringles. Desenhar seu sistema em torno desse pior caso também não é produtivo.
Outro exemplo: a média do consumo de RAM da sua frota de servidores é 90%. Isso é bom ou ruim? Parece folgadamente bom, mas se alguns servidores dentre milhares baterem 100%, as requisições direcionadas a eles falharão e serão perdidas, o que não é admissível. A média da RAM é importante, mas também é importante monitorar o pior caso, e tratá-lo ("matar" automaticamente os servidores problemáticos no curto prazo, e consertar o bug causador da doença no longo prazo).
Presumimos, talvez até instintivamente, que média é uma métrica boa pois presumimos que os acontecimentos seguem uma distribuição normal. As pessoas acreditam firmemente naquela máxima "tudo tende à media no longo prazo". Pode até ser verdade, mas Keynes observou que no longo prazo todos estaremos mortos. Em big data, é importante acostumar-se a usar quantis ou percentis.
No caso da latência, um bom agregador seria "p99", ou seja, qual a latência máxima para 99% dos clientes. O quantil p100 corresponde ao agregador "max", ou seja, o maior valor observado, p0 corresponde ao "min". O quantil p50 parece a média, mas é na verdade a mediana (que coincide com a média numa distribuição normal).
No caso da RAM, avg, p90, p99 e max são todas métricas relevantes. Uma boa média é o objetivo; o máximo aponta a existência de pelo menos um servidor problemático; os percentis p90 e p99 indicam se o grosso da frota está próximo da média (portanto saudável).
Analisar os diversos percentis vai dar uma boa noção de qual distribuição teórica (normal, exponencial, Poisson) encaixa na sua série de dados. Este artigo é uma excelente peça de advocacia pró-quantis.
Também pode acontecer das séries de dados apresentarem interrupções, ou o espaçamento dos dados no tempo ser irregular, de modo que a definição de "valor mais atual" fica difusa. Os sistemas de coleta de dados também falham ou soluçam, mas o mundo não pode parar quando isso acontece.
Tomar o último valor observado como o mais atual pode ser uma boa opção — mas por quanto tempo? Vale usar o último valor por 24h quando espera-se uma amostra nova por minuto? Provavelmente não.
Quando existem lacunas na série de dados, há o velho problema de considerar as lacunas como valendo "zero" ou "nada". Para cada situação, a resposta será diferente. Se o nível da caixa de água reporta 80, 80, 80, 80, 0, 80, 80 (uma amostra por minuto) esse zero só pode significar falha do sensor, e deve ser encarado como um "nada".
Outro cacoete é usar média móvel, tanto para preencher lacunas quanto para definir o "valor corrente" quando a série de dados é meio ruidosa. O pessoal de finanças adora usar médias móveis em análise gráfica. Porém, médias móveis são filtros passa-baixas disfarçados. Se usadas indiscriminadamente, causam reações lentas e atrasadas.
O texto saiu um pouco abstrato, reconheço. Como acontece com muitos outros textos deste site, o principal objetivo é "pensar alto", não pretender ser o guia definitivo sobre o assunto.
Mas pretendo escrever no futuro com exemplos práticos, tirados de sensores reais. A ideia é basear estas explorações no OpenTSDB e no Pandas, com que estou mais habituado (dentro do contexto de que sou um bisonho nessa seara).