
Dizem que na vida vale a pena tentar pelo menos uma vez. E se você está acostumado a trabalhar com DBMSs relacionais, se familiarizar com o NoSQL na prática vale a pena, antes de tudo, pelo menos para o desenvolvimento geral. Agora, devido ao rápido desenvolvimento dessa tecnologia, existem muitas opiniões conflitantes e debates acalorados sobre esse assunto, o que está alimentando especialmente o interesse.
Se você se aprofundar na essência de todas essas disputas, poderá ver que elas surgem devido à abordagem errada. Aqueles que usam os bancos de dados NoSQL exatamente onde são necessários ficam satisfeitos e obtêm todas as vantagens desta solução. E os pesquisadores que confiam nessa tecnologia como uma panacéia, onde ela não é aplicável, ficam desapontados por perder os pontos fortes dos bancos de dados relacionais sem obter benefícios significativos.
Vou contar sobre a nossa experiência na implementação de uma solução baseada no Cassandra DBMS: com o que tivemos que lidar, como saímos de situações difíceis, conseguimos obter um benefício usando o NoSQL e onde tivemos que investir esforço / dinheiro extra.
A tarefa inicial é criar um sistema que registre as chamadas para um determinado armazenamento.
O princípio do sistema é o seguinte. Arquivos com uma certa estrutura descrevendo a estrutura da chamada chegam à entrada. Em seguida, o aplicativo garante que essa estrutura seja salva nas colunas apropriadas. No futuro, as chamadas salvas são usadas para exibir informações sobre o consumo de tráfego para assinantes (cobranças, chamadas, histórico de saldo).

Por que Kassandra foi escolhida é bastante compreensível - ela escreve como uma metralhadora, facilmente escalável e tolerante a falhas.
Então, aqui está o que a experiência nos deu
Sim, o nó travado não é uma tragédia. Essa é a essência da tolerância a falhas de Cassandra. Mas o nó pode estar ativo e ao mesmo tempo começar a ceder ao desempenho . Como se viu, isso afeta imediatamente o desempenho de todo o cluster.
Cassandra não cobre onde o Oracle salvou com suas constantes . E se o autor do aplicativo não entendeu isso com antecedência, a captura de Cassandra não será pior que a original. Quando ele vier, vamos inseri-lo.
O Kassandra gratuito "pronto para uso" não gostou muito da segurança da informação: não há registro de ações do usuário nem diferenciação de direitos . As informações sobre chamadas estão relacionadas a dados pessoais, o que significa que todas as tentativas de solicitá-las / alterá-las de qualquer forma devem ser registradas com a possibilidade de auditoria subsequente. 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 podem remover livremente todo o espaço de chaves são funções diferentes, responsabilidades diferentes, competências. 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 conta que as chamadas exigem análises sérias, além de amostras periódicas para uma variedade de condições. Como os registros selecionados devem ser excluídos e reescritos (como parte da tarefa, devemos apoiar o processo de atualização dos dados quando os dados no loop de dados chegaram até nós incorretamente), Kassandra não é nossa amiga aqui. Cassandra, como um cofrinho, é conveniente colocar nele, mas você não poderá contar nele.
Enfrentou o problema de transferir dados para zonas de teste (5 nós no teste versus 20 no baile). Nesse caso, um despejo não pode ser usado.
O problema de atualizar o esquema de dados de um aplicativo que está gravando no Kassandra. A reversão dará origem a muitas lápides que, de maneira imprevisível, podem diminuir nossa produtividade . Cassandra é otimizado para gravação e, antes de gravar, não pensa muito. Qualquer operação com dados existentes também é um registro. Ou seja, depois de remover o excesso, simplesmente geramos ainda mais registros, e apenas uma parte deles será marcada com lápides.
Tempo limite na inserção. Cassandra é linda na gravação, mas às vezes o fluxo de entrada pode ser muito desconcertante para ela . Isso acontece quando o aplicativo começa a circular vários registros que não podem ser inseridos por qualquer motivo. E precisaremos de um DBA real, que seguirá os logs gc.log, system e debug para consultas lentas, métricas para compactação pendente.
Vários datacenters em um cluster. Onde ler e onde escrever?
Talvez dividido em leitura e escrita? E se sim, deveria haver um CD para escrever ou ler mais perto do aplicativo? E não teremos um cérebro dividido real se escolhermos o nível de consistência incorretamente? Muitas perguntas, muitas configurações inexploradas, recursos que realmente quero distorcer.
Como decidimos
Que o nó não desperdiçou, desativou o SWAP . E agora, com falta de memória, o nó deve se deitar e não produzir grandes pausas de gc.
Portanto, não esperamos mais lógica no banco de dados. Os desenvolvedores de aplicativos reaprendem e começam a se tornar ativamente seguros em seu próprio código. Separação clara e perfeita do armazenamento e processamento de dados.
Adquirimos suporte do DataStax. O Kassandra in a box já parou de se desenvolver (o último commit em fevereiro de 2018). Ao mesmo tempo, o Datastax oferece um excelente serviço e um grande número de modificados e adaptados às soluções de IC existentes.
Também quero observar que o Kassandra não é muito conveniente para consultar amostras. Obviamente, o CQL é um grande passo para os usuários (comparado ao Trift). Mas se você tem departamentos inteiros, acostumados a junções tão convenientes, filtragem gratuita por qualquer campo e opções de otimização de consultas, e esses departamentos estão trabalhando para fechar reclamações e acidentes, a decisão sobre Kassandra lhe parece inimiga e estúpida. E começamos a abordar a questão de como nossos colegas podem fazer amostras.
Consideramos duas opções: na primeira opção, escrevemos chamadas não apenas em C *, mas também no banco de dados de arquivamento Oracle. Somente, diferentemente do C *, as chamadas são armazenadas neste banco de dados apenas para o mês atual (profundidade suficiente de armazenamento de chamadas para casos de recertificação). Aqui vimos imediatamente o seguinte problema: se você escrever de forma síncrona, perderemos todas as vantagens de C * associadas à inserção rápida, se de forma assíncrona, não há garantia de que todas as chamadas necessárias geralmente atinjam o Oracle. Havia uma vantagem, mas grande: para a exploração, o mesmo familiar desenvolvedor PL / SQL permanece, ou seja, praticamente implementamos o padrão "Fachada". Uma opção alternativa. Implementamos um mecanismo que descarrega chamadas de C *, extrai alguns dados para enriquecimento das tabelas correspondentes no Oracle, junta as amostras recebidas e nos fornece o resultado, que de alguma forma usamos (retrocede, repete, analisa, admira). Contras: o processo é bastante múltiplo e, além disso, não há interface para o pessoal operacional.
Como resultado, ainda decidimos pela segunda opção. O Apache Spark foi utilizado para amostras de diferentes latas. A essência do mecanismo se resumia ao código Java, que, usando as teclas especificadas (assinante, teclas de seção de tempo de chamada), extrai dados de C *, bem como os dados necessários para enriquecer qualquer outro banco de dados. Em seguida, junta-os à memória e exibe o resultado na tabela resultante. Um focinho de trama foi desenhado sobre a faísca e acabou sendo bastante útil.

