BT
x Por favor preencha a pesquisa do InfoQ !

LMAX: 6 milhões de transações por segundo com uma única thread

por Julio Faerman em 02 Ago 2011 |

Martin Fowler, autor de diversos livros essenciais sobre arquitetura e desenvolvimento de sistemas corporativos, publicou recentemente em seu blog uma descrição detalhada da arquitetura da plataforma financeira LMAX. Também apresentou como foi desenvolvida a plataforma de modo a atingir uma impressionante taxa de 6 milhões de transações por segundo, usando apenas uma thread, usando hardware comum:

A medição de 6 milhões de transações por segundo foi realizada em um servidor Dell Nehalem quad core dual socket de 3Ghz com 32 GB RAM.

A plataforma financeira LMAX foi apresentada em 2010, nos QCon de Londres e de São Francisco, este último com gravação do InfoQ.  As apresentações tiveram grande repercussão em sites e blogs sobre arquitetura de sistemas. 

As plataformas financeiras em geral têm requisitos complexos, mas esta tinha um novo complicador. Ao invés de ser vendida para poucos clientes corporativos, seria oferecida a clientes no varejo, com uma expectativa de altíssimo volume de transações por segundo.

Tendo lidado com diversos problemas de desempenho no desenvolvimento de um sistema de apostas esportivas, a equipe do LMAX decidiu explorar arquiteturas alternativas às soluções tradicionais envolvendo coordenação de sessões com bancos de dados relacionais. 

Paralelismo e filas

O primeiro protótipo da arquitetura, com foco em paralelismo, foi construído usando o modelo de atores. Neste modelo ao invés de se controlar a concorrência com as primitivas tradicionais (Mutex, Semaforo etc.), são utilizados objetos de alto nível como atores e mensagens. 

Apesar de ter sua origem na década de 70, o modelo de atores tem ganhado popularidade apenas recentemente, devido a dificuldades apresentadas no controle de concorrência entre múltiplos núcleos de processamento, como os encontrados nas CPUs modernas. No entanto, o modelo já é cidadão de primeira classe em linguagens como Scala e Erlang.

A equipe do LMAX foi até a raiz do problema na avaliação do desempenho do protótipo e observou que o gerenciamento de filas pelos atores é ineficiente do ponto de vista de uso do cache interno do processador, cujo acesso é muito mais rápido que o acesso à RAM. Fowler comenta:

Para colocar alguma informação em uma fila, é preciso (obviamente) escrever naquela fila. De modo similar, para retirar dados da fila, deve-se escrever na fila para realizar a remoção. Há portanto uma contenção de escrita: mais que um cliente pode precisar escrever na mesma estrutura de dados. Para lidar com esse tipo de contenção em filas, normalmente utilizam-se travas (locks). Mas se uma trava é usada, isso pode causar uma troca de contexto com o kernel e quando isso ocorre, o processador provavelmente perderá os dados em seus caches. 

A conclusão foi que, para otimização do cache, é necessário que apenas um núcleo do processador escreva em uma dada região de memória. Devido a esta restrição, surgiram duas decisões importantes. A primeira foi criar uma nova estrutura para controle de concorrência sem travas, batizada de "Disruptor". A segunda foi investigar o quão rápido pode ser o processamento da lógica de negócio em uma única thread, se não for usado o controle de concorrência.

Disruptor

A estrutura de controle Disruptor funciona como uma fila circular para múltiplos clientes. Nessa fila, tudo o que é adicionado pelos produtores é disponibilizado paralelamente aos consumidores. São utilizados apenas contadores simples, ao invés de travas, para garantir que o limites de leitura não sejam ultrapassados. 

No caso do LMAX, todo evento produzido é processado por três consumidores antes de chegar à lógica de negócio (veja a figura): o journaler, o replicator e o unmarshaller:

  • O papel do journaler é persistir todos os eventos. Para isso, não é usado um banco de dados, e sim apenas arquivos sequenciais, cujo acesso no disco é muito eficiente. 
  • O replicator retransmite os eventos para nós redundantes, que são usados para alta disponibilidade. 
  • O unmarshaller desserializa os eventos para objetos Java, que serão consumidos pela lógica de negócio. 

