Um pool de daemons do memcache pode ser usado para compartilhar sessões com mais eficiência?

25

Estamos passando de uma configuração de 1 servidor para uma configuração de dois servidores e preciso começar a compartilhar sessões PHP entre as duas máquinas com balanceamento de carga. Já instalamos o memcached ( e iniciamos ) e, por isso, fiquei agradavelmente surpreso ao concluir as sessões de compartilhamento entre os novos servidores alterando apenas três linhas no php.iniarquivo ( session.save_handler e session.save_path ):

Eu substituí:

session.save_handler = files

com:

session.save_handler = memcache

Em seguida, no servidor da web principal, defino o session.save_pathponto para localhost:

session.save_path="tcp://localhost:11211"

e no servidor escravo, defino o session.save_pathponto para o mestre:

session.save_path="tcp://192.168.0.1:11211"

Trabalho feito, eu testei e funciona. Mas...

Obviamente, usar o memcache significa que as sessões estão na RAM e serão perdidas se uma máquina for reinicializada ou o daemon do memcache travar - estou um pouco preocupado com isso, mas estou um pouco mais preocupado com o tráfego de rede entre os dois servidores da web (especialmente como aumentamos) porque sempre que alguém é balanceado por carga para o servidor escravo, suas sessões serão buscadas na rede a partir do servidor web mestre. Eu queria saber se eu poderia definir dois save_pathspara que as máquinas olhem em seu próprio armazenamento de sessão antes de usar a rede. Por exemplo:

Mestre:

session.save_path="tcp://localhost:11211, tcp://192.168.0.2:11211"

Escravo:

session.save_path="tcp://localhost:11211, tcp://192.168.0.1:11211"

Isso compartilharia sessões com êxito entre os servidores e ajudaria no desempenho? ou seja, economize tráfego de rede 50% do tempo. Ou essa técnica é apenas para failovers (por exemplo, quando um daemon do memcache está inacessível)?

Nota : Na verdade, não estou perguntando especificamente sobre a replicação do memcache - mais sobre se o cliente PHP do memcache pode entrar dentro de cada daemon do memcache em um pool, retornar uma sessão se encontrar um e criar apenas uma nova sessão se não encontrar um em todas as lojas. Enquanto escrevo isso, estou pensando em pedir um pouco demais ao PHP, lol ...

Suponha : sem sessões complicadas, balanceamento de carga round-robin, servidores LAMP.

Tom
fonte
11
A documentação do Memcache não recomenda o uso do Memcache para armazenamento de sessão. Veja code.google.com/p/memcached/wiki/… !

Respostas:

37

Isenção de responsabilidade: Você ficaria louco de me ouvir sem fazer uma tonelada de testes E obter uma segunda opinião de alguém qualificado - sou novo neste jogo .