Ao resolver um problema com a atualização de dados, um teste promocional examinou novamente várias soluções. A transferência através do Sstloader e a opção de dividir o cluster na zona de teste em duas partes, cada uma das quais entra alternadamente no mesmo cluster que o promocional, sendo assim alimentada a partir dele. Ao atualizar o teste, foi planejado alterar seus locais: a parte que trabalhou no teste é limpa e inserida no baile, e a outra começa a trabalhar com os dados separadamente. No entanto, pensando novamente, avaliamos de forma mais racional os dados que devem ser transferidos e percebemos que as chamadas em si são uma entidade inconsistente para testes, geradas rapidamente se necessário, e é o conjunto de dados promocionais que não vale a pena transferir para o teste. Existem vários objetos de armazenamento que valem a pena mover, mas são literalmente algumas tabelas e outras não muito pesadas. Portanto , o Spark novamente nos ajudou como uma solução, com a ajuda da qual escrevemos e começamos a usar ativamente a transferência de dados entre as tabelas de scripts de teste de formatura.
Nossa política de implantação atual nos permite trabalhar sem propinas. Antes do baile, há uma rolagem obrigatória para o teste, onde o erro não é tão caro. Em caso de falha, você sempre pode descartar o espaço de casos e rolar todo o esquema desde o início.
Para garantir a disponibilidade contínua do Cassandra, você precisa do dba e não apenas dele. Todo mundo que trabalha com o aplicativo deve entender onde e como analisar a situação atual e como diagnosticar problemas em tempo hábil. Para isso, usamos ativamente o DataStax OpsCenter (Administração e Monitoramento de Cargas de Trabalho), métricas do sistema Cassandra Driver (número de tempos limite para gravação em C *, número de tempos limite para leitura em C *, latência máxima etc.), monitoramento o trabalho do aplicativo em si, trabalhando com o Kassandra.
Quando pensamos na questão anterior, percebemos onde estaria nosso principal risco. Esses são formulários de exibição de dados que emitem dados de várias solicitações de armazenamento independentes entre si. Dessa forma, podemos obter informações bastante inconsistentes. Mas esse problema seria igualmente relevante se trabalhassemos com apenas um data center. Portanto, a coisa mais razoável aqui é, é claro, executar a função de lote de leitura de dados em um aplicativo de terceiros, o que garantirá que os dados sejam recebidos em um único período de tempo. Quanto à separação da leitura e da escrita em termos de desempenho, ficamos parados com o risco de que, com alguma perda de conexão entre os CDs, possamos obter dois grupos completamente inconsistentes.
Como resultado, no momento paramos no nível de consistência para o registro EACH_QUORUM, para leitura - LOCAL_QUORUM
Breves impressões e conclusões
Para avaliar a solução resultante do ponto de vista do suporte operacional e das perspectivas de desenvolvimento adicional, decidimos pensar em onde mais esse desenvolvimento poderia ser aplicado.
Se estiver em movimento, escore dados para programas como “Pague quando for conveniente” (carregue informações C *, cálculo usando scripts Spark), declarações contábeis com agregação por direções, armazenamento de funções e cálculo de direitos de acesso de usuário usando a matriz de funções.
Como você pode ver, o repertório é amplo e variado. E se escolhermos o campo de apoiadores / oponentes do NoSQL, nos juntaremos aos apoiadores, já que recebemos nossas vantagens e exatamente onde esperávamos.
Até a opção Cassandra pronta para uso permite o dimensionamento horizontal em tempo real, resolvendo sem problemas o problema de aumentar os dados no sistema. Conseguimos colocar em um circuito separado um mecanismo muito carregado para calcular agregados para chamadas e também para separar o esquema e a lógica do aplicativo, eliminando a prática viciosa de escrever trabalhos e objetos personalizados no próprio banco de dados. Tivemos a oportunidade de escolher e configurar, para acelerar, em quais DCs calcularemos e em quais registros de dados, nos asseguramos das quedas de ambos os nós individuais e de todo o DC.
Aplicando nossa arquitetura a novos projetos, e já tendo alguma experiência, gostaria de levar imediatamente em consideração as nuances descritas acima e evitar alguns erros, suavizar alguns cantos afiados que não poderiam ser evitados inicialmente.
Por exemplo, acompanhe as atualizações do Cassandra a tempo , porque alguns problemas que recebemos já eram conhecidos e corrigidos.
Não coloque o próprio banco de dados e o Spark nos mesmos nós (nem os divida estritamente pela quantidade de uso aceitável de recursos), pois o Spark pode consumir mais do que o esperado OP e obteremos rapidamente o problema número 1 da nossa lista.
Bombear a competência de monitoramento e operação na fase de teste do projeto. Inicialmente, leve em consideração o máximo de todos os possíveis consumidores de nossa solução , pois a estrutura do banco de dados dependerá disso.
Torça o circuito resultante várias vezes para possível otimização. Selecione quais campos podem ser serializados. Compreender quais tabelas adicionais podemos fazer para levar em consideração da maneira mais correta e otimizada e, em seguida, retornar as informações necessárias mediante solicitação (por exemplo, supondo que possamos armazenar os mesmos dados em tabelas diferentes, levando em consideração quebras diferentes de acordo com critérios diferentes) podem economizar significativamente tempo do processador para pedidos de leitura).
É uma boa ideia montar imediatamente TTL e limpar dados desatualizados.
Ao descarregar dados do Cassandra, a lógica do aplicativo deve funcionar de acordo com o princípio FETCH, para que nem todas as linhas sejam carregadas na memória por vez, mas selecionadas em lotes.
Antes de transferir o projeto para a solução descrita, é aconselhável verificar a tolerância a falhas do sistema, realizando uma série de testes de falha , como perda de dados em um data center, restauração de dados danificados por um determinado período e redução da rede entre os data centers. Esses testes não apenas permitem avaliar os prós e contras da arquitetura proposta, mas também fornecem boas práticas de aquecimento aos engenheiros que os conduzem, e a habilidade resultante ficará longe de ser supérflua se as falhas do sistema forem reproduzidas no baile.
Se trabalharmos com informações críticas (como dados para cobrança, cálculo da dívida do assinante), você também deve prestar atenção às ferramentas que reduzirão os riscos que surgem devido às características do DBMS. Por exemplo, use o utilitário nodesync (Datastax), tendo desenvolvido uma estratégia ideal para seu uso, para que, por uma questão de consistência, não forme uma carga excessiva no Cassandra e use-o apenas para determinadas tabelas em um determinado período.
Bem, depois de seis meses de vida, com Cassandra? Em geral, não há problemas não resolvidos. Acidentes graves e perda de dados, também não permitimos. Sim, tive que pensar em compensar alguns problemas que não haviam surgido anteriormente, mas no final não ofuscou nossa solução arquitetônica. Se você quer e não tem medo de tentar algo novo, e ao mesmo tempo não quer ficar muito decepcionado, prepare-se para o fato de que nada acontece de graça. Você terá que descobrir, pesquisar na documentação e coletar seu rake individual do que na antiga solução herdada, e nenhuma teoria lhe dirá com antecedência exatamente qual rake está esperando por você.