【问题标题】:Redis: Using lua and concurrent transactionsRedis:使用 lua 和并发事务
【发布时间】:2019-01-20 17:17:09
【问题描述】:

两个问题

  1. lua 脚本真的可以解决所有 redis 事务的情况吗?
  2. 来自一个客户端的异步事务的最佳做法是什么?

让我解释一下,第一期

Redis 事务受到限制,无法unwatch 特定键,并且所有键在exec 上都无人关注;我们仅限于给定客户端上的单个正在进行的交易。

我见过threads,许多redis 用户声称他们只需要lua 脚本。甚至 redis 官方文档也声明他们可能会删除事务以支持 lua 脚本。但是,也有这样不够的情况,比如最标准的情况:使用redis作为缓存。

假设我们想在 redis 中缓存一些来自持久数据存储的数据。这是一个快速的过程:

  1. 检查缓存 -> 未命中
  2. 从数据库加载数据
  3. 存储在 redis 中

但是,如果在第 2 步(加载数据)和第 3 步(存储在 redis 中)之间,数据被另一个客户端更新了怎么办?

存储在 redis 中的数据将是陈旧的。所以......我们使用redis事务对吗?我们在从 db 加载之前watch 密钥,如果密钥在存储之前在其他地方更新,存储将失败。伟大的!但是,在原子 lua 脚本中,我们无法从外部数据库加载数据,因此此处不能使用 lua。希望我只是遗漏了一些东西,或者我们的流程有问题。

继续第二期(异步事务)

假设我们有一个 socket.io 集群,它处理各种消息和游戏请求,用于服务器和客户端之间的高速通信。这个集群是用 node.js 编写的,适当地使用了 Promise 和异步概念。

假设有两个请求到达我们集群中的一个服务器,这需要在 redis 中加载和缓存数据。使用上面的事务,可以监视多个键,并且多个 multi->exec 事务将在一个 redis 连接上以重叠的顺序运行。一旦第一个 exec 运行,所有被监视的键​​都将不被监视,即使另一个事务仍在运行。这可能允许第二个事务在它应该失败时成功。

这些重叠可能发生在同一服务器上发生的完全不同的请求中,如果需要同时加载多种数据类型,有时甚至可能发生在同一个请求中。

这里的最佳做法是什么?我们是否需要为每个单独的事务创建单独的 redis 连接?似乎我们会损失很多速度,如果是这种情况,我们会看到许多连接仅从一台服务器创建。

作为替代方案,我们可以使用 redlock / mutex 锁定代替 redis 事务,但相比之下这很慢。

任何帮助表示赞赏!

【问题讨论】:

    标签: redis transactions


    【解决方案1】:

    在我的查询上报给 redis 工程师后,我收到了以下信息:

    嗨,杰里米,

    您使用多个后端连接的方法将是处理问题的预期方法。我们没有看到多个后端连接有任何问题,每个都使用一个乐观的 Redis 事务 (WATCH/MULTI/EXEC) - “第二个事务在它应该失败的地方成功”是不可能的。

    使用 LUA 不适合解决这个问题。

    最好的问候, Redis 实验室团队

    【讨论】:

      猜你喜欢
      • 2015-10-27
      • 1970-01-01
      • 2013-08-28
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 2021-01-20
      • 2012-05-18
      相关资源
      最近更新 更多