【问题标题】:Redis: Atomic get and conditional setRedis:原子获取和条件集
【发布时间】:2018-10-22 20:49:18
【问题描述】:

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

Redis 可以做到这一点吗?

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

【问题讨论】:

  • 您可以使用 Lua 脚本在 redis 端完成所有操作:redis.io/commands/eval
  • @ChrisTanner 将此作为答案,我会投票赞成
  • 如果其他人也希望创建写锁,这是一个很好的阅读:redis.io/topics/distlock

标签: lua redis conditional atomic


【解决方案1】:

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

【讨论】:

【解决方案2】:

我最终使用了redlock-py,这是一种 Redlock 算法的实现,Redis 文档推荐用于创建写锁:https://redis.io/topics/distlock。对于希望在 Redis 中创建类似写锁的任何人来说,链接的文章都是很棒的读物。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

      有了这个模块,你可以通过:

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

      【讨论】:

        猜你喜欢
        • 2018-09-30
        • 1970-01-01
        • 2021-01-05
        • 2014-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-21
        • 1970-01-01
        相关资源
        最近更新 更多