BT
x A sua opinião é importante! Por favor preencha a pesquisa do InfoQ sobre os seus hábitos de leitura!

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.

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

Conteúdo educacional

Feedback geral
Bugs
Publicidade
Editorial
InfoQ Brasil e todo o seu conteúdo: todos os direitos reservados. © 2006-2014 C4Media Inc.
Política de privacidade
BT