【问题标题】:Using Redis transaction vs redlock to solve the Lost Update Problem使用 Redis 事务 vs redlock 解决丢失更新问题
【发布时间】:2021-03-20 02:02:42
【问题描述】:

我正在使用具有 2 个以上节点的 Redis 集群。我试图找出最适合处理并发的工具 - 事务或锁定。事务是well documented,但我没有找到关于redlock 的最佳最佳实践示例。我还想知道为什么存在两种工具,每种工具的用例是什么。

为简单起见,假设我想做一个并发增量,而 Redis 中没有 INCR 命令。

选项 1。使用事务

如果我理解正确的话,NodeJS 伪代码应该是这样的:

transactIncrement = async (key) => { 等待 redisClient.watch(key); 让值 = redisClient.get(key); 价值 = 价值 + 1; const multi = await redisClient.multi(); 尝试 { 等待 redisClient.set(key, value, multi); 等待 redisClient.exec(multi); } 抓住 (e) { // 很可能是因为事务失败而抛出的错误 // TODO: 考虑是否在每种情况下都重新启动是个好主意,这会引入潜在的无限循环 // 不管怎样,重启 等待交易增量(键); } }

我在上面看到的坏事是:

  • try-catch 块
  • 在 redis 集群上使用具有多个键的事务的可能性受到限制

选项 2。红锁

尝试锁定已经锁定的资源是否不会立即导致失败?那么redlock会在出错之前尝试N次?

如果为真,那么这是我的伪代码:

redlockIncrement = async (key) => {
  await redlock.lock(key, 1);  
  // below this line it's guaranteed that other "threads" are put on hold 
  // and cannot access the key, right? 
  let value = await redisClient.get(key);
  value = value + 1;
  await redisClient.set(key, value);
  await redlock.unlock(key);
}

总结

如果我做对了,那么 redlock 绝对是一种更强大的技术。如果我在上述假设中错了,请纠正我。如果有人提供解决类似问题的代码示例,那也很棒,因为我找不到。

【问题讨论】:

    标签: node.js redis concurrency redlock


    【解决方案1】:

    Redlock 是useful,当您有一组分布式要协调以创建原子操作的组件时。

    您不会将它用于影响单个 Redis 节点的操作。这是因为 Redis 已经有了更简单、更可靠的方法来确保使用其单线程服务器的命令的原子性:事务或脚本。 (您没有提到Lua scripting,但这是创建自定义原子命令的最强大方式。

    由于INCR 在单个键上运行,因此在单个节点上运行,实现它的最佳方法是使用简单的 Lua 脚本。

    现在,如果您想使用跨多个节点的命令序列,事务和脚本都将不起作用。在这种情况下,您可以使用 Redlock 或类似的分布式锁。但是,您通常会在 Redis 设计中尽量避免这种情况。具体来说,您将使用hash tags 强制某些键驻留在同一节点上:

    哈希标签是一种确保在同一个哈希槽中分配多个键的方法。这用于在 Redis Cluster 中实现多键操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多