Estratégias de armazenamento em cache - Amazon ElastiCache

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Estratégias de armazenamento em cache

No tópico a seguir, você pode encontrar estratégias para preencher e manter seu cache.

Que estratégias implementar para preencher e manter seu cache dependem de quais dados você está armazenando em cache e dos padrões de acesso a eles. Por exemplo, você provavelmente não quer usar a mesma estratégia para um placar dos 10 primeiros colocados em um site de jogos e em notícias atuais. No restante desta seção, discutiremos estratégias comuns de manutenção de cache, suas vantagens e suas desvantagens.

Carregamento lento

Como o nome indica, o carregamento lento é uma estratégia de cache que carrega dados no cache apenas quando necessário. Ele funciona como descrito a seguir.

ElastiCache A Amazon é um armazenamento de valores-chave na memória que fica entre seu aplicativo e o armazenamento de dados (banco de dados) que ele acessa. Sempre que seu aplicativo solicita dados, ele primeiro faz a solicitação ao ElastiCache cache. Se os dados existirem no cache e forem atuais, ElastiCache retornará os dados para seu aplicativo. Se os dados não existirem no cache ou tiverem expirado, sua aplicação solicitará os dados do seu armazenamento de dados. Seu armazenamento de dados retorna os dados para sua aplicação. Sua aplicação, em seguida, grava os dados recebidos do armazenamento no cache. Dessa forma, eles podem ser recuperados mais rapidamente na próxima vez que forem solicitados.

Um acerto de cache ocorre quando os dados estão no cache e não estão expirados:

  1. A aplicação solicita dados do cache.

  2. O cache retorna os dados à aplicação.

Uma perda de cache ocorre quando os dados não estão no cache ou estão expirados:

  1. Sua aplicação solicita dados do cache.

  2. O cache não possui os dados solicitados e, portanto, retorna null.

  3. Sua aplicação solicita e recebe os dados do banco de dados.

  4. A aplicação atualiza o cache com os novos dados.

Vantagens e desvantagens do carregamento lento

As vantagens do carregamento lento são as seguintes:

  • Apenas dados solicitados são armazenados em cache.

    Como a maioria dos dados nunca é solicitada, o carregamento lento evita o preenchimento do cache com dados que não são solicitados.

  • Falhas de nó não são fatais para sua aplicação.

    Quando um nó falha e é substituído por um novo nó vazio, sua aplicação continua a funcionar, embora com latência aumentada. À medida que as solicitações são feitas para o novo nó, cada perda de cache resulta em uma consulta do banco de dados. Ao mesmo tempo, a cópia de dados é adicionada ao cache para que as solicitações subsequentes sejam recuperadas do cache.

As desvantagens do carregamento lento são as seguintes:

  • Existe uma penalidade de ausência no cache. A perda de cache resulta em 3 viagens,

    1. Solicitação inicial de dados do cache

    2. Consulta do banco de dados para os dados

    3. Gravação de dados no cache

    Essas perdas podem causar um atraso observável na obtenção dos dados para a aplicação.

  • Dados obsoletos.

    Se os dados forem gravados no cache somente quando houver uma perda de cache, os dados no cache poderão ficar obsoletos. Esse resultado ocorre porque não há atualizações para o cache quando os dados são alterados no banco de dados. Para resolver esse problema, você pode usar as estratégias Gravação simultânea e Adicionar o TTL.

Exemplo de pseudocódigo de carregamento lento

O código a seguir é um exemplo de pseudocódigo de lógica de carregamento lento.

// ***************************************** // function that returns a customer's record. // Attempts to retrieve the record from the cache. // If it is retrieved, the record is returned to the application. // If the record is not retrieved from the cache, it is // retrieved from the database, // added to the cache, and // returned to the application // ***************************************** get_customer(customer_id) customer_record = cache.get(customer_id) if (customer_record == null) customer_record = db.query("SELECT * FROM Customers WHERE id = {0}", customer_id) cache.set(customer_id, customer_record) return customer_record

Para este exemplo, o código da aplicação que obtém os dados é o seguinte.

customer_record = get_customer(12345)

Gravação simultânea

A estratégia de gravação simultânea adiciona dados ou atualiza dados no cache sempre que eles são gravados no banco de dados.

Vantagens e desvantagens da gravação simultânea