A ideia de melhoria de eficiência proposta nesta pergunta não funcionará. O principal erro que cometi foi pensar que a ordem em que os armazenamentos em cache são definidos no pool determina algum tipo de prioridade. Este não é o caso . Quando você define um conjunto de daemons memached (por exemplo, usando session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"), não pode saber qual loja será usada. Os dados são distribuídos uniformemente, o que significa que um item pode ser armazenado no primeiro ou pode ser o último (ou pode ser o último se o cliente memcache estiver configurado para replicar - observe que é o cliente que manipula a replicação, o servidor memcached não faça isso sozinho). De qualquer forma, isso significa que o uso do host local como o primeiro no pool não melhorará o desempenho - há 50% de chance de atingir qualquer loja.

Depois de fazer um pouco de teste e pesquisa, concluí que você PODE compartilhar sessões entre servidores usando o memcache, MAS provavelmente não deseja - não parece ser popular porque não é tão dimensionável quanto o uso de um compartilhamento. banco de dados nele não é tão robusto. Gostaria de receber feedback sobre isso para que eu possa aprender mais ...

Ignore o seguinte, a menos que você tenha um aplicativo PHP:


Dica 1: se você deseja compartilhar sessões entre 2 servidores usando o memcache:

Certifique-se de responder Sim para " Ativar suporte ao manipulador de sessão do memcache? " Ao instalar o cliente memcache do PHP e adicione o seguinte no seu /etc/php.d/memcache.iniarquivo:

session.save_handler = memcache

No servidor da web 1 (IP: 192.168.0.1):

session.save_path="tcp://192.168.0.1:11211"

No servidor da web 2 (IP: 192.168.0.2):

session.save_path="tcp://192.168.0.1:11211"

Dica 2: se você deseja compartilhar sessões entre 2 servidores usando o memcache E possuir suporte a failover:

Adicione o seguinte ao seu /etc/php.d/memcache.iniarquivo:

memcache.hash_strategy = consistent
memcache.allow_failover = 1

No servidor da web 1 (IP: 192.168.0.1):

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

No servidor da web 2 (IP: 192.168.0.2):

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

Notas:

  • Isso destaca outro erro que cometi na pergunta original - eu não estava usando um idêntico session.save_pathem todos os servidores.
  • Nesse caso, "failover" significa que, se um daemon do memcache falhar, o cliente do memcache do PHP começará a usar o outro. ou seja, qualquer pessoa que teve sua sessão na loja que falhou será desconectada. Não é failover transparente.

Dica 3: se você deseja compartilhar sessões usando o memcache E ter suporte transparente a failover:

Igual à dica 2, exceto que você precisa adicionar o seguinte ao seu /etc/php.d/memcache.iniarquivo:

memcache.session_redundancy=2

Notas:

  • Isso faz com que o cliente memcache PHP grave as sessões em 2 servidores. Você obtém redundância (como RAID-1) para que as gravações sejam enviadas para n espelhos e as falhas get'ssejam repetidas nos espelhos. Isso significa que os usuários não perdem sua sessão no caso de uma falha do daemon do memcache.
  • As gravações espelhadas são feitas em paralelo (usando E / S sem bloqueio), portanto, o desempenho da velocidade não deve diminuir muito à medida que o número de espelhos aumenta. No entanto, o tráfego de rede aumentará se os espelhos do memcache forem distribuídos em máquinas diferentes. Por exemplo, não há mais 50% de chance de usar o host local e evitar o acesso à rede.
    • Aparentemente, o atraso na replicação de gravação pode causar a recuperação de dados antigos, em vez de uma falta de cache. A questão é se isso importa para o seu aplicativo? Com que frequência você escreve dados da sessão?
  • memcache.session_redundancyé para redundância de sessão, mas também há uma memcache.redundancyopção ini que pode ser usada pelo seu código de aplicativo PHP, se você desejar que ele tenha um nível diferente de redundância.
  • Você precisa de uma versão recente (ainda em beta no momento) do cliente memcache PHP - a versão 3.0.3 do pecl funcionou para mim.
Tom
fonte
Você poderia comentar sobre "ele não é dimensionado tão bem quanto usa um banco de dados compartilhado"? Não vejo como é diferente de uma configuração de banco de dados mestre-escravo típica. Obrigado!
quer
Esta é uma análise bem interessante, embora existam rumores (também conhecidos como relatórios de erros) de que isso não funciona conforme o esperado quando você usa a ext/memcacheversão 3.x. Também estamos brincando com essa opção e decidi percorrer a lista de servidores e escrever nela mesma.
Até
no caso da dica 3: e se um host armazenado em cache do memcached cair e depois aparecer, segundos o host ficará desativado. pelo que entendi - nenhum dado de sessão será restaurado e alguns deles serão perdidos, certo?
GioMac
28

Re: Dica 3 acima (para qualquer pessoa que se depare com isso via google), parece que, pelo menos atualmente, para que isso funcione, você deve usar os memcache.session_redundancy = N+1servidores N no seu pool , pelo menos esse parece ser o limite mínimo valor que funciona. (Testado com o php 5.3.3 no debian stable, pecl memcache 3.0.6, dois servidores memcached. session_redundancy=2Falharia assim que eu desligasse o primeiro servidor no save_path, session_redundancy=3funciona bem.)

Isso parece ser capturado nestes relatórios de erros:

Michael Jackson
fonte
11
Não pode upvote você suficiente ..
fest
11
Estou feliz por ter rolado para baixo. Esse foi o problema.
Daren Schwenke
Não está claro para mim, esse recurso está disponível apenas na série PECL memcache 3.x? Tudo isso está listado no software Beta em pecl.php.net/package/memcache , enquanto no 2.2.7 se eu matar o servidor em que vejo o líder, tudo morre.
Joe
Faz anos desde que eu olhei isso, para ser honesto. Pelo que me lembro, era um recurso 3.x (icbw). Implementamos muitos sistemas usando as versões "beta" desse plug-in (alguns deles com tráfego bastante alto) e não tivemos nenhum problema que parecesse relacionado a isso. YMMV, teste as coisas antes que elas entrem no ar, etc. :) Eu não trabalho no PHP há alguns anos, então alguns dos pontos mais sutis das curiosidades estão começando a desaparecer.
Michael Jackson
3

Juntamente com as configurações do php.ini mostradas acima, verifique também o seguinte:

memcache.allow_failover = 1  
memcache.hash_strategy = 'consistent'

Então você obterá failover total e redundância do lado do cliente. A ressalva dessa abordagem é que, se o memcached estiver desativado no localhost, sempre haverá uma falha de leitura antes que o cliente php memcache tente o próximo servidor no pool especificado em session.save_path

Lembre-se de que isso afeta as configurações globais do cliente php memcache em execução no servidor da web.

Ian Lewis
fonte
O uso de uma consistentestratégia de hash faz sentido, considerando que session.save_pathé diferente em cada servidor da web?
Tom
1

O memcached não funciona dessa maneira (por favor, corrija-me se estiver errado!)

Se você deseja que seu aplicativo tenha armazenamento de sessão redundante, é necessário criar algo que altere / adicione / exclua entradas nas duas instâncias armazenadas em cache. O memcached não lida com isso, a única coisa que fornece é como armazenamento de hash da chave. Portanto, sem replicação, sincronização, nada, nada.

Espero não estar errado sobre esse assunto, mas é isso que sei do memcached, já faz alguns anos desde que o toquei.

rasgou-
fonte
Seria útil para mim se você estivesse errado. :-) Existe um artigo no phpslacker.com ( phpslacker.com/2009/03/02/php-session-clustering-with-memcache ) que sugere que o memcached pode funcionar como descrito na pergunta. Talvez dependa de como o cliente memcache implementa a estratégia de hash?
Tom
11
O memcache não funciona assim, mas parece que o php pode funcionar da maneira que você deseja. Você precisará alterar o php.ini ou alterar seu aplicativo como descrito. No blog: onde está o cluster que você pergunta? Bem, verdade seja dita, não existe. O que temos até agora é um pool de memcache composto por 2 servidores. O PHP está configurado para gravar no pool. O PHP lê / grava no pool de servidores na ordem especificada pela diretiva ini “session.save_path”. Para leituras, o PHP solicitará um objeto de cache por chave do pool. Porque “failover” está habilitado PHP irá consultar o pool de servidores memchache um-por-um até que o [...]
tore-
1

O memcached não é replicado imediatamente , mas o repcached (um memcached corrigido) sim. No entanto, se você já estiver usando o mysql, por que não usar sua funcionalidade de replicação com a replicação master-master e obter o benefício da replicação completa de dados.

C.

symcbean
fonte
Obrigado pela informação. Não é realmente a replicação que eu estou procurando. É mais um caso de querer entrar em cada memcached sucessivamente até que a sessão seja encontrada. ou seja, primeiro verifique o localhost porque é mais rápido e depois verifique o outro servidor.
Tom
11
Em nome de todos os deuses PORQUE ???? Esta é a solução totalmente errada para .... bem, qualquer problema em que eu possa pensar. Além de ser muito ineficiente, mesmo com apenas 2 servidores, o desempenho ficará progressivamente pior muito rapidamente se você adicionar mais servidores. E isso não leva em consideração o fato de que sua solução aumenta duas vezes mais a probabilidade do que com um único servidor, quando, na prática, adicionar servidores a um cluster deve reduzir a probabilidade de uma interrupção. (BTW, se você baseado DNS média round-robin, em seguida, a afinidade de sessão está implícito!)
symcbean
Obrigado pelo feedback, sim, admito livremente que sou um noob no compartilhamento de sessões! :-) No entanto, ainda não entendi por que minha proposta é tão feia. Eu pensei que seria mais eficiente do que usar um banco de dados compartilhado e também pensei que tornaria as interrupções menos prováveis.
Tom
Não, isso os torna mais prováveis. A associação de dados como esse faz sentido quando você tem um número muito grande de nós, porque reduz a quantidade de replicação, mas normalmente é necessário fazer alguma replicação com um número definido de conjuntos para preservar a disponibilidade. Você precisaria ser muito exigente quanto ao desempenho para ver a diferença entre replicação repcached e replicação mysqld.
29410 sycbean
Testei e confirmei que, enquanto estiver usando o allow_failover = 1, vários espelhos tornam as interrupções menos prováveis. Posso desligar um espelho, reiniciar e desligar o outro, reiniciar e desligar o primeiro novamente - tudo sem estar desconectado. Eu acho que o cliente memcache PHP está fazendo muita trapaça nos bastidores.
Tom