Como olhar nos olhos de Cassandra sem perder dados, estabilidade e fé no NoSQL

Como olhar nos olhos de Cassandra sem perder dados, estabilidade e fé no NoSQL

Dizem que vale a pena tentar tudo na vida pelo menos uma vez. E se você está acostumado a trabalhar com SGBDs relacionais, então vale a pena conhecer o NoSQL na prática, antes de mais nada, pelo menos para o desenvolvimento geral. Agora, devido ao rápido desenvolvimento desta tecnologia, existem muitas opiniões conflitantes e debates acalorados sobre este tema, o que alimenta especialmente o interesse.
Se você se aprofundar na essência de todas essas disputas, verá que elas surgem devido à abordagem errada. Quem utiliza bancos de dados NoSQL exatamente onde são necessários fica satisfeito e recebe todas as vantagens desta solução. E os experimentadores que confiam nesta tecnologia como uma panacéia onde ela não é aplicável ficam desapontados, tendo perdido os pontos fortes dos bancos de dados relacionais sem obter benefícios significativos.

Contarei a vocês nossa experiência na implementação de uma solução baseada no SGBD Cassandra: o que tivemos que enfrentar, como saímos de situações difíceis, se conseguimos nos beneficiar do uso do NoSQL e onde tivemos que investir esforços/fundos adicionais .
A tarefa inicial é construir um sistema que registre chamadas em algum tipo de armazenamento.

O princípio de funcionamento do sistema é o seguinte. A entrada inclui arquivos com uma estrutura específica que descreve a estrutura da chamada. O aplicativo então garante que essa estrutura seja armazenada nas colunas apropriadas. Futuramente, as chamadas salvas serão utilizadas para exibir informações sobre o consumo de tráfego dos assinantes (tarifas, ligações, histórico de saldo).

Como olhar nos olhos de Cassandra sem perder dados, estabilidade e fé no NoSQL

Está bem claro por que eles escolheram Cassandra - ela escreve como uma metralhadora, é facilmente escalonável e tolerante a falhas.

Então, foi isso que a experiência nos deu

Sim, um nó com falha não é uma tragédia. Esta é a essência da tolerância a falhas de Cassandra. Mas um nó pode estar ativo e ao mesmo tempo começar a sofrer desempenho. Acontece que isso afeta imediatamente o desempenho de todo o cluster.

Cassandra não irá protegê-lo onde a Oracle o salvou com suas restrições. E se o autor do aplicativo não entendeu isso de antemão, então o duplo que chegou para Cassandra não é pior que o original. Assim que chegar, colocaremos.

IB não gostou muito do Cassandra grátis pronto para uso: Não há registro de ações do usuário, nem diferenciação de direitos. As informações sobre chamadas são consideradas dados pessoais, o que significa que todas as tentativas de solicitá-las/alterá-las de qualquer forma deverão ser registradas com possibilidade de posterior auditoria. Além disso, você precisa estar ciente da necessidade de separar direitos em diferentes níveis para diferentes usuários. Um engenheiro de operação simples e um superadministrador que pode excluir livremente todo o keyspace têm funções, responsabilidades e competências diferentes. Sem essa diferenciação de direitos de acesso, o valor e a integridade dos dados serão imediatamente questionados mais rapidamente do que com QUALQUER nível de consistência.

Não levamos em consideração que as chamadas exigem análises sérias e amostragem periódica para diversas condições. Como os registros selecionados devem então ser excluídos e reescritos (como parte da tarefa, devemos apoiar o processo de atualização de dados quando os dados inicialmente entraram incorretamente em nosso loop), Cassandra não é nossa amiga aqui. Cassandra é como um cofrinho - é conveniente colocar coisas, mas você não pode contar com isso.

Encontramos um problema ao transferir dados para zonas de teste (5 nós no teste versus 20 no baile). Neste caso, o dump não pode ser usado.

O problema com a atualização do esquema de dados de um aplicativo gravado no Cassandra. Uma reversão gerará muitas marcações para exclusão, o que pode levar a perdas de produtividade de maneiras imprevisíveis.. Cassandra é otimizada para gravação e não pensa muito antes de escrever. Qualquer operação com dados existentes também é uma gravação. Ou seja, ao deletar o desnecessário, simplesmente produziremos ainda mais registros, e apenas alguns deles serão marcados com lápides.

Tempo limite ao inserir. Cassandra está linda na gravação, mas às vezes o fluxo de entrada pode confundi-la significativamente. Isso acontece quando o aplicativo começa a percorrer vários registros que não podem ser inseridos por algum motivo. E precisaremos de um DBA real que monitorará gc.log, logs de sistema e depuração para consultas lentas, métricas de compactação pendentes.

Vários data centers em um cluster. Onde ler e onde escrever?
Talvez dividido em leitura e escrita? E se sim, deveria haver um CD mais próximo da aplicação para escrita ou leitura? E não acabaremos com um cérebro realmente dividido se escolhermos o nível de consistência errado? São muitas dúvidas, muitas configurações desconhecidas, possibilidades que você realmente quer mexer.

Como decidimos

