RefList Cache /ou: Piece of cake!

Posted: 17 de set de 2009 | . David Lojudice Sobrinho | tags: , , ,

Quem já usou cache para uma aplicação web sabe: o que no começo parece simple, é mais complicada do que parece.

Um dos maiores problemas de cache é a invalidação. Quando invalidar? Onde invalidar?

Vou contar a história do projeto que participei a um ano atrás, o Gostei.com, onde o uso de memcached é extenso. Tínhamos o seguinte problema: um mesmo post pode aparecer em várias listas, sendo que estas listas poderiam ter ordenações e filtros diferentes. Mas se o post sofresse alguma alteração, como um novo voto, o número de votos tinha que ser igual em todas as listas.








A primeira abordagem foi um pouco ingênua: serializar e guardar no cache a lista inteira (List<Post>), incluindo o post junto. O problema é que a quantidade de votos de um post pertence a classe Post, tínhamos uma quantidade de votos diferente em cada lista (lista diversão-mais_votados e todos-mais_recentes, por exemplo) para o mesmo post. Era impossível saber em quais listas aquele post foi cacheado.

A solução foi usar o que chamamos de RefList Cache. Ao invés de guardar a lista com os posts, cacheamos a lista com os IDs dos posts (List<Guid>) e para cada post existe apenas um lugar no cache (uma key única). Assim, quando um post sofrer alguma alteração, basta atualizar invalidar o cache em um único lugar. Graças a um recurso do memcached (get_multi), é possível ter o RefList e todos os item com apenas duas chamadas.





Piece of cake! Quer dizer... nem tanto. Ainda tem um problema. Nada garante que todos os IDs da RefList vão estar no cache. O que fazer? Um dos recursos da lib que criamos é o conceito de hierarquia de repositório, onde é possível dizer a ordem dos locais onde a lib vai procurar pelo dado (Local Cache, Memcached, DB). Por exemplo, caso metade dos posts estiver no cache, a lib vai tentar pegar a outra metade no banco.

Aqui tem uma apresentação que ajuda a explicar a idéia: PPT.

Sweet! :)

0 comentários: