EVOLUINDO SISTEMAS DISTRIBUÍDOS 6 ANOS DE NoSQL DAS TRINCHEIRAS Eiti Kimura Fernando Gonçalves MAR 2016
QUEM SOMOS NÓS?
Eiti Kimura • Arquiteto de software e Coordenador de TI na Movile • Apache Cassandra Developer 1.1 Certified (2013) • Apache Cassandra MVP (2014 e 2015) • Apache Cassandra Contributor (2015) • Cassandra Summit Speaker (2014 e 2015) eitikimura
Fernando Gonçalves • Desenvolvedor na Movile • Estudante de Ciência da Computação na Unicamp fhsgoncalves
Sumário ● INTRODUÇÃO ● CASOS DE USO ○ Plataforma de Tarifação e controle de assinaturas ○ Registro de dados de apps e envio de notificações push ● CONCLUSÃO ○ Problemas encontrados, lições aprendidas.
LÍDER EM DESENVOLVIMENTO DE PLATAFORMAS DE COMÉRCIO E CONTEÚDO MÓVEL NA AMÉRICA LATINA
A Movile é a empresa por trás das apps que fazem sua vida mais fácil!
O Melhor conteúdo para Crianças
Líder em delivery de comida no Brasil
80% A empresa registrou um crescimento anual de 80% nos últimos 6 anos.
INTRODUÇÃO
Apache Cassandra é um banco de dados não relacional (NoSQL) orientado a colunas, distribuído, escalável, de alta disponibilidade, tolerante a falhas. [The Definitive Guide, Eben Hewitt, 2010]
Controle de Assinaturas e Tarifações • Composto de uma API de serviço; • Responsável pelo gerenciamento de assinaturas de usuários; • Cobrança dos usuários nas operadoras; O serviço não pode parar de forma alguma e deve ser muito rápido.
A plataforma em números 105M de assinaturas 76,3M de usuários únicos 145M de transações ao dia
Linha e evolutiva da Plataforma (SBS) Cluster da versão 1.0 para 1.2 Expansão do cluster Remodelagem de para 10 nós dados com 4 nós no cluster 2008 2009 2014 2011 2013 2015 Banco relacional puro Cluster upgrade Expansão de 4 da versão para 6 nós Apache Cassandra 0.7 para 1.0 (v0.5) Novo indice de dados para assinaturas
ARQUITETURA V1 API API API API API DB Engine Engine Engine
Desvantagens da Arquitetura • Ponto único de falha • Tempos de resposta lentos • Downtimes frequentes • Caro e difícil para escalar Escalar uma plataforma sem escalar as dependências externas resulta em falha.
ARQUITETURA V2 Regular SQL Queries API API Engine DB Engine API API
Benefícios da nova solução Problemas de desempenho: OK; ❏ Problemas de disponibilidade: OK; ❏ Ponto único de falha: Parcialmente Resolvido; ❏ Aumento significante no throughput de leitura e escrita; ❏
ARQUITETURA V2 Ponto Fraco SQL Queries Engine DB Engine
QUAIS SÃO OS PROBLEMAS?
Problemas na Arquitetura Consultas ao banco relacional podem consumir tempo Com o aumento da concorrência ocorre degradação de desempenho nas operações com o banco de dados relacional. Continua com impacto na escalabilidade
Proposta de Evolução Extrair dados do Apache Cassandra ao invés do banco relacional; ➔ Sem ponto único de falha; ➔ Melhoria de desempenho, porém mais trabalho filtrando a informação; ➔
BACKEND SERVICE
KIWI - BACKEND SERVICE Foco em smartphones Engajamento de usuário Notificações por Push Analytics Alta performance Alta disponibilidade
Alguns dados do Kiwi em 2015 Total de notificações push enviadas Análise de dados 450M Total de instalações de apps 40M Total de configurações de usuários 20M
NOSSO DESAFIO Notificação por push ANDROID iOS
ARQUITETURA V1 SQL
ARQUITETURA V2 Consumidor Amazon SQS SQL DynamoDB
ARQUITETURA V2 Push Notification Publicador #1 APNS Publicador #2 SQL Publicador #3 GCM Limite de vazão alcançado
Problemas na Arquitetura Vazão de leitura atingida SQL Vazão de leitura muito baixa DynamoDB $$ Custos altos
Lentidão no envio de Notificações por Push
ARQUITETURA V3 Push Notification Publicador #1 APNS Publicador #2 Publicador #3 Cassandra v2.1 GCM
Mudanças no modelo ➔ Amazon DynamoDB Objeto serializado com Avro ◆ Poucas colunas ◆ ➔ Apache Cassandra Objeto explodido ◆ Mais de 80 colunas sem serialização ◆
Resultados PRÉ MIGRAÇÃO DynamoDB + SQL Custo total da solução US$ 10.825,00/mês Vazão de leitura = ~ 12.000/s
Resultados PÓS MIGRAÇÃO (8 nós c3.2xlarge) Custo total da nova solução US$ 2.580,00/mês 77% DE ECONOMIA 17x Vazão Vazão de leitura = ~ 200.000/s
Lições Aprendidas O que deu errado
COLLECTIONS
Introdução a collections map<type1, type2> http://bit.ly/cassandra-tombstones set<type1> Problema com tombstones list<type1>
Introdução a atualização de dados no Cassandra sstables tombstones repair
Número de sstables antes do repair # de arquivos sstable Horário
Durante o repair # de arquivos sstable Horário
Alteração do tipo de dados cqlsh:test> CREATE TABLE teste_com_mapa( cqlsh:test> CREATE TABLE teste_sem_mapa( ... id int, ... id int, ... mapa map<text, text> , ... mapa blob, ... PRIMARY KEY (id) ... PRIMARY KEY (id) ); ); Usando blob Usando Collections
Repair usando blob ao invés de map # de arquivos sstable Horário
MANUTENÇÃO DO CLUSTER
Sobre adição de nós (Cassandra v2.1) PARA NÃO PERDER DADOS: 1. Não adicionar em paralelo (ESPERAR BALANCEAR) 2. Rodar repair a cada adição 3. Consulte o procedimento no manual.
Quando esquecemos de rodar repair Tempo de resposta para leitura (ms) Horário
Lembre-se sempre... AUTOMATIZAR MONITORAR
HINTED HANDOFF
Hinted Handoff http://bit.ly/cassandra-hinted-handoff
Hinted Handoff CASSANDRA-10233 - IndexOutOfBoundsException in HintedHandOffManager CASSANDRA-10485 - Missing host ID on hinted handoff write ERROR [HintedHandoff:1] 2015-08-31 18:31:55,600 CassandraDaemon.java:182 - Exception in thread Thread [HintedHandoff:1,1,main] java.lang.IndexOutOfBoundsException: null at java.nio.Buffer.checkIndex(Buffer.java:538) ~[na:1.7.0_79] at java.nio.HeapByteBuffer.getLong(HeapByteBuffer.java:410) ~[na:1.7.0_79] at org.apache.cassandra.utils.UUIDGen.getUUID(UUIDGen.java:106) ~[apache-cassandra-2.2.0.jar:2.2.0] at org.apache.cassandra.db.HintedHandOffManager.scheduleAllDeliveries(HintedHandOffManager.java:515) ~[apache-cassandra-2.2.0.jar:2.2.0] at org.apache.cassandra.db.HintedHandOffManager.access$000(HintedHandOffManager.java:88) ~[apache- cassandra-2.2.0.jar:2.2.0] at org.apache.cassandra.db.HintedHandOffManager$1.run(HintedHandOffManager.java:168) ~[apache- cassandra-2.2.0.jar:2.2.0] at org.apache.cassandra.concurrent.DebuggableScheduledThreadPoolExecutor$UncomplainingRunnable.run (DebuggableScheduledThreadPoolExecutor.java:118) ~[apache-cassandra-2.2.0.jar:2.2.0] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_79] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) [na:1.7.0_79] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThread)
Hinted Handoff cqlsh:system> SELECT target_id,hint_id,message_version FROM hints LIMIT 5; target_id | hint_id | msg_version --------------------------------------+--------------------------------------+------------ | 2f5e0320-62d3-11e5-877e-77558ae77cc8 | 8 72888e32-dae5-41cd-a033-3c5871a3e045 | fad152f0-662a-11e5-89ed-77558ae77cc8 | 8 72888e32-dae5-41cd-a033-3c5871a3e045 | fad152f1-662a-11e5-89ed-77558ae77ac9 | 8 72888e32-dae5-41cd-a033-3c5871a3e045 | fb69e970-662a-11e5-89ed-77558ae77cd5 | 8 52868e32-dae5-41cd-b033-2b5871a3e032 | fb69e971-662a-11e5-89ed-77558ae77zc6 | 8 (5 rows)
Hinted Handoff - POSSÍVEIS CAUSAS - # enable assertions. disabling this in production will give a modest performance benefit (around 5%). JVM_OPTS="$JVM_OPTS -ea" Problemas de bootstrap na adição de novos nós ao cluster
Hinted Handoff Correção de Emergência Executar operação de 'truncate' na tabela de hints Atualizar para versão >= 2.1.11 A versão 3.x não foi afetada pelo problema, pois a nova StorageEngine armazena os hints em arquivos e não mais na estrutura de uma tabela do Cassandra.
ULTRA WIDE ROW (ANTI-PATTERN)
Estrutura de dados CREATE TABLE idx_config ( utilizada (CQL) conf_id int, ref_id varchar, Chave primária subs_key varchar, data varchar, last_charge timestamp, expiration timestamp, last_charge_at timestamp, Dados da assinatura status_id int, desnormalizados origin_id int, msg_balance int, master boolean, enabled boolean, PRIMARY KEY ((conf_id, ref_id), subs_key) ); Chave de partição
Limites Lógicos
Recommend
More recommend