一尘不染

在多线程Rails环境中使用Redis的最佳方法是什么?(彪马/ Sidekiq)

redis

我在应用程序中使用Redis,既用于Sidekiq队列,也用于模型缓存。

考虑到将要在Redis上使用的模型将同时从我的Web应用程序(通过Puma运行)和Sidekiq内部的后台作业中被调用,使模型具有Redis连接的最佳方法是什么?

我目前正在初始化程序中执行此操作:

Redis.current = Redis.new(host: 'localhost', port: 6379)

然后在整个代码中简单地使用Redis.current.get/ Redis.current.set(和类似的代码)…

据我了解,这应该是线程安全的,因为Redis客户端一次只能使用Monitor运行一个命令。

现在,Sidekiq有自己的Redis连接池,建议您这样做

Sidekiq.redis do |conn|
   conn.get
   conn.set
end

据我了解,这比仅使用Redis.current的方法要好,因为当多个线程遇到Redis时,它们没有多个线程在单个连接上互相等待。

但是,如何使从Sidekiq.redis获得的此连接对我的模型可用?(无需在每个方法调用中将其作为参数传递)

我无法在该块中设置Redis.current,因为它是全局的,并且我返回使用相同连接的每个人(加上它们之间的随机切换,这甚至可能是非线程安全的)

我应该将从Sidekiq.Redis获得的连接存储到线程局部变量中,并在各处使用该线程局部变量吗?

在这种情况下,在“ Puma”环境中我该怎么办?如何设置线程局部变量?

任何对此的想法都将不胜感激。

谢谢!


阅读 338

收藏
2020-06-20

共1个答案

一尘不染

您为应用程序代码使用单独的全局连接池。在您的redis.rb初始值设定项中输入以下内容:

require 'connection_pool'
REDIS = ConnectionPool.new(size: 10) { Redis.new }

现在,您可以在任何地方的应用程序代码中执行以下操作:

REDIS.with do |conn|
  # some redis operations
end

您最多可以有10个连接在您的puma /
sidekiq工作人员之间共享。如您所正确指出的那样,这将导致更好的性能,因为您不会让所有线程都争用单个Redis连接。

所有这些都记录在这里:https : //github.com/mperham/sidekiq/wiki/Advanced-
Options#connection-pooling

2020-06-20