Redis:使用 lua 和并发事务



两个问题

  1. Lua 脚本真的能解决 Redis 事务的所有情况吗?
  2. 来自一个客户端的异步事务的最佳实践是什么?

让我解释一下,第一个问题

Redis事务是有限的,无法unwatch特定的密钥,并且所有密钥在exec时都是不受监视的;我们仅限于给定客户端上的单个正在进行的事务。

我见过许多 redis 用户声称 lua 脚本是他们所需要的线程。甚至 redis 官方文档也声明他们可能会删除有利于 lua 脚本的事务。但是,在某些情况下这还不够,例如最标准的情况:使用 redis 作为缓存。

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

  1. 检查缓存 ->未命中
  2. 从数据库加载数据
  3. 以雷迪斯存储

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

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

继续讨论第二个问题(异步事务(

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

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

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

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

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

任何帮助表示赞赏!

在我的查询被升级到 redis 工程师后,我收到了以下内容:

嗨杰里米,

使用多个后端连接的方法将是处理问题的预期方法。我们认为多个后端连接没有任何问题,每个连接都使用乐观的 Redis 事务 (WATCH/MULTI/EXEC( - 没有机会"第二个事务会在应该失败的地方成功"。

使用 LUA 不太适合此问题。

此致敬意 瑞迪斯实验室团队

最新更新