Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache invalidation strategy

Tags:

caching

redis

In my current application, we are dealing with some information which rarely changes.
For performance optimization, we want to store them in the cache.
But the problem is in invaliding these objects whenever these are updated.
We have not finalized the caching product.
As we are building this application on Azure, we will probably use Azure Redis cache.
One strategy could be to add code in Update API which will invalidate object in the cache.
I am not sure if this is a clean way?
We do not want to go with Cache Expiration based on time (TTL).
Could you please suggest some other strategies used for cache invalidation?

like image 740
Pragmatic Avatar asked May 11 '15 11:05

Pragmatic


People also ask

What is cache invalidation mechanism?

Cache invalidation refers to process during which web cache proxies declare cached content as invalid, meaning it will not longer be served as the most current piece of content when it is requested. Several invalidation methods are possible, including purging, refreshing and banning.

What is the best caching strategy?

Cache-Aside (Lazy Loading) A cache-aside cache is the most common caching strategy available. The fundamental data retrieval logic can be summarized as follows: When your application needs to read data from the database, it checks the cache first to determine whether the data is available.

What happens when cache is invalidated?

Cache invalidation describes the process of actively invalidating stale cache entries when data in the source of truth mutates. If a cache invalidation gets mishandled, it can indefinitely leave inconsistent values in the cache that are different from what's in the source of truth.


1 Answers

Invalidate the cache during the Update stage is a viable approach, and was extremely used in the past.

You have two options here when the UPDATE happens:

  1. You may try to set the new value during update operation, or
  2. Just delete the old one and update during a read operation.

If you want an LRU cache, then UPDATE may just delete the old value, and the first time the object will be fetched, you'll create it again after the read from the actual database. However, if you know that your cache is very small and you are using another main database for concerns different than data size, you may update directly during UPDATE.

However, all this is not enough to be completely consistent.
When you write to your DB, the Redis cache may be unavailable for a few seconds for example, so data remains not synchronized between the two.
What do you do in that case?
There are several options you could use at the same time.

  1. Set a TTL anyway, so that eventually broken data is refreshed.
  2. Use lazy read repair. When you read from the DB, from time to time check with the primary if the value matches. If not update the cached item (or delete it).
  3. Use epochs or similar ways to access your data. Not always possible, however sometimes you access cached data about a given object. When possible you may change the object ID/handle every time you modify it, so that it is impossible that you access stale data in the cache: every key name refers to a specific version of your object.

So the del-cache-on-update and write-cache-on-read is the basic strategy, but you can employ other additional systems to eventually repair the inconsistencies.

There is another option actually instead of using the above options, which is to have a background process using Redis SCAN to verify key by key if there are inconsistencies. This process can be slow and can run against a replica of your database.

As you can see here the main idea is always the same: if an update to the cache fails, don't make it a permanent issue that will remain there potentially forever, give it a chance to fix itself at a later time.

like image 96
antirez Avatar answered Sep 28 '22 11:09

antirez