我有一个 Rails 应用程序,它运行 50 个并发 Sidekiq 工作程序,从外部 API 接收数据,对其进行操作并将其存储在数据库中。 为了防止多次存储相同的数据,我创建了唯一的字符串,并将其存储到 Redis 中。
r = Redis.current
r.pipelined do
options.each do |o|
r.setex(o.generate_index, 1.hour, o.value)
end
end
在将新对象保存到数据库之前,我会检查 Redis 中是否存在它的唯一字符串:
r = Redis.current
option_ids = r.pipelined do
new_options.each do |o|
r.get(o.generate_index) # check if unique string already exists
end
end
我也在没有管道的情况下进行了测试,结果相同: Redis GET/SET 非常慢。 某些 GET 请求花费的时间超过一秒!
奇怪的事情:在运行 50 个 Sidekiq 工作线程时,Redis 性能很差,我从 shell 对 Redis 进行了基准测试,结果非常好:
r = Redis.current
10000000.times { puts Benchmark.realtime{ 1000.times{|i| r.get(i)} }}
输出如下:
0.197379041
0.192059888
0.196165358
0.207617425
0.198095963
0.195844917
0.211404108
0.203188759
0.208119298
0.184018683
没有基准测试花费的时间超过 0.5 秒。
我还尝试了 Redis.new 而不是 Redis.current,结果相同。
我不知道问题出在哪里
编辑: 经过更多测试和基准测试后,我注意到代码中的基准测试似乎阻碍了其他工作人员,并使他们的速度比预期慢得多。如果不进行基准测试,工作人员的速度可提高 10 倍。 此外,我的虚拟服务器似乎无法处理那么多工作人员。我的开发笔记本电脑可以容纳 100 名工作人员,并且性能仍然非常快。 而且,当负载很重时,Ruby 端的数据库查询似乎非常慢。 我对简单的 Mongoid 查找进行了基准测试,例如
time = Benchmark.realtime do
existing_option = Option.find_by(index: o.generate_index)
end
这些基准测试有时花费的时间超过一秒,但查询并未显示在 mongodb 慢速日志中(这意味着数据库上的实际查询花费的时间不到 100 毫秒)。 然而,纯 rubycode(没有数据库命中)似乎执行正常。 我想知道当我使用 Typhoeus Hydra 而不是 sidekiq 实现 HTTP 请求时,它的性能是否会更好。
最佳答案
一个线程接触 Redis 与 50 个线程有很大不同。
在您的工作线程中使用了 Sidekiq redis 连接池。它将更好地扩展。
Sidekiq.redis do |conn|
conn.pipelined do
...
end
end
关于ruby-on-rails - Sidekiq 工作线程中的 Redis 性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26568479/