Sidekiq 并发和数据库连接池



这是我的问题:每天晚上,我必须处理大约 50k 个后台作业,每个作业平均需要 60 秒。这些工作基本上是调用Facebook,Instagram和Twitter API来收集用户的帖子并将其保存在我的数据库中。作业由 sidekiq 处理。

起初,我的设置是:

  • :concurrency: 5sidekiq.yml

  • pool: 5在我的database.yml

  • 在我的 Web 服务器 (puma( 配置中设置为 5RAILS_MAX_THREADS

我的理解是:

  • 我的 Web 服务器 (rails s( 将使用最多 5 个线程,因此最多 5 个连接到我的数据库,这是可以的,因为连接池设置为 5。

  • 我的 sidekiq 进程将使用 5 个线程(因为并发设置为 5(,这也可以,因为连接池设置为 5。

为了在同一时间内处理更多作业并减少处理所有作业的全局时间,我决定将 sidekiq 并发增加到 25。在生产中,我配置了一个最大连接数为 120 的 Heroku Postgres 标准数据库,以确保我能够使用 Sidekiq 并发。

因此,现在的设置是:

  • :concurrency: 25sidekiq.yml

  • pool: 25在我的database.yml

  • 在我的 Web 服务器 (puma( 配置中设置为 5RAILS_MAX_THREADS

我可以看到 25 名 sidekiq 工人正在工作,但每项工作花费的时间更多(有时超过 40 分钟而不是 1 分钟(!?

实际上,我一直在做一些测试,并意识到以 5、10 或 25 的 sidekiq 并发处理 50 个作业会导致相同的持续时间。好像不知何故,某处出现了 5 个连接的瓶颈。

我已经检查了 Sidekiq 文档和 SO 上的其他一些帖子(sidekiq - 并发> 50 稳定吗?,扩展 sidekiq 网络架构:并发与进程(,但我无法解决我的问题。

所以我想知道:

  • 我对pool和 Sidekiqdatabase.yml连接的轨道的理解是否正确concurrency

  • 设置这些参数的正确方法是什么?

把它放在这里,以防其他人可以使用快速、非常通用的指针:

有时,增加并发工作线程的数量可能不会产生预期的结果。

例如,如果任务数量和内核数量之间存在很大差异,调度程序将继续切换您的任务,并且并没有太多收获,作业只需要大致相同或更多的时间。

这里有一个关于作业调度如何工作的相当有趣的读物的链接 https://en.wikipedia.org/wiki/Scheduling_(计算(#Operating_system_process_scheduler_implementations

还有其他方面需要考虑,例如数据存储访问,您的工作人员是否使用相同的表?它是否由锁定整个表的存储引擎(例如MyISAM(提供支持?如果是这种情况,那么如果您有 100 个工作线程同时运行,并且有足够的 RAM 和内核,它们都将排队等待正在运行的任何查询以释放他们都应该使用的表上的锁。 使用InnoDB等引擎的表也可能发生这种情况,该引擎不会在写入时锁定整个表,但您可能有不同的工作线程访问相同的行(InnoDB使用行级锁定(或只是一些不锁定但减慢表速度的大型索引。

我遇到的另一个问题与 Rails(我假设您正在使用(有关,在某些情况下会对 RAM 造成相当大的损失,因此您可能还想查看您的内存占用。

我的建议是打开日志记录并查看数据,您的员工花费最多时间的地方?它是网络层上的东西(不太可能(,它是否在等待访问核心?从数据存储中读取/写入?您的机器正在交换吗?

最新更新