As vantagens da gravação simultânea são as seguintes:

  • Os dados no cache nunca são obsoletos.

    Como os dados no cache são atualizados sempre que são escritos no banco de dados, eles sempre estão atualizados.

  • Penalidade de gravação versus penalidade de leitura.

    Cada gravação envolve duas viagens:

    1. Uma gravação no cache

    2. Uma gravação no banco de dados

    Que acrescenta latência ao processo. Dito isto, os usuários finais geralmente são mais tolerantes à latência ao atualizarem dados do que ao recuperarem dados. Existe um sentido inerente de que as atualizações são mais trabalhosas e, portanto, demoram mais.

As desvantagens da gravação simultânea são as seguintes:

  • Dados ausentes.

    Se você cria um novo nó, seja devido a uma falha de nó ou ao aumento de escala na horizontal, haverá dados ausentes. Esses dados continuam ausentes até que sejam adicionados ou atualizados no banco de dados. Você pode minimizar isso implementando carregamento lento com gravação simultânea.

  • Rotatividade do cache.

    A maioria dos dados nunca é lida, o que é um desperdício de recursos. Ao adicionar um valor de tempo de vida (TTL), você pode minimizar o espaço desperdiçado.

Exemplo de pseudocódigo de gravação simultânea

O código a seguir é um exemplo de pseudocódigo da lógica de gravação simultânea.

// ***************************************** // function that saves a customer's record. // ***************************************** save_customer(customer_id, values) customer_record = db.query("UPDATE Customers WHERE id = {0}", customer_id, values) cache.set(customer_id, customer_record) return success

Para este exemplo, o código da aplicação que obtém os dados é o seguinte.

save_customer(12345,{"address":"123 Main"})

Adicionar o TTL

O carregamento lento permite dados obsoletos, mas não falha com nós vazios. A gravação simultânea garante que os dados sempre sejam atuais, mas pode falhar com nós vazios e pode preencher o cache com dados supérfluos. Ao adicionar um valor de tempo de vida (TTL) a cada gravação, você pode ter as vantagens de cada estratégia. Ao mesmo tempo, você pode em grande parte evitar desordenar o cache com dados adicionais.

O Time to live (TTL) (Tempo de vida) é um valor inteiro que especifica o número de segundos até a chave expirar. O Memcached especifica este valor em segundos. Quando uma aplicação tenta ler uma chave expirada, isso é tratado como se a chave não fosse encontrada. O banco de dados é consultado para a chave e o cache é atualizado. Essa abordagem não garante que um valor não esteja obsoleto. Contudo, isso impede que os dados fiquem obsoletos demais e exige que os valores no cache sejam ocasionalmente atualizados a partir do banco de dados.

Para obter mais informações, consulte o .

Exemplos de pseudocódigo de TTL

O código a seguir é um exemplo de pseudocódigo da lógica de gravação simultânea com TTL.

// ***************************************** // function that saves a customer's record. // The TTL value of 300 means that the record expires // 300 seconds (5 minutes) after the set command // and future reads will have to query the database. // ***************************************** save_customer(customer_id, values) customer_record = db.query("UPDATE Customers WHERE id = {0}", customer_id, values) cache.set(customer_id, customer_record, 300) return success

O código a seguir é um exemplo de pseudocódigo de lógica de carregamento lento com TTL.

// ***************************************** // function that returns a customer's record. // Attempts to retrieve the record from the cache. // If it is retrieved, the record is returned to the application. // If the record is not retrieved from the cache, it is // retrieved from the database, // added to the cache, and // returned to the application. // The TTL value of 300 means that the record expires // 300 seconds (5 minutes) after the set command // and subsequent reads will have to query the database. // ***************************************** get_customer(customer_id) customer_record = cache.get(customer_id) if (customer_record != null) if (customer_record.TTL < 300) return customer_record // return the record and exit function // do this only if the record did not exist in the cache OR // the TTL was >= 300, i.e., the record in the cache had expired. customer_record = db.query("SELECT * FROM Customers WHERE id = {0}", customer_id) cache.set(customer_id, customer_record, 300) // update the cache return customer_record // return the newly retrieved record and exit function

Para este exemplo, o código da aplicação que obtém os dados é o seguinte.

save_customer(12345,{"address":"123 Main"})
customer_record = get_customer(12345)

Tópicos relacionados da