skip to Main Content

I’d like to atomically set all values of a list, just like the regular SET command.

I need it because the list is to be a cached representation of a database query. I’d like to access the cache in the "paginated" mode by using LRANGE.

I thought of using RPUSH, but if a race condition occurs, my cache will contain multiple sets of duplicate results one after another, and I wouldn’t like that.

Using RPUSH in conjunction with LTRIM to the known list length should work most of the time, but it may fail in cases where the data source returned different result sets and we had a race condition on LTRIM. Of course it’s a lot less likely to happen, but still.

The SORTED SET with indexes as weights suffers from similar kinds of problems.

Using redis’ transactions seems like an overkill: as far as I’m concerned, they halt all other incoming commands until the transaction is over — and the cached result set may be a chunky one.

Yet, DEL and RPUSH in a transaction seems like the only option so far. Is it really?

3

Answers


  1. Chosen as BEST ANSWER

    Yeah, I think I figured it out. It should be a LUA script, since they are atomic:

    redis.call('DEL', KEYS[1])
    local res = redis.call('LPUSH', KEYS[1], unpack(ARGV))
    return res
    

    I haven't tested it yet, but should work. First we delete the array, then we set all its values.


  2. LPUSH and RPUSH is variadic so you can just call either of them with all the values you want to add.

    > RPUSH foo alfa bravo charlie delta
    

    This will happen atomically.

    Login or Signup to reply.
  3. The short answer is it sounds like a transaction would generally be the easiest way to handle this:

    MULTI
    DEL list
    RPUSH list item1 item2 item3...
    EXEC
    

    However, if your list is enormous, and you are concerned with blocking the Redis server while it’s being populated, your other option would be to use a distributed locking pattern like redlock to lock the key from reads/writes while you populate the list.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search