Redis:原子性获取和条件设置

我想在 Redis 中执行一个原子的 GET 操作,如果返回的值等于某个期望的值,我想要做一个 SET 操作,但是我希望将所有这些操作都链式地作为一次原子操作。 (我正在尝试设置一个指示是否有任何进程正在将数据写入磁盘的标志,因为只有一个进程被允许这样做。)

这是否可能用 Redis 实现?

我看到了关于 MULTI 操作的文档,但我没有看到条件操作的 MULTI 操作。希望其他人能给出一些关于这个问题的建议,这将非常感激!

点赞
用户4554496
用户4554496

你可以使用Lua脚本在Redis服务器上执行GET和set操作。它们是原子的,允许您添加逻辑。

2018-05-12 23:53:01
用户1727392
用户1727392

我最终使用了redlock-py,这是Redis文档推荐用于创建写锁的redlock算法的一种实现:https://redis.io/topics/distlock。该文章对于任何想在Redis中创建类似的写锁的人来说都是非常棒的阅读材料。

2018-05-14 23:12:24
用户1031804
用户1031804

redis-if

redis-if 是一个用于“条件事务”的 Lua 脚本库。比WATCH + MULTY更方便。

你可以传递任何组合的条件和后续命令作为 JSON 对象:

const Redis = require('ioredis')

const redis = new Redis()

redis.defineCommand('transaction', { lua: require('redis-if').script, numberOfKeys: 0 })

await redis.set('custom-state', 'initialized')
await redis.set('custom-counter', 0)

// this call will change state and do another unrelated operation (increment) atomically
let success = await redis.transaction(JSON.stringify({
  if: [
    // apply changes only if this process has acquired a lock
    [ 'initialized', '==', [ 'sget', 'custom-state' ] ]
  ],
  exec: [
    [ 'set', 'custom-state', 'finished' ],
    [ 'incr', 'custom-counter' ]
  ]
}))

运用这个脚本,我们从项目中删除了所有自定义脚本。

2021-02-20 06:48:34
用户568708
用户568708

我在寻找类似功能时遇到了这篇文章,但我没有看到任何吸引我的选项。相反,我选择用 Rust 写了一个小模块,提供了这种准确的操作:

https://github.com/KennethWilke/redis-setif

使用这个模块,你可以这样做:

SETIF <key> <expected> <new>
HSETIF <key> <field> <expected> <new>
2021-11-11 02:49:17
用户3348419
用户3348419

你可以使用SET命令来实现此操作,使用以下两个参数,详细信息请参考这里

GET - 返回存储在键中的旧字符串,不存在时返回nil。

NX - 只有在键不存在时才设置键。

由于Redis在运行另一个命令时不会执行任何命令,所以您可以以原子方式完成这两个操作。

2023-02-07 17:15:23