Usando o Memcached: é uma boa prática atualizar o cache ao atualizar o banco de dados?

13

Esta pergunta é sobre melhores práticas em arquitetura.

Nossa Arquitetura Atual

Eu tenho uma classe PHP que acessa o MySQL para informações do usuário. Vamos chamá-lo User. Useré acessado muitas vezes, por isso implementamos camadas de cache para reduzir a carga.

A primeira camada é o que chamamos de cache "por solicitação". Depois que os dados foram recuperados do MySQL, armazenamos os dados em uma propriedade privada de User. Quaisquer pedidos subsequentes para os dados retornam a propriedade em vez de solicitar novamente os dados do MySQL.

Como a solicitação da Web vive e morre conforme a solicitação, esse cache apenas impede que o aplicativo acesse o MySQL mais de uma vez em uma única solicitação.

Nossa segunda camada é o Memcached. Quando a propriedade privada está vazia, primeiro verificamos os dados no Memcached. Se o Memcached estiver vazio, consultamos os dados do MySQL, atualizamos o Memcached e atualizamos a propriedade privada de User.

A questão

Nossa aplicação é um jogo e, às vezes, é imperativo que alguns dados estejam o mais atualizados possível. No período de aproximadamente cinco minutos, uma solicitação de leitura para os dados do usuário pode ocorrer 10 ou 11 vezes; uma atualização pode ocorrer. Os pedidos de leitura subsequentes precisam estar atualizados ou a mecânica do jogo falha.

Então, o que fizemos foi implementar um pedaço de código que é executado quando ocorre uma atualização do banco de dados. Esse código define a chave no Memcached com os dados atualizados, para que todas as solicitações subsequentes ao Memcached estejam atualizadas.

Isso é ótimo? Há alguma preocupação com o desempenho ou outras "dicas" que devemos estar atentos ao tentar manter uma espécie de "cache ativo" como esse?

Stephen
fonte
O que isso tem a ver com excluir e adicionar novamente dados?
Mike Nakis
Esclareceu o título da pergunta.
Stephen
Por que não apenas expirar os dados em cache? Atualizar significa que você precisará garantir que a atualização seja mantida (para que, se novos dados precisem ser atualizados dessa maneira, você precise continuar alterando a atualização). A expiração do cache significa que tudo é extraído do banco de dados - e quaisquer novas atualizações não precisam de novas alterações no código de atualização. A desvantagem é que a carga do banco de dados pode ser maior.
Peter K.
@ Peter Sim, nós pensamos sobre isso também. Se não surgirem outros problemas com a nossa abordagem atual, continuaremos com ela. Caso contrário, podemos seguir o que você descreveu.
Stephen
1
@ Stephen A abordagem que você descreve é ​​chamada "Write Through Cache" e é uma abordagem bastante comum.
Sripathi Krishnan 6/01/12

Respostas:

10

Minha recomendação é examinar seu perfil de uso e seus requisitos para o cache.

Não vejo razão para deixar dados obsoletos no cache de memórias. Eu acho que você escolheu a abordagem correta, ou seja: atualize o DB.

De qualquer forma, você precisará de um wrapper na atualização do banco de dados (o que você fez). Seu código para atualizar o usuário no banco de dados e na RAM também deve ser enviado para o memcached OU uma expiração no memcached.

Por exemplo - se seus usuários normalmente fazem uma atualização uma vez por sessão como parte do logoff, não faz muito sentido atualizar os dados no cache (por exemplo, pontuação total alta) - você deve expirar imediatamente.

Se, no entanto, eles atualizarem os dados (por exemplo, estado atual do jogo) e, 0,2 segundos depois, você terá uma ocorrência imediata na página PHP que solicitará os dados, desejando que sejam atualizados no cache.

jasonk
fonte
3

Eu não faria isso exatamente como você descreveu. O que você precisa fazer é decidir se você realmente precisa de dados completamente atualizados. Em seguida, se você precisar, decida quais partes dos dados devem estar sempre atualizadas e separe-as das coisas que podem ser armazenadas em cache em sua arquitetura.

Por exemplo, você provavelmente deseja atualizar o endereço de e-mail do usuário assim que o alterar, para não enviar e-mails para o endereço errado, mas é improvável que a data de nascimento ou sobrenome do usuário precise ser completamente atualizado para fornecer uma experiência decente ao usuário. (NB: Não estou usando um exemplo de arquitetura de jogo, pois não sei que tipo de jogo apontar e acho que este é bastante fácil de entender).

Dessa forma, você tem dois conjuntos de dados claros: dados armazenáveis ​​em cache de curto e longo prazo. Provavelmente, você pode se safar com uma duração de cache de mais ou menos um minuto nos dados de curto prazo, apenas para aliviar a carga no banco de dados, mas os dados de longo prazo podem ser deixados no cache em uma duração variável, desde que sejam usava.

Então você precisa lidar com as atualizações. Primeiro, eu usaria um gatilho de banco de dados para simplesmente remover itens do cache quando estiverem desatualizados. Isso forçará sua camada de negócios a acionar uma atualização de cache na próxima vez em que solicitar os dados, liberando espaço no cache se os dados não estiverem sendo usados ​​(por exemplo, se um usuário alterar seu endereço de email e sair imediatamente) . Se isso causar problemas de desempenho na interface do usuário (ou seja, introduzir muito atraso enquanto aguarda a atualização do cache), você poderá simplesmente acionar a chamada de cache assim que o item for removido do cache. Eu também procuraria otimizar os tempos de leitura do banco de dados para esse pequeno conjunto de dados, para garantir que qualquer atraso induzido na atualização do cache seja mínimo (isso deve ser mais fácil, pois você só precisa carregar dados que realmente precisa).

O que eu não faria, em nenhuma circunstância, é adicionar um método adicional de preenchimento do cache, pois você precisará manter a chamada (e ganchos de API etc.) em dois locais.

Quanto às dicas, a principal coisa que você precisa ter cuidado se estiver escrevendo diretamente no cache é a sincronização. Se muitos threads tentarem ler enquanto você estiver fazendo sua atualização silenciosa, você poderá ter sérios problemas de dados inválidos, o que impedirá o ponto de tentar manter os dados atualizados em primeiro lugar.

Ed James
fonte