O artigo de Fowler descreve em mais detalhes os componentes e suas possíveis variações. A empresa LMAX (que deu nome à arquitetura) disponibilizou o Disruptor como um framework sob licença Apache no Google Code, mostrando inovação considerável em um mercado que é geralmente "segredista".

Dave Farley, co-autor do livro Continuous Delivery e membro da empresa LMAX, apresenta em seu blog mais detalhes sobre a lógica de negócio, que é implementada em interfaces e objetos comuns, possibilitando o uso de modelos orientados a objetos ricos e flexíveis. Farley conclui:

Orgulho-me da nossa infraestrutura tecnológica, mas para mim o ganho real não é o grau de sofisticação da arquitetura, mas sim o quanto ela libertou a equipe para se concentrar nos problemas de negócio que somos pagos pra resolver.

Thread única

Com a arquitetura descrita, o processamento da lógica de negócio pode ser executado em apenas uma thread, pois os Disruptors gerenciam I/O e concorrência. Os Disruptors e o cache "aquecido" – que é acessado o máximo possível antes de se se buscar na memória principal – foram fatores essenciais para se atingir o altíssimo desempenho medido.

Fowler ressalta ainda o quanto os testes de desempenho foram importantes para se chegar a tais resultados, mas alerta:

Criar código de testes de alto desempenho pode ser tão difícil quanto escrever código para produção. É comum obter resultados falsos, devido aos testes não serem tão rápidos quanto o componente sob medição.

Aplicações

Na sua conclusão, Martin Fowler apresenta considerações importantes sobre como podemos aproveitar a arquitetura LMAX em nossos sistemas. Apesar de o cenário da LMAX ser um tanto particular e extremo, as decisões e componentes utilizados são comuns em arquiteturas modernas. 

Manter os dados em memória RAM e usar o disco apenas para restauração e backup, por exemplo, é uma estratégia comum em produtos de grid e noSQL, como Infinispan, Coherence, Prevayler, entre outros. A maneira como os eventos são utilizados é semelhante ao sistema CQRS, apesar de este não ser usado explicitamente pelo LMAX. (Para uma introdução ao CQRS, veja o artigo de Fowler sobre o assunto e essa palestra de Pedro Teixeira, realizada no ultimo QCon São Paulo.) 

Mesmo que a sua arquitetura seja menos estrita e use muito menos recursos, os dilemas e decisões enfrentados pela LMAX são certamente instrutivos e reaproveitáveis em diversas situações.

Avalie esse artigo

Relevância
Estilo/Redação

Olá visitante

Você precisa cadastrar-se no InfoQ Brasil ou para enviar comentários. Há muitas vantagens em se cadastrar.

Obtenha o máximo da experiência do InfoQ Brasil.

Dê sua opinião

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

Leandro by leandro moreira

Muito bom artigo, talvez substituir : cache "aquecido" por cache recente.

Thread única? by Fernando Lozano

Perdoem a crítica, mas o título ficou meio enganador, pois a arquitetura LMAX descrita pelo artigo do Martin Fowler NÃO USA uma ÚNICA thread: os disruptors de entrada e de saída tem vários threads independentes do thread que roda o business processor. O que ela demonstra é uma maneira de se trabalhar com múltiplos threads, algo inevitável em qualquer sistema de servidor, com o mínimo de lock e máximo aproveitamento dos caches e consquentemente das CPUs.

Além disso, a arquiteura exige que existam outras instâncias do conjunto disruptors + business processors rodando em paralelo, para que não haja perda de serviço em caso de problemas com uma das instâncias, o que obrigaria a uma potencialmente demorada re-execução de toda a fila de eventos.

