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

What is the best way to use Redis in a Multi-threaded Rails environment? (Puma / Sidekiq)

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

让我的模型可以使用 Redis 连接的最佳方法是什么,考虑到将使用 Redis 的模型将从我的 Web 应用程序(运行 通过 Puma)和后台调用Sidekiq 内的职位?

我目前正在我的初始化程序中这样做:

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

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

据我所知,这应该是线程安全的,因为 Redis 客户端使用监视器一次只运行一个命令。

现在,Sidekiq 有自己的 Redis 连接池,推荐做

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

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

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

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

我是否应该将从 Sidekiq.Redis 获得的连接存储到线程局部变量中,然后在任何地方使用该线程局部变量?

在那种情况下,我在 "Puma" 上下文中做什么?如何设置线程局部变量?

非常感谢对此的任何想法。

谢谢!

您为应用程序代码使用了单独的全局连接池。在你的 redis.rb 初始值设定项中放入这样的东西:

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

现在在您的应用程序代码中的任何地方,您都可以这样做:

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

您最多可以在 puma/sidekiq 名员工之间共享 10 个联系人。这将带来更好的性能,因为正如您正确注意到的那样,您不会让所有线程都在争夺单个 Redis 连接。

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