Para evitar que o nó afunde, o SWAP foi desativado. E agora, se houver falta de memória, o nó deve ficar inativo e não criar grandes pausas no GC.

Portanto, não dependemos mais da lógica do banco de dados. Os desenvolvedores de aplicativos estão se reciclando e começando a tomar precauções ativamente em seu próprio código. Separação clara ideal de armazenamento e processamento de dados.

Adquirimos suporte da DataStax. O desenvolvimento do Cassandra in a box já cessou (o último commit foi em fevereiro de 2018). Ao mesmo tempo, a Datastax oferece um excelente serviço e um grande número de soluções modificadas e adaptadas para soluções IP existentes.

Também quero observar que Cassandra não é muito conveniente para consultas de seleção. Claro, CQL é um grande avanço para os usuários (em comparação com Trift). Mas se você tem departamentos inteiros acostumados a conexões tão convenientes, filtragem gratuita por qualquer campo e recursos de otimização de consultas, e esses departamentos estão trabalhando para resolver reclamações e acidentes, então a solução no Cassandra parece hostil e estúpida para eles. E começamos a decidir como nossos colegas deveriam fazer amostras.

Consideramos duas opções: na primeira opção escrevemos chamadas não apenas em C*, mas também no banco de dados Oracle arquivado. Apenas, ao contrário do C*, este banco de dados armazena chamadas apenas do mês atual (profundidade de armazenamento de chamadas suficiente para casos de recarga). Aqui vimos imediatamente o seguinte problema: se escrevermos de forma síncrona, perderemos todas as vantagens do C* associadas à inserção rápida; se escrevermos de forma assíncrona, não há garantia de que todas as chamadas necessárias tenham chegado ao Oracle. Havia uma vantagem, mas uma grande: para a operação permanece o mesmo desenvolvedor PL/SQL familiar, ou seja, implementamos praticamente o padrão “Facade”. Implementamos um mecanismo que descarrega chamadas de C*, extrai alguns dados para enriquecimento das tabelas correspondentes no Oracle, junta as amostras resultantes e nos dá o resultado, que então utilizamos de alguma forma (reverter, repetir, analisar, admirar). Contras: o processo é bastante complexo e, além disso, não há interface para os funcionários da operação.

No final, optamos pela segunda opção. Apache Spark foi usado para coletar amostras de diferentes frascos. A essência do mecanismo foi reduzida ao código Java, que, usando as chaves especificadas (assinante, tempo de chamada - chaves de seção), extrai dados de C*, bem como os dados necessários para enriquecimento de qualquer outro banco de dados. Depois disso, ele os junta em sua memória e exibe o resultado na tabela resultante. Desenhamos uma face de teia sobre a faísca e ficou bastante utilizável.

Como olhar nos olhos de Cassandra sem perder dados, estabilidade e fé no NoSQL

Ao resolver o problema de atualização dos dados de testes industriais, consideramos novamente várias soluções. Tanto a transferência via Sstloader quanto a opção de dividir o cluster da zona de teste em duas partes, cada uma das quais pertencendo alternadamente ao mesmo cluster do promocional, sendo assim alimentada por ele. Ao atualizar o teste, foi planejado trocá-los: a parte que funcionou no teste é liberada e entra em produção, e a outra passa a trabalhar com os dados separadamente. Porém, depois de pensar novamente, avaliamos de forma mais racional os dados que valiam a pena transferir e percebemos que as próprias chamadas são uma entidade inconsistente para testes, gerada rapidamente se necessário, e é o conjunto de dados promocionais que não tem valor para transferência para o teste. Existem vários objetos de armazenamento que valem a pena mover, mas são literalmente algumas mesas, e não muito pesadas. Portanto nós como solução, o Spark veio novamente em socorro, com a ajuda do qual escrevemos e começamos a usar ativamente um script para transferência de dados entre tabelas, prom-test.

Nossa política de implantação atual nos permite trabalhar sem reversões. Antes da promoção, há um teste obrigatório, onde um erro não sai tão caro. Em caso de falha, você sempre pode descartar o casespace e rolar todo o esquema desde o início.

Para garantir a disponibilidade contínua do Cassandra, você precisa de um dba e não só dele. Todos que trabalham com o aplicativo devem entender onde e como analisar a situação atual e como diagnosticar problemas em tempo hábil. Para isso, utilizamos ativamente o DataStax OpsCenter (Administração e monitoramento de cargas de trabalho), métricas do sistema Cassandra Driver (número de timeouts para escrita em C*, número de timeouts para leitura de C*, latência máxima, etc.), monitoramos a operação da própria aplicação, trabalhando com Cassandra.

Quando pensamos na questão anterior, percebemos onde poderia estar o nosso principal risco. São formulários de exibição de dados que exibem dados de diversas consultas independentes ao armazenamento. Dessa forma, podemos obter informações bastante inconsistentes. Mas este problema seria igualmente relevante se trabalhássemos com apenas um data center. Portanto, o mais razoável aqui é, obviamente, criar uma função em lote para leitura de dados em um aplicativo de terceiros, o que garantirá que os dados sejam recebidos em um único período de tempo. Quanto à divisão em leitura e escrita em termos de desempenho, aqui fomos travados pelo risco de que com alguma perda de ligação entre os DCs poderíamos acabar com dois clusters completamente inconsistentes entre si.

