Redis:原子获取和条件集

Redis: Atomic get and conditional set

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

是否可以使用 Redis 来完成此操作?

我看过有关 MULTI 操作的文档,但我还没有看到 MULTI 操作中的条件操作。其他人可以为此提供的任何建议将不胜感激!

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

我最终使用了 redlock-py, an implementation of the redlock algorithm that the Redis docs recommend for creating write locks: https://redis.io/topics/distlock。对于希望在 Redis 中创建类似写锁的任何人来说,链接的文章都是很棒的读物。

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' ]
  ]
}))

使用此脚本,我们从项目中删除了所有自定义脚本。

我遇到这个 post 寻找类似类型的功能,但我没有看到任何吸引我的选项。我选择用 Rust 编写一个小模块来提供这种确切类型的操作:

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

使用此模块,您可以通过以下方式执行此操作:

SETIF <key> <expected> <new>
HSETIF <key> <field> <expected> <new>