pikkabird
pikkabird

Reputation: 137

Redis cache busting - "dynamic" keys

We're using Redis for caching in our .NET 8 APIs (Azure Redis for some, Enterprise Redis for others).

Certain API endpoints take query string parameters, and these parameters are factored into the cache key name.

Below are a couple examples of cache keys for data sets returned to the same user (Id 12345) from the same "Fruit" endpoint, but with different filters/parameters supplied:

FruitAPI:{12345}:Fruit:Yellow,MildlySweet,Potassium
FruitAPI:{12345}:Fruit:Yellow,Sour,VitaminC

We need to be able to invalidate all such cache entries. The only approach I can think of is doing a pattern search for the "fixed" part, FruitAPI:{12345}:Fruit:*, then deleting each matching key.

We're using one of the latest versions of StackExchange.Redis, so Keys() will likely be doing a SCAN; however, as explained here, "crawling the redis keyspace via SCAN or KEYS is not efficient, and you should avoid requiring to do this as part of routine application logic".

I suppose we could use a set, to store the key names for FruitAPI:{12345}:Fruit:, but the cache entries will expire (at different times), while the set will still contain all the keys.

Are there any other options?

Thank you.

Upvotes: 1

Views: 68

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062494

There are multiple ways of approaching this scenario, depending on the specifics.

  1. If the common part is a single token, use a single hash (keyed by that shared token) with hash-fields per element; then a single key delete nukes all related elements; a wrinkle here is that until recently hash fields don't have independent expiration, but that is resolved in HEXPIRE
  2. Manually build a "set" of related keys, tagged by the common elements - so you do a SADD with every SET, then deleting the shared token means iterating that set and issuing a key delete per entry - this gets complex, but works
  3. Don't think "delete"; instead, per shared-token, store (separately) a timestamp (in some format) that is the last invalidation time; invalidating a shared token just means "update the timestamp for that token to now", and check that token when reading
  4. Use something that does it for you

In asp.net, "output cache" currently uses option 2, but "hybrid cache" (hopefully January) uses option 3. So it might be that you can use option 4, and just wait until January and use "hybrid cache", using the shared part here as a "tag".

Upvotes: 2

Related Questions