0

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

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

选项 1.使用事务

如果我理解正确,NodeJS 伪代码将如下所示:

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

我在上面看到的坏事是:

  • 尝试捕获块
  • 在 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 绝对是一种更强大的技术。如果我在上述假设中错了,请纠正我。如果有人提供解决类似问题的代码示例,那也很棒,因为我找不到。

4

1 回答 1

0

当您想要协调一组分布式组件以创建原子操作时, Redlock很有用。

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

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

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

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

于 2020-12-09T13:05:21.473 回答