How to choose between cache-aside, read-through, write-through, client-side, and distributed caching strategies Como já mencionamos nos últimos post, estamos felizes que Pekka Enberg decidiu escrever e estamos orgulhosos de patrocinarmos 3 capítulos dele. Por que guardar dados? Um livro sobre a latência Obter o livro Latency extrato PDF Obter o livro Latency extrato PDF Obter o livro Latency extrato PDF Além disso, Pekka acabou de compartilhar as principais tomadas desse livro em uma (Ainda disponível a pedido) Avaliações sobre a construção de aplicativos de baixa latência Vamos continuar a nossa Excerto do livro com mais do capítulo de cache de Pekka. É reimpresso aqui com a permissão do editor. Latença * • • • • Ao adicionar cache ao seu aplicativo, você deve primeiro considerar sua estratégia de cache, que determina como as leituras e escrituras ocorrem a partir da cache e do armazenamento de backup subjacente, como um banco de dados ou um serviço. Em outras palavras, quando seu aplicativo olha para um valor do cache, mas o valor não está lá ou expirou, a estratégia de cache manda se é o seu aplicativo ou o cache que recupera o valor da loja de backup. Como de costume, diferentes estratégias de cache têm diferentes compensações em latência e complexidade, então vamos entrar diretamente nisso. Cache-aside em cache Quando há um cache hit, a latência de acesso aos dados é dominada pela latência de comunicação, que é geralmente pequena, pois você pode obter um cache próximo em um servidor de cache ou até mesmo em seu espaço de memória de aplicativos. No entanto, quando há uma falta de cache, com cache-side caching, o cache é uma loja passiva atualizada pelo aplicativo. isto é, o cache apenas relata uma falta e o aplicativo é responsável por recuperar dados da loja de backup e atualizar o cache. A Figura 1 mostra um exemplo de cache-aside caching em ação.Uma aplicação olha para um valor de um cache por uma chave de cache, que determina os dados que o aplicativo está interessado. Se a chave existe na cache, a cache devolve o valor associado à chave, que a aplicação pode usar. No entanto, se a chave não existe ou expirou na cache, temos uma falta de cache, que a aplicação tem que lidar. Suponha que você esteja cacheando informações do usuário e usando o ID do usuário como a chave de pesquisa. Nesse caso, o aplicativo executa uma consulta pelo ID do usuário para ler informações do usuário do banco de dados. As informações do usuário retornadas do banco de dados são então transformadas em um formato que você pode armazenar no cache. Em seguida, o cache é atualizado com o ID do usuário como a chave do cache e as informações como o valor. Por exemplo, uma maneira típica de realizar este tipo de cache é transformar as informações do usuário retornadas do banco de dados em JSON e armazená-lo no cache. Cache-aside caching é popular porque é fácil configurar um servidor de cache como o Redis e usá-lo para cache consultas de banco de dados e respostas de serviço. Com cache-aside caching, o servidor de cache é passivo e não precisa saber qual banco de dados você usa ou como os resultados são mapeados para o cache. É seu aplicativo fazendo todo o gerenciamento de cache e transformação de dados. Em muitos casos, a cache-side caching é uma maneira simples e eficaz de reduzir a latência da aplicação.Você pode ocultar a latência de acesso à base de dados, tendo as informações mais relevantes em um servidor de cache perto de sua aplicação. No entanto, o cache-side caching também pode ser problemático se você tiver requisitos de consistência de dados ou frescura. Por exemplo, se você tiver vários leitores simultâneos que estão procurando uma chave na cache, você precisa coordenar em seu aplicativo como você lida com falhas de cache simultâneas; caso contrário, você pode acabar com múltiplos acessos de banco de dados e atualizações de cache, o que pode resultar em pesquisas subsequentes de cache retornando valores diferentes. No entanto, com o cache-aside caching, você perde o suporte de transação porque o cache e o banco de dados não se conhecem, e é responsabilidade da aplicação coordenar atualizações aos dados. Finalmente, o cache-aside caching pode ter latência de cauda significativa porque algumas buscas de cache experimentam a latência de leitura da base de dados em uma falta de cache. isto é, embora no caso de um cache hit, a latência de acesso é rápida porque vem de um servidor de cache próximo; buscas de cache que experimentam uma falta de cache são apenas tão rápidas quanto o acesso à base de dados. Leia através do Caching A memória cache de leitura é uma estratégia em que, ao contrário da memória cache de lado, a memória cache é um componente ativo quando há uma falta de memória cache. Quando há uma falta de memória cache, uma memória cache de leitura tenta ler um valor para a chave da loja de backup automaticamente. A latência é semelhante à memória cache de lado, embora a latência de recuperação da loja de backup seja da memória cache para a loja de backup, não da aplicação para a loja de backup, que pode ser menor, dependendo da sua arquitetura de implantação. A Figura 2 mostra um exemplo de um cache de leitura em ação. O aplicativo executa uma pesquisa de cache em uma chave, e se houver uma falta de cache, o cache executa uma leitura para o banco de dados para obter o valor para a chave. O cache então atualiza-se e retorna o valor para a aplicação. Do ponto de vista de um aplicativo, uma falta de cache é transparente porque o cache sempre retorna uma chave se existe, independentemente de houver uma falta de cache ou não. O cache de leitura é mais complexo de implementar porque um cache precisa ser capaz de ler o backup store, mas também precisa transformar os resultados da base de dados em um formato para o cache. Por exemplo, se o backup store é um servidor de banco de dados SQL, você precisa converter os resultados da consulta em um formato JSON ou similar para armazenar os resultados no cache. No entanto, porque o cache coordena as atualizações e o banco de dados lê com cache de leitura, ele pode dar garantias transacionais à aplicação e garantir a consistência em falhas de cache concomitantes. Naturalmente, a mesma advertência de latência de cauda aplica-se a caches de leitura como eles fazem ao cache-side caching. Uma exceção: como componentes ativos, caches de leitura podem esconder a latência melhor com, por exemplo, cache de atualização. Aqui, o cache atualiza asincronicamente o cache antes que os valores expiram – portanto, ocultando a latência de acesso da base de dados de aplicativos completamente quando um valor está no cache. Escrever através do caching O cache-side e o cache-through são estratégias em torno de leituras de cache, mas às vezes você também quer que o cache suporte as leituras. Em tais casos, o cache fornece uma interface para atualizar o valor de uma chave que o aplicativo pode invocar. No caso do cache-side, o aplicativo é o único a se comunicar com a loja de backup e, portanto, atualizar o cache. No entanto, com o cache-through, existem duas opções para lidar com as leituras: cache-through e cache-back. O cache de escrita é uma estratégia onde uma atualização para o cache se propaga imediatamente para a loja de backup. Sempre que um cache é atualizado, o cache atualiza sincronicamente o backup store com o valor cache. A latência de escrita do cache de escrita é dominada pela latência de escrita para a loja de backup, o que pode ser significativo. Como mostrado na Figura 3, um aplicativo atualiza um cache usando uma interface fornecida pelo cache com uma chave e um par de valores. O cache atualiza seu estado com o novo valor, atualiza o banco de dados com o novo valor e espera que o banco de dados comprometa a atualização até reconhecer a atualização do cache para o aplicativo. No entanto, para caches não transacionais, o cache e o backup store podem estar fora de sincronização na presença de erros. Por exemplo, se escrever para cache é bem sucedido, mas a escrita para backup store falha, os dois estarão fora de sincronização. Claro, um cache de escrita pode fornecer garantias transacionais, negociando algum tempo de latência para garantir que o cache e o banco de dados estejam atualizados ou nenhum deles. Tal como acontece com um cache de leitura, o cache de escrita assume que o cache pode se conectar ao banco de dados e transformar um valor de cache em uma consulta de banco de dados. Por exemplo, se você estiver caching dados do usuário onde o ID do usuário serve como a chave e um documento JSON representa o valor, o cache deve ser capaz de transformar a representação JSON de informações do usuário em uma atualização de banco de dados. Com o cache de escrita, a solução mais simples é muitas vezes armazenar o JSON no banco de dados. A principal desvantagem do cache de escrita é a latência associada com atualizações de cache, que é essencialmente equivalente à latência de comissão de banco de dados. Escrever por trás do caching Em outras palavras, com o cache de escrita atrás, o cache pode aceitar várias atualizações antes de atualizar o backup, como mostrado na Figura 4, onde o cache aceita três atualizações de cache antes de atualizar o banco de dados. A latência de gravação de um cache de escrita por trás é menor do que com o cache de escrita por trás, porque o backup store é atualizado de forma assíncrona. Ou seja, o cache pode reconhecer a escrita imediatamente para o aplicativo, resultando em uma escrita de baixa latência e, em seguida, executar a atualização do backup store no fundo. No entanto, a desvantagem do cache de escrita por trás é que você perde o suporte de transação porque o cache não pode mais garantir que o cache e o banco de dados estejam em sincronia. Além disso, o cache de escrita por trás pode reduzir a durabilidade, o que é a garantia de que você não perde dados. Cliente do lado Caching Uma estratégia de cache do lado do cliente significa ter o cache na camada do cliente dentro de seu aplicativo. embora servidores de cache como o Redis usem cache na memória, o aplicativo deve se comunicar através da rede para acessar o cache através do protocolo Redis. Se o aplicativo é um serviço executado em um centro de dados, um servidor de cache é excelente para o cache porque a rota de rede dentro de um centro de dados é rápida e a complexidade do cache está no próprio cache. No entanto, a latência da última milha ainda pode ser um fator significativo na experiência do usuário em um dispositivo, razão pela qual o cache do lado do cliente é tão lucrativo. Com o cache do lado do cliente, uma combinação de cache de leitura e escrita é ideal do ponto de vista da latência, porque tanto as leituras quanto as escrituras são rápidas.Claro, seu cliente geralmente não será capaz de se conectar diretamente ao banco de dados, mas acessa o banco de dados indiretamente através de um proxy ou de um servidor API. Para muitas aplicações que precisam de cache do lado do cliente de baixa latencia, a abordagem local-prime para a replicação pode ser mais prática. Mas para cache de leitura simples, o cache do lado do cliente pode ser uma boa solução para alcançar baixa latencia.Claro, o cache do lado do cliente também tem um compromisso: pode aumentar o consumo de memória do aplicativo porque você precisa de espaço para o cache. Caching distribuído Até agora, apenas discutimos o cache como se existira uma única instância de cache. Por exemplo, você usa um cache no aplicativo ou um único servidor Redis para cachear consultas de um banco de dados PostgreSQL. No entanto, muitas vezes você precisa de múltiplas cópias dos dados para reduzir a latência geográfica em vários locais ou escalar para acomodar sua carga de trabalho. Com tal cache distribuído, você tem inúmeras instâncias do cache que trabalham independentemente ou em um aglomerado de cache. Com cache distribuído, você tem muitas das mesmas complicações e considerações como as discutidas no Capítulo 4 sobre replicação e no Capítulo 5 sobre particionamento. Com cache distribuído, você não quer encaixar todos os dados cache em cada instância, mas sim ter dados cache divididos entre os nós. No geral, o cache distribuído é uma encruzilhada dos benefícios e problemas do cache, particionamento e replicação, então cuidado se você estiver indo com isso. * • • • • Para continuar lendo, do ScyllaDB ou . Descarregar o trecho do capítulo Latency grátis Compre o livro completo de Manning Sobre Cynthia Dunlop Cynthia é Diretora Sênior de Estratégia de Conteúdo na ScyllaDB. Ela escreve sobre desenvolvimento de software e engenharia de qualidade há mais de 20 anos.