[datafest-2017] apache cassandra para sistemas de alto desempenho
TRANSCRIPT
• Coordenador de TI e Arquiteto de Software 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)• Strata Hadoop World Singapore Speaker (2016)• Spark Summit Europe Speaker (2017)
Eiti Kimura
eitikimura
Sumário
● INTRODUÇÃO○ Definição e Funcionamento Apache Cassandra
● CASO DE USO○ Aplicação prática do Apache Cassandra em sistemas de alto
desempenho
● CONCLUSÃO○ Problemas encontrados, lições aprendidas.
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]
Descentralizado / Distribuído
Tolerante a falhas, sem ponto único central de controle, não existe um nó “master”
Utiliza o Protocolo Peer-to-Peer
Escalabilidade Elástica
A taxa de transferência (throughput) de operações de leitura e escrita aumenta linearmente a medida que novas máquinas são adicionadas.
http://bit.ly/netflix-cassandra
Consistência Eventual Propagada
DEF:
eventually = after some timeeventualmente = talvez, possivelmente
Linguagem de manipulação de dados
Oferece um modelo muito próximo ao SQL no tocante ao armazenamento de dados em forma de tabelas que contém linhas e colunas.
CQLCassandra Query Language
Inserção de dados com Thrift (< 0.8) - Part 1
TTransport tr = new TSocket(HOST, PORT); TFramedTransport tf = new TFramedTransport(tr); TProtocol proto = new TBinaryProtocol(tf);
Cassandra.Client client = new Cassandra.Client(proto); tf.open();
client.set_keyspace("Keyspace1"); //dbnameString cfName = "Clients"; // table namebyte[] userIDKey = "1".getBytes(); // pk
//this is a row keyClock clock = new Clock(System.currentTimeMillis());
java code snippet
Inserção de dados com Thrift (< 0.8) - Part 2
ColumnParent cp = new ColumnParent(cfName);
//insert the name column client.insert(userIDKey, cp,
new Column("name".getBytes(UTF8), "Eiti Kimura".getBytes(), clock), CL);
//insert the Age column client.insert(userIDKey, cp,
new Column("age".getBytes(UTF8), "35".getBytes(), clock), CL);
java code snippet
Inserção de dados com CQL
INSERT INTO "Keyspace1"."Standard1" (id, name, age) VALUES ('1', 'Eiti Kimura', '35');
cql code snippet
Acessar o shell do Apache Cassandra:
# cd apache-cassandra/bin
# ./cqlsh
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.
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.
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;
Alteração do tipo de dados
Usando Collections Usando blob
cqlsh:test> CREATE TABLE teste_com_mapa( ... id int, ... mapa map<text, text> , ... PRIMARY KEY (id) );
cqlsh:test> CREATE TABLE teste_sem_mapa( ... id int, ... mapa blob, ... PRIMARY KEY (id) );
http://bit.ly/cassandra-tombstones
Hinted Handoff
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]
CASSANDRA-10233 - IndexOutOfBoundsException in HintedHandOffManagerCASSANDRA-10485 - Missing host ID on hinted handoff write
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
# enable assertions. disabling this in production will give a modest performance benefit (around 5%).
JVM_OPTS="$JVM_OPTS -ea"
Não faça isso
Hinted Handoff
Correção de Emergência
Executar operação de 'truncate' na tabela de hintsAtualizar 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.
Cassandra 1.2
ERROR [CompactionExecutor:6523] 2015-10-09 12:33:23,551CassandraDaemon.java (line 191) Exception in threadThread[CompactionExecutor:6523,1,main]java.lang.AssertionError: incorrect row data size 3758096384 written to/movile/cassandra-data/SBSPlatform/idx_config/SBSPlatform-idx_config-tmp-ic-715-Data.db; at org.apache.cassandra.io.sstable.SSTableWriter.append(SSTableWriter.java:162) at org.apache.cassandra.db.compaction.CompactionTask.runWith(CompactionTask.java:162) at org.apache.cassandra.io.util.DiskAwareRunnable.runMayThrow(DiskAwareRunnable.java:48) at org.apache.cassandra.utils.WrappedRunnable.run(WrappedRunnable.java:28)
+3GB em 1 linha
Limites Físicos de Partição
Cassandra 2.0 ou Anterior
● ~ 100MB ou menos / partição;● ~ 100k valores (colunas na linha).
Cassandra 2.1+
● Algumas centenas de MB por partição;● Milhões de valores (colunas por partição).
❏ Usar intensamente Collections do Cassandra;
❏ Adição de nós em paralelo;
❏ Problemas no HintedHandOff;
❏ Client Side Joins (anti-pattern)
❏ Copiar modelo relacional (anti-pattern);
❏ Não verificar limites da ferramenta (lógicos e físicos).
O que NÃO fazer