【发布时间】:2016-04-20 03:16:17
【问题描述】:
我正在使用 Sidekiq(在 Heroku 和 Puma 上)异步发送电子邮件,并希望使用 Redis 来保存计数器和缓存模型。
RedisCloud 的免费计划包括 30 个 Redis 连接。我不清楚如何管理:
- Sidekiq 使用的 redis 连接
- 模型中使用的 redis 连接(缓存和计数器)
Sidekiq 客户端大小配置如下:
Sidekiq.configure_client do |config|
config.redis = {url: ENV["REDISCLOUD_URL"], size: 3}
end
如果我理解正确,Puma 会分叉多个进程,在我的例子中是 2 个,这将导致:
2 (Puma Workers) * 3 (size) * 1 (Web Dyno) = 6 connections to redis used to push jobs.
Sidekiq 服务器
Sidekiq 采用 2 个连接(或版本 4 中的 5 个),将并发设置为 10 将默认服务器大小为 12 或 15。
如果我想使用所有剩余的可用连接 (30 - 6 = 24),我可以设置:
Sidekiq.configure_client do |config|
config.redis = { size: 19 }
end
redis 连接总数为 19 + 5 (Sidekiq 4) = 24,使用默认的并发 25 即可。 正如 Mike Perham 所说,并发性不得超过(服务器池大小 - 2)* 2。
现在,让我感到困惑的地方是在 Sidekiq 中使用 Redis。
# initializers/redis.rb
$redis = Redis.new(:url => uri)
每当我在模型或控制器中使用 Redis 时,我都会这样调用:
$redis.hincrby("mycounter", "key", 1)
据我了解,当调用 $redis.whateverFunction 时,所有 puma 线程在单个 Redis 连接上相互等待。
在这个答案What is the best way to use Redis in a Multi-threaded Rails environment? (Puma / Sidekiq) 中,推荐的方法是使用与 Sidekiq Wiki https://github.com/mperham/sidekiq/wiki/Advanced-Options#connection-pooling 相关的 connection_pool gem
require 'connection_pool'
$redis = ConnectionPool.new(size: 10) { Redis.new }
如果我理解正确,那么 $redis.whateverFunction 将拥有自己的 10 个连接池,sidekiq 拥有自己的连接工作池,现在将设置新的总共 20 个 redis 连接(30 个(可用总数) - 10(redis 模型连接),需要更改 Sidekiq 客户端和服务器大小。
如何确定模型/控制器 redis 连接所需的连接池大小(此处为 10)?既然 Redis 是单线程的,那么增加连接池实际上是如何提高 redis 操作性能的呢?
对此的任何想法都会有很大帮助。 谢谢!
【问题讨论】:
标签: ruby multithreading ruby-on-rails-4 redis sidekiq