Sana Inside » Post 'Cinco funcionalidades que podem ser desenvolvidas (e otimizadas) usando o memcache'

Cinco funcionalidades que podem ser desenvolvidas (e otimizadas) usando o memcache

Se você é um desenvolvedor web minimamente engajado e esteve no planeta terra nos últimos três anos, provavelmente já ouviu falar do memcached (do contrário, pode começar a saber mais pelo site oficial). Designado para servir como um sistema distribuído de cache em memória ram dispensável e de alta-performance para aliviar a barra dos servidores de bancos de dados, o Memcache é usado pelos maiores sites da internet (três exemplos: Facebook, Youtube, Flickr) e já fez a alegria de muito desenvolvedor de sites de grande-tráfego desde que foi lançado (mas é uma mão-na-roda também para os pequenos).

Mesmo que o memcache não deva ser usado como um mecanismo de armazenamento persistente de dados, principalmente se eles forem importantes, definitivamente não é só para fazer cache de querys do seu SGBD que essa maravilhosa ferramenta de Deus da Danga Interactive serve. Por ser instantaneamente escalável e pelo menos duas vezes mais rápido do que um “select from table” no já rápido mysql em acessos via tcp/ip (veja esse benchmark), o memcache pode ser usado como único mecanismo de armazenamento para aumentar bastante o desempenho de algumas aplicações que usam apenas dados descartáveis , ou seja, que se forem perdidos  num eventual crash do servidor não vão causar nenhum problema significativo.

A seguir, menciono cinco idéias de funcionalidades, fundamentais ou comuns mesmo em sites de pequeno tráfego, que podem tirar proveito das vantagens do memcache. Implantei as três primeiras no Flogão em 2006 e posso garantir que você (e o load average do seu servidor) ficarão contentes com o resultado:

1. Sessões de usuário

A abordagem mais comum para implantar a função que permite que um usuário faça login e navegue identificado por um site consiste em enviar para o cliente um cookie com um id ou token, e manter no lado do servidor um registro em arquivo ou num banco de dados para permitir a identificação segura e correta de cada sessão. Arquivos em disco são uma má idéia para qualquer site com número relevante (>500) de pessoas logadas ao mesmo tempo, e o banco de dados pode sofrer um pouco se por algum motivo você precisar fazer algum update na tabela de sessões a cada página que o usuário visitar.

Usar o memcache para manter os registros das sessões em seu servidor é a melhor solução. Armazene as informações serializadas da sessão numa entrada cuja chave seja o id ou token do cookie do usuário e seja feliz. Além de mais rápido (principalmente para updates), usar o memcache é mais prático, já que você pode setar um timeout para expirar cada sessão automaticamente depois de X minutos, caso o usuário saia do site sem clicar em “Logout”. Para fazer isso num banco de dados ou arquivo, você precisaria executar um update do momento em que ocorreu a última ação do usuário a cada página que ele visitar (caindo na situação crítica mencionada no parágrafo anterior), e ainda rodar um cronjob de tempos em tempos para remover as sessões expiradas.

2. Quem está online

Uma funcionalidade que permite mostrar se um usuário está online, ou até mesmo listar todos os que estão online e são da mesma região, por exemplo, é muito interessante principalmente para sites sociais e pode ajudar a aumentar o engajamento dos usuários em um site. A implementação desta é bem ligada às sessões de usuário, e também pode tirar muito proveito do armazenamento em memória permitido pelo memcache. A idéia é análoga a da funcionalidade 1, criar uma entrada usando como chave o id ou token do cookie, e armazenar nela o momento (um timestamp) em que o usuário fez a última ação no site, a ser atualizado a cada página que ele abrir.

Você poderia até mesmo usar a mesma entrada da sessão do usuário, mas sugiro que crie entradas diferentes pelo seguinte motivo: a entrada com a sessão do usuário deve ter um timeout mais alto (geralmente cerca de 1-2horas) que a entrada para essa funcionalidade (cerca de 3-5 minutos), de modo que se o usuário sair da frente do computador para ir lanchar, por exemplo, seu site logo reconhecerá que ele não está mais “online de fato”, mas o manterá logado caso ele volte para o computador e queira navegar no seu site depois de 30 minutos.

