Primeiro, as notícias. Acabei de postar um candidato a lançamento do spymemcached 2.6. O atual cliente com reconhecimento de vbucket do Membase em versão preliminar também se baseia nesse código.
Portanto O que há de novo na versão 2.6? Há uma série de aprimoramentos no desempenho, no transcodificador e no tratamento do tempo limite, mas a grande mudança está no tratamento do tempo limite.
Houve vários comentários e postagens sobre o problema número 136 do spymemcached. A partir dos relatórios de erros no spy 136, várias pessoas estão executando aplicativos e vendo uma RuntimeException do MemcachedClient get(). Essa é uma chamada de método muito simples para o consumidor e, portanto, é muito comum, mas há um trabalho complexo acontecendo por baixo para otimizar a forma como o spymemcached é usado. Permita-me explicar um pouco mais.
Tecnicamente falando, nada no spymemcached é feito de forma síncrona. Quando você faz uma chamada de método get() que parece ser síncrona, usamos as APIs de simultaneidade do Java para fazer com que o get seja aparentemente síncrono, executando a operação por meio das mesmas filas de gravação assíncronas para uma determinada conexão, usando uma trava de contagem regressiva com um tempo limite padrão para permitir que a operação flua pelo sistema, seja atendida e respondida muito rapidamente. Na realidade, a maioria dessas operações é realizada em uma questão de alguns milissegundos a um microssegundo.
Dito isso, ainda há algumas situações que podem ocorrer durante a execução
a) como um aplicativo de espaço do usuário
b) em um sistema ocupado
c) em uma rede ocupada ou instável
d) em uma JVM, devido a atividades de coleta de lixo ou JIT
Muitos deles podem ser controlados em grande parte com algum esforço, mas não podem ser totalmente eliminados. Isso significa que o código deve estar sempre pronto para receber timeouts ocasionais. De forma equivalente, o spymemcached deve ter como objetivo recuperar-se o mais rápido possível da condição de timeout.
Dito isso, quando eu estava investigando a questão do espião 136, algumas coisas surgiram.
Mike Wiederhold observou que às vezes via uma retransmissão TCP. Pesquisando mais sobre o assunto, ele descobriu que o tempo padrão antes de uma retransmissão é de 1 segundo. Bem, com nosso tempo limite padrão na trava de 1 segundo, isso significa que qualquer retransmissão TCP causaria um tempo limite. Com as implementações virtualizadas e na nuvem atualmente, algumas das quais são conhecidas por estarem em redes com excesso de assinaturas, é provável que isso ocorra ocasionalmente. A solução simples para isso é aumentar o tempo limite padrão. Não foi algo que fiz de ânimo leve, mas acho que é a coisa certa a fazer.
Alguns de nossos testes de carga com Membase acertar isto. De teste de memória (um testador de estresse de brinquedo, não um cliente real) Sei que o Membase lida facilmente com dezenas de milhares a centenas de milhares de operações por segundo, dependendo dos sistemas em uso.
Comecei a procurar coisas que impedissem a recuperação, já que muitos dos relatórios de erros apontavam para uma falha na recuperação. Acontece que o mecanismo que implementa o tempo limite síncrono não faz nada para impedir que esse item seja gravado no objeto MemcachedNode para o qual foi designado.
Em outras palavras, nosso thread que lida com o nó não estava prestando atenção suficiente ao tempo de uma determinada operação.
Pensando nisso em termos de apenas uma operação em uma circunstância, se o buffer para envio de dados para a rede estiver cheio porque está muito ocupado ou porque há uma interrupção momentânea, não há nada que impeça outros threads de acumular mais operações nesse MemcachedNode. Essas operações atingirão o tempo limite no thread de chamada, mas ainda serão enviadas pela rede. Isso estenderá o efeito dessa interrupção momentânea até que o acúmulo de coisas que não serão usadas seja resolvido. Em um servidor realmente saturado, talvez ele nunca se recupere.
Com as alterações de código no candidato à versão 2.6, agora nos protegemos até mesmo contra o envio de uma operação que tenha atingido o tempo limite. Já recebi um bom feedback e isso ajudou a limpar as coisas para os testes do Membase, mas com projetos tão amplamente distribuídos como o spymemcached, o memcached e o Membase, é bom receber algum feedback do mundo real. Se você estiver usando o spymemcached existente, dê uma chance e me avise.