A equipe do LMAX também gera snapshots diários de cada instância e reinicia cada uma para manter um nível de serviço alto. TODO o estado do sistema está contido no último smapshot + fila de eventos posteriores, não existe nenhum outro armazenamento persistente nesta arquitetura, em especial não existe um BD.

O LMAX é uma arquitetura muito interessante e de sucesso comprovado, mas não pensem que é trivial trabalhar hoje em dia com qualquer arquitetura diferente do modelo transacional baseado em bancos de dados relacionais. ;-)

Re: Thread única? by Julio Faerman

Não foi afirmado que o sistema usa uma única thread, mas que uma única thread processa 6M transações (logica de negócio) por segundo.

Re: Leandro by Julio Faerman

Obrigado leandro, não conhecia o termo. Vício do inglês,

Re: Thread única? by Fernando Lozano

Seria 6M transações em uma única thread se pudéssemos considerar apenas a execução do business processor. Mas as transações do LMAX envolvem também os disruptors de entrada e de saída. Não podemos considerar uma transação completa como envolvendo apenas o business processor porque sem os disruptors (e as filas de eventos associadas) não tem como chegar trabalho nos business processors nem é possível assegurar a integridade das transações.

Eu concordo que o artigo original não deixa claro se são 6M transações considerando apenas o business processor ou se considerando a arquitetura como um todo, mas eu não vejo como poderia ser diferente (de considerar tudo).

Re: Thread única? by Fernando Lozano

Pense bem, 6 MILHÕES de tps envolvendo só de operações sobre memória, sem nenhuma operação de E/S de disco nem de rede, não é nada de mais em uma CPU x86 moderna, que é capaz de executar dezenas de BILHÕES de instruções por segundo. Este valor só se torna significativo se envolver alguma E/S e portanto os disruptores e seus respectivos threads.

Excelente.... by Natanael Fonseca

Parabéns pelo artigo !

Re: Thread única? by José Filipe Neis

Considerando que na verdade são passos separados, acho que sim, poderia ser considerada como uma transação lógica, apesar de não representar a transação de negócio.

De qualquer maneira, não acho que o número de tps é o ponto mais importante do artigo. O throughput dos caras vai ser algo assustador de qualquer maneira. A grande sacada, a meu ver, está numa maneira melhor de trabalhar com os locks. Como o Fernando colocou no comentário anterior, não é simples, mas cenários de alto volume (como o do LMAX) tem sérias dificuldades pra rodar com o tradicional modelo de BD relacional (na verdade, o volume não precisa nem ser tão alto assim :)).

Re: Thread única? by Julio Faerman

O problema é que como o I/O é assíncrono, fica muito difil medir isso. As transações "do negócio" são um lugar bom pra colocar a medição, mas sim, não leva em conta o sistema como um todo.

Re: Excelente.... by Julio Faerman

Obrigado!

Re: Thread única? by Julio Faerman

Com certeza o desempenho não é o mais importante, mas é o que chama mais atenção :)

Muito bom padô! by Jairo Rodrigues

Obrigado por essa leitura de qualidade. Animará os acadêmicos à darem mais atenção as matérias fundamentais da computação (estrutura de dados, arq de computadores, SO, sistemas distribuidos, etc).

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

12 Dê sua opinião
Feedback geral
Bugs
Publicidade
Editorial
Marketing
InfoQ Brasil e todo o seu conteúdo: todos os direitos reservados. © 2006-2016 C4Media Inc.
Política de privacidade
BT

Percebemos que você está utilizando um bloqueador de propagandas

Nós entendemos porquê utilizar um bloqueador de propagandas. No entanto, nós precisamos da sua ajuda para manter o InfoQ gratuito. O InfoQ não compartilhará seus dados com nenhum terceiro sem que você autorize. Procuramos trabalhar com anúncios de empresas e produtos que sejam relevantes para nossos leitores. Por favor, considere adicionar o InfoQ como uma exceção no seu bloqueador de propagandas.