Como resultado, por enquanto parou no nível de consistência para escrever EACH_QUORUM, para leitura - LOCAL_QUORUM

Breves impressões e conclusões

A fim de avaliar a solução resultante do ponto de vista do apoio operacional e das perspectivas de desenvolvimento adicional, decidimos pensar onde mais tal desenvolvimento poderia ser aplicado.

Logo de cara, depois pontuação de dados para programas como “Pague quando for conveniente” (carregamos informações em C*, cálculo usando scripts Spark), contabilização de sinistros com agregação por área, armazenamento de funções e cálculo de direitos de acesso do usuário com base na função matriz.

Como você pode ver, o repertório é amplo e variado. E se escolhermos o campo dos apoiadores/oponentes do NoSQL, então nos juntaremos aos apoiadores, já que recebemos nossas vantagens, e exatamente onde esperávamos.

Até mesmo a opção Cassandra pronta para uso permite o dimensionamento horizontal em tempo real, resolvendo de forma absolutamente indolor o problema de aumento de dados no sistema. Conseguimos mover um mecanismo de carga muito alta para calcular agregados de chamadas em um circuito separado e também separar o esquema e a lógica do aplicativo, eliminando a má prática de escrever trabalhos e objetos personalizados no próprio banco de dados. Tivemos a oportunidade de escolher e configurar, para agilizar, em quais DCs realizaremos os cálculos e em quais registraremos os dados, nos seguramos contra travamentos de nós individuais e do DC como um todo.

Aplicando a nossa arquitetura a novos projetos, e já tendo alguma experiência, gostaria de ter imediatamente em conta as nuances descritas acima, e evitar alguns erros, suavizar alguns cantos agudos que não puderam ser evitados inicialmente.

Por exemplo, acompanhe as atualizações de Cassandra em tempo hábilporque alguns dos problemas que tivemos já eram conhecidos e corrigidos.

Não coloque o próprio banco de dados e o Spark nos mesmos nós (ou dividir estritamente pela quantidade de uso de recursos permitido), já que o Spark pode consumir mais OP do que o esperado, e obteremos rapidamente o problema número 1 de nossa lista.

Melhorar o monitoramento e a competência operacional na fase de testes do projeto. Inicialmente, leve em consideração, tanto quanto possível, todos os potenciais consumidores da nossa solução, porque é disso que a estrutura do banco de dados dependerá.

Gire o circuito resultante várias vezes para possível otimização. Selecione quais campos podem ser serializados. Compreender quais tabelas adicionais devemos fazer para levar em consideração da maneira mais correta e otimizada e, em seguida, fornecer as informações necessárias mediante solicitação (por exemplo, assumindo que podemos armazenar os mesmos dados em tabelas diferentes, levando em consideração diferentes detalhamentos de acordo com critérios diferentes, podemos economizar significativamente tempo de CPU para solicitações de leitura).

Média Providencie imediatamente a anexação de TTL e a limpeza de dados desatualizados.

Ao baixar dados do Cassandra A lógica do aplicativo deve funcionar com base no princípio FETCH, de modo que nem todas as linhas sejam carregadas na memória de uma só vez, mas selecionadas em lotes.

É aconselhável antes de transferir o projeto para a solução descrita verifique a tolerância a falhas do sistema conduzindo uma série de testes de colisão, como perda de dados em um data center, restauração de dados danificados durante um determinado período, queda de rede entre data centers. Tais testes não apenas permitirão avaliar os prós e os contras da arquitetura proposta, mas também fornecerão boas práticas de aquecimento para os engenheiros que os conduzem, e a habilidade adquirida estará longe de ser supérflua se as falhas do sistema forem reproduzidas na produção.

Se trabalharmos com informações críticas (como dados de faturamento, cálculo de débito de assinantes), também vale a pena ficar atento a ferramentas que irão reduzir os riscos decorrentes das funcionalidades do SGBD. Por exemplo, use o utilitário nodesync (Datastax), tendo desenvolvido uma estratégia ideal para seu uso para por uma questão de consistência, não crie uma carga excessiva em Cassandra e usá-lo apenas para determinadas tabelas em um determinado período.

O que acontece com Cassandra depois de seis meses de vida? Em geral, não existem problemas não resolvidos. Também não permitimos acidentes graves ou perda de dados. Sim, tivemos que pensar em compensar alguns problemas que não surgiam anteriormente, mas no final isso não atrapalhou muito a nossa solução arquitetônica. Se você quer e não tem medo de experimentar algo novo e ao mesmo tempo não quer ficar muito decepcionado, prepare-se para o fato de que nada é de graça. Você terá que entender, se aprofundar na documentação e montar seu próprio rake individual mais do que na antiga solução legada, e nenhuma teoria lhe dirá com antecedência qual rake está esperando por você.

Fonte: habr.com

Adicionar um comentário