dragonflydb / dragonfly

A modern replacement for Redis and Memcached
https://www.dragonflydb.io/
Other
24.76k stars 892 forks source link

introduce CAS commands #1033

Open romange opened 1 year ago

romange commented 1 year ago

we should support conditional commands on server side to reduce dependence on lua scripts.

Inspiration: redlock https://redis.io/docs/manual/patterns/distributed-locks/ implementations that use

 if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
    else
        return 0
    end'

there are more - TBD

dranikpg commented 1 year ago
  1. Instead of extending separate commands, I'd look into separate commands for MULTI/EXEC to allow simple conditional aborts and conditional skips. Many scripts can be reduced to such multi tx'es with such conditional checks and maybe simple if's

  2. There is already WATCH and the script from your example could be replaced with watch in theory, but now with two round trips the delete op can be much more costly

  3. We can look into a simple optimizer for lua scripts that together with the squasher will predict the shard flow of the script.

for example, if we have

if redis.call('CMD-1', key1) then
  redis.call('CMD-2', key1)

then the executor can "infere" that the next key access will to the very same key (thus on the same shard), so it can execute the script interpreter right after the command without returning from the hop

romange commented 1 year ago

I do not know how technically we can divide lua script unless we pass the interpretor in the middle of the run to continue running on the destination shard.

Regarding conditional muti/exec - again the problem is hops. Unless we implement the optimization that runs the whole multi-exec sequence on the shard if it touches a unique shard.

On Wed, Apr 5, 2023, 15:06 Vladislav @.***> wrote:

1.

Instead of extending separate commands, I'd look into separate commands for MULTI/EXEC to allow simple conditional aborts and conditional skips. Many scripts can be reduced to such multi tx'es with such conditional checks and maybe simple if's 2.

There is already WATCH and the script from your example could be replaced with watch in theory, but now with two round trips the delete op can be much more costly 3.

We can look into a simple optimizer for lua scripts that together with the squasher will predict the shard flow of the script.

for example, if we have

if redis.call('CMD-1', key1) then redis.call('CMD-2', key1)

then the executor can "infere" that the next key access will to the very same key (thus on the same shard), so it can execute the script interpreter right after the command without returning from the hop

— Reply to this email directly, view it on GitHub https://github.com/dragonflydb/dragonfly/issues/1033#issuecomment-1497378595, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4BFCCXDTNM3NOTPCBFDP3W7VN3BANCNFSM6AAAAAAWQ7VVTQ . You are receiving this because you authored the thread.Message ID: @.***>

dranikpg commented 1 year ago
  1. We'll just pass the interpreter. The squashed executor will have all the context

  2. In what sense is the problem hops? Do you mean that we can't squash a conditional? Yes, its true in general and its a problem for long sequences. But if all squashed commands are on one shard, we can do it. It's not difficult to detect.