Cropping Redis - how to avoid race conditions?

I want to cache DB queries using redis. At the moment, the pseudocode in the separate API endpoint looks like this:

GET /data

      

  • Check if the object is in the REDIS cache (cacheKey)
  • If it's in the cache, just return it back to the client
  • If it is not in cache then fetch data from DB
  • Writing data to the REDIS cache (in the cache)
  • Returning data to the client

I cache objects that don't change often, so I set the expiration to 24 hours for example. The problem is when I want to update an object like this. The pseudocode looks like this:

PUT /data

      

  • Refresh data in DB
  • Write data to the cache (or just set the cache to the cache-cap null / delete)

The problem is that after new data has been written to the cache (or the cache has been deleted), it GET /data

can still overwrite the new data in the cache with the old data. This happens when the 4 point shape GET /data

is executed just after point 2 of PUT /data

.

Is there some mechanism that will prevent new data from being overwritten with old data in the cache?

+3


source to share


2 answers


In the case when it PUT

puts fresh data into the cache memory simultaneously with sending it to the database (pass-through cache), you can use SET

/ HSET

when writing to the cache from yours PUT

and SETNX

/ HSETNX

when writing to the cache from yours GET

. Since GET

will only write to the cache if the key does not exist, it SETNX

will usually succeed. But if someone else (possibly PUT

) came along and installed the key in the meantime, it SETNX

will fail because the key already exists and you will get the desired result.



In the case of PUT

simply deleting the data in the cache to be repopulated next GET

, I don't think you can provide a better guarantee than you already have. The data will live for one expiration date after it has been fetched from the database, which is not strictly wrong, it's just worse than you'd like.

+3


source


The NX approach as @hobbs suggested there is still a race condition. I would add to it using WATCH / MULTI / EXEC blocks around the GET workflow for transactional behavior.



With the NX-only approach, there is still a chance that 3 to 4 PUTs will get in the way.

+3


source







All Articles