Um complicador de se usar o memcache para esta funcionalidade é o caso de você desejar listar todos os usuários que estão online. Uma forma de resolver isso seria setar a entrada no memcache com um timeout maior do que o timeout desejado (por exemplo, se quer que o usuário não seja mais considerado online depois de 5 minutos, sete o timeout em 10min) e criar as entradas estruturando-as como uma lista duplamente encadeada, mantendo num arquivo ou tabela do banco de dados a chave para o primeiro nó da lista. Neste caso, você precisaria remover da lista com um script (rodando pelo menos de 4 em 4 minutos, para os valores exemplificados) as entradas cuja última atividade tenha acontecido há mais de 5 minutos.

3. Contador de visitas

Contar visitas numa tabela é uma situação de stress para o seu banco de dados pois para cada leitura que se fizer do número de visitas para exibir na página, é preciso fazer também um update adicionando a nova visita. Embora uma operação do tipo “update contador set visitas=visitas+1 where id=’suapagina’ ” seja muito rápida em SGBDs como o mysql, ainda assim você estará tendo um ratio read/write de 1/1, e isso nunca é bom. O memcache pode te ajudar :)

Uma forma de se fazer isso seria, no primeiro acesso a uma página consultar no banco de dados o número de visitas, e salvar o valor já incrementado numa entrada do memcache. Nos acessos subsequentes, você pode fazer a leitura e o incremento do contador direto no cache. Para manter o banco de dados atualizado e garantir a persistência da informação, você pode criar uma regra para que, a cada dez visitas contadas no memcache, ou a cada 20 horas após a última atualização, deve-se atualizar o valor das visitas no banco de dados. Você deve manter o timeout dessas entradas alto (tipo 24horas) e certificar-se de que sua instância do memcache sempre terá memória suficiente para todas suas entradas.

Número de visitas não são uma informação tão descartável quanto sessões de usuário, mas ainda assim não vejo problemas em utilizar o memcache para contá-las, porque servidores bem-configurados não “caem” ou perdem informações com frequência, e mesmo que isso aconteça ocasionalmente, deixar de ter contado algumas visitas não chega a ser um desastre. Desastre é o seu site ficar lento por causa do servidor de banco de dados pedindo arrego e recusando conexões (ou seja, também vai deixar de contar algumas visitas).

4. Proteção contra quebras de senha por força bruta ou ataques de dicionário

Essa é uma funcionalidade bem direta, porém muito importante para a segurança das contas de seus usuários, e que aparentemente muitos sites deixam de implementar (vide caso recente no Twitter). Tudo o que você precisa fazer é bloquear novas tentativas de login numa conta por X minutos depois de X tentativas seguidas com a senha errada. Pode ser facilmente implementada em banco de dados e nem é muito custosa, mas é mais prático fazer também com o memcache.

A lógica é simples: quando tentarem logar numa conta com a senha errada, checa-se se o memcache já tem uma entrada com um número de tentativas erradas para aquele login. Se ela não existir, cria-se uma entrada (por exemplo, com a chave “tentativas_logindousuario”) armazenando o número de tentativas erradas (uma, no caso), e setando o timeout para X minutos (5 é um bom valor). Se já existir, sua aplicação deve checar se o número de tentativas já excedeu o máximo estipulado (5 também é um bom valor aqui). Se sim, será exibida uma mensagem de erro para o usuário informando que novas tentativas estão bloqueadas por 5 minutos. Se não, deve-se incrementar o número de tentativas, resetando o timeout para aquela chave (use o método set, ao invés do update, para fazer os incrementos).

Dois detalhes: Antes mesmo de checar no seu banco de dados se a senha está correta, você pode consultar a entrada de tentativas no memcache, de modo que se seu site estiver sofrendo um ataque para quebra de senhas, depois da quinta tentativa errada as consultas não irão mais consumir recursos do seu banco. E claro, sempre que um usuário se logar com a senha correta, deve-se remover a entrada com o número de tentativas erradas.

5. Captchas

Captchas (ou, em bom português, aqueles textos chatos que os usuários precisam digitar para validar um cadastro) geralmente são implementadas de modo semelhante a sessões de usuário. No php pelo menos, as implementações que vi usavam sempre variáveis de sessão, que por sua vez são mantidas em arquivos temporários no disco. No Flogão isso nos causava um problema pelo fato de que tínhamos alguns servidores web recebendo requisições através de um load balancer: se a requisição que exibiu o captcha para o usuário foi para o servidor 1, e posteriormente a requisição em que o usuário posta o texto digitado for para o servidor 2, sempre daria erro no captcha.

Isso se resolve, ou fazendo uma gambiarra para um formulário  ser sempre postado para o mesmo servidor (usando um subdomínio), ou utilizando um banco de dados ao invés de variáveis de sessão. Ou, melhor ainda, com o memcache (você já tinha adivinhado :p). Mesmo que seu site não rode em um load balancer (o que é verdade pra 99,9% dos sites), implementar seus captchas usando o memcache é uma boa idéia caso faça uso abundante deles (por exemplo, para validar comentários num fórum ou blog). Se usar só em cadastros, e houverem poucos por dia, apenas se importe em fazer isso se estiver com tempo sobrando e procurando alguma maneira geek de diversão.

Indo além

Eu poderia ficar aqui escrevendo por mais alguns longos parágrafos sobre outras funcionalidades que poderiam fazer uso do memcache, mas vou deixar isso por conta de sua criatividade. Liberte-se do conceito de que o memcache deve ser usado apenas como mais uma camada de cache para querys ao banco de dados, comece a olhar para a sua aplicação procurando por dados que você não precisa armazenar por muito tempo e com certeza encontrará várias funcionalidades que podem se beneficiar dele. Seu(s) servidor(es) de banco de dados agradece(m). E os usuários do seu site (agora mais rápido) também :)

Ps.: Sinta-se a vontade para postar nos comentários outras idéias de como utilizar o memcache em outras funcionalidades de aplicações web.

Ps.2.: Se você caiu aqui de paraquedas querendo tiver alguma dúvida sobre o memcache, poste a pergunta aí nos comentários que eu tento ajudar no que for possível.

Ps.3.: O memcache pode ser usado com as mais populares linguagens de programação. Existem clientes como o php memcache (ou memcached php), memcache rails, java, python, c e outros. O download pode ser feito no site oficial.

Tags: , , , , , ,
  • Pingback: funcionalidade.net - Cinco funcionalidades que podem ser desenvolvidas (e otimizadas …

  • Ricardo.

    boa noite,

    Qual o limite de memória que o memcache consegue gerenciar ? e como posso configurar no arquivo memcache.conf.

    Obrigado.

  • http://www.sanainside.com Diego Sana

    Oi Ricardo,

    Um servidor memcache pode endereçar até 4GB de memória. Se sua máquina tiver mais que isso, você pode rodar mais de uma instancia do memcache, em portas diferentes, pra usar mais memória. A quantidade de memória alocada é passada por parametro de linha de comando na hora de iniciar o servidor, não existe um “memcache.conf”, geralmente o que se faz é um “init script” pra iniciar o memcache sempre que reiniciar a máquina e nesse script vc já deixa setada a quantidade de memória. Leia a página inicial do http://www.danga.com/memcached/ que ela explica como inicializar o servidor e tira outras dúvidas :)

  • Pingback: O Mysql e o NoSql | Sana inside

  • jcoj2004

    hum… no caso teria q reescrever boa parte da aplicacao que faz uso de sessoes…. existe algo transparente para utilizacao de memcache?? estamos sofrendo com sessoes em db com teste com milhares de usuarios.. pq cada acao e um update no banco como disseste

    Abracos

  • alan_agraupe

    O mencahced deve estar instalado e operacional no servidor onde o site está hospedado não é isso?… Caso contrário o sistema não funciona.

  • Pingback: O Mysql e o NoSql :: Top Tutoriais

© 2008 Powered by WordPress