O caminho errado para ampliar Cassandra DB quando os índices secundários são em lugar de

Cassandra é o meu favorito (não conseguiu) banco de dados por vários motivos: ele não tem um ponto único de falha (SPoF), suporta multi-região, bom para ler e escrever ops, flexível sobre leitura e escrita consistência níveis, escalas linear e não demasiado complexo para gerenciar o dia-a-dia das operações.

como todas as bases de dados, você deve usar Cassandra com base nos seus padrões de acesso aos dados, por isso, se você precisar de uma base de dados flexível para consultas ad-hoc ou adaptável o suficiente para mudanças constantes de modelos de bases de dados, você deve considerar outras opções.

Cassandra é um DB orientado a coluna e é realmente poderoso quando você tem suas consultas de dados já definidas. Datastax, a empresa que suporta Cassandra, recomenda que você deve começar por projetar suas consultas e, em seguida, seu modelo de dados em Cassandra. Apesar do fato de sua estrutura colunar, Cassandra suporta muitas estruturas de dados como um tipo de coluna, como mapas.Cassandra é uma base de dados chave primária, o que significa que seus dados são persistidos e organizados em torno de um conjunto baseado no valor de hash (a chave de partição) da chave primária. Para tabelas que têm mais de um PK, Cassandra considera apenas a primeira parte do PK como sendo a chave de partição. Veja mais sobre as chaves compósitas aqui.

para ser mais claro, vamos voltar a uma das características mais importantes de uma Cassandra DB: é a arquitetura e o fato de que não tem um Espof.

um aglomerado de Cassandra é composto por nós (3 ou mais) e esses nós juntos compõem um anel de nós:

Um cluster do Cassandra composta por seis nós (n6)

Um cluster do Cassandra composta por seis nós (n6)

Um cluster do Cassandra com seis nós (n6)

Cada nó em um Cassandra cluster “de forma independente”, mas diferente de nós pode armazenar os mesmos dados de acordo com o fator de replicação (RF) configuração configurado para o cluster.

para saber onde (que nó) os seus dados persistem, Cassandra usa o valor de hash (token) calculado através de uma função de hash consistente usando a coluna PK de uma dada tabela.

quando você executa uma consulta, o nó coordenador (normalmente o mais próximo de uma das instâncias de sua aplicação) irá procurar por que nós em um anel tem seus dados, dessa forma, se um nó está em baixo por alguma razão, outro nó poderia servir seus dados (RF ≥2). Essa é a magia sobre uma abordagem sem mestre, onde cada nó em um anel é igual em termos de leitura e escrita.

este conceito sobre PK e o Fator de replicação é muito importante para entender como escalar o seu aglomerado de Cassandra quando a sua aplicação está em condições de alta carga.

Índices Secundários

Cassandra tem também o conceito de índices secundários. Em bases de dados relacionais, você pode ter muitos índices em uma dada tabela, o custo de ter um índice secundário está associado com operações de escrita, não para operações de leitura. Em Cassandra isso não é verdade.

índices secundários em Cassandra pode ser útil e tentador quando o seu modelo de dados mudou e você precisa perguntar com base em uma nova coluna.

De qualquer forma, com um índice secundário, você pode executar uma consulta como que:

SELECT * FROM my_table WHERE SECONDARY_INDEX = ‘valor’;

O problema sobre o uso de um Índice Secundário

Imagine o cenário: você está em um Blackfriday/CyberMonday e seu cluster do Cassandra está sofrendo de pico de eventos e que você precisa para adicionar mais nós, para a escala de seu banco de dados, balanceamento melhor seu tráfego e… sobreviver. Bem, certo?

normalmente, é uma situação normal numa aplicação altamente escalável. Mas e se sua aplicação estiver executando consultas usando um índice secundário?Sim, tens razão.Lembras-te quando eu disse que a Cassandra distribui dados num anel usando a chave de partição? Isso já está acontecendo, mas o problema é quando você introduz um índice secundário em sua consulta. Os índices secundários não fazem parte de uma chave de partição, e Cassandra sabe onde seus dados estão vivendo através da chave de partição. Quando você executa uma consulta que usa este tipo de índice, o que Cassandra faz é procurar por cada nó em seu anel tentando satisfazer sua consulta.

cenário real

durante um Blackfriday, nossas aplicações estavam com cargas elevadas. Muitos e muitos clientes que querem se beneficiar dos enormes descontos fornecidos por um evento Blackfriday.

demos uma olhada em nosso APM e toda a análise nos levou à nossa persistência, neste caso uma Cassandra DB. Temos longos períodos de latência, mas não para todos os pedidos, apenas para alguns.Tentando manter as coisas de volta ao estado normal novamente, nossa primeira manobra foi adicionar mais nós ao nosso grupo de Cassandra.

nós adicionamos e ainda estamos sofrendo de problemas de latência. A questão era: por que isso ainda está acontecendo?Estávamos errados. Foi uma conclusão simplista e não nos preocupamos com um detalhe muito importante: este comportamento estava acontecendo não em todos os pedidos, mas em alguns deles.Se você pensou no índice secundário, bingo! Era exactamente esse o problema.

Adicionar nós nunca resolveria o problema, porque o problema não estava relacionado a todas as consultas que chegavam à base de dados, o problema estava em alguns e aqueles eram os reais degradando o desempenho da base de dados. Foi uma coisa de Pareto.

detalhando a questão e como a mitigamos

em um momento antes do evento Blackfriday, precisávamos mudar nosso modelo de dados. Regionalizámos a nossa aplicação e a região do cliente começou a ser uma coisa importante para nós, precisávamos de consultar dados baseados num produto ou região.

olhando para trás e ligando os pontos, poderíamos perceber que éramos muito preciosos sobre a implementação, pois queríamos refletir este novo comportamento não só na camada API (new query param), mas também na maneira que acessamos os dados em Cassandra.E porque éramos tão preciosos? Porque mesmo considerando que nosso tempo de consulta não aumentou muito, nós fizemos a mudança.

que a implementação não só aumentou o nosso tempo de consulta usando um índice secundário, mas também gerou mais problemas de acordo com o aumento da infra-estrutura de Cassandra. À medida que adicionamos mais nós em nosso cluster, significava mais nós para procurar os dados, assim a questão estava aumentando exponencialmente.

para mitigar o problema, o que fizemos foi recuperar o número de nós que tínhamos anteriormente e aumentou o Fator de replicação para a maioria dos nossos nós no aglomerado.

nós também mudamos nosso nível de consistência de leitura para ser menos consistente. Estávamos a usar o quórum e, em vez disso, mudámos para um. Isso nos ajudou a baixar a carga em nós.

à medida que congelamos as nossas aplicações dias antes do evento, sabíamos que não tínhamos novos dados (operações de escrita) e os dados seriam consistentes no seu estado actual.

os dias seguintes e a solução do modelo DB

como parte da solução final, nós precisávamos (re)pensar sobre o nosso modelo de banco de dados e retroceder as mudanças que fizemos como um caminho de mitigação durante o evento.

antes do evento estávamos usando o ID do produto (PID)como chave de partição, o que foi uma boa decisão, uma vez que o PID tem bons atributos para ser um PK devido à sua natureza sobre ser um número sequencial (alta cardinalidade), e, dessa forma, espalhar os dados uniformemente em torno do conjunto.

sobre o novo campo “Região”, nós alavancamos Cassandra coleta de dados tipo e usou um mapa para cada região como uma coluna em nossa tabela de produtos.Os índices secundários são sempre uma má ideia?

a resposta curta é não.

explicando um pouco melhor, há dois tipos de índices em Cassandra: índices locais e globais.

um índice local como o nome diz é um tipo de índice que existe apenas localmente, que significa em um nó. Quando você cria um índice secundário, Cassandra cria uma nova tabela (escondida) onde o secundário se torna uma chave primária nesta tabela. A visibilidade desta nova tabela é em termos de um nó, não um anel (cluster). É o caso dos índices secundários.

por outro lado, um índice global tem visibilidade através da sua chave de partição, por isso a Cassandra sabe onde os dados estão num anel através dessa chave de partição.

índices secundários podem ser uma alternativa, quando você tem em uma consulta tanto: índices primários e secundários. Nesse caso, Cassandra sabe onde seus dados residem (que nó) através da chave de partição e, em seguida, olha para cima a tabela local no nó que se refere aos índices secundários (locais).

há também algumas outras nuances sobre índices secundários que são muito bem explicados aqui, mas a melhor prática é evitá-los, desnormalizando seu modelo de dados.

Deixe uma resposta

O seu endereço de email não será publicado.