Sidekiq并发和数据库连接池

19
这是我的问题:每晚我需要处理约50k个后台作业,每个作业平均需要60秒。这些作业基本上是调用 Facebook、Instagram 和 Twitter 的 API 来收集用户的帖子并将它们保存在我的数据库中。这些作业由 Sidekiq 处理。
起初,我的设置是:
- 在 `sidekiq.yml` 中设置了 `:concurrency: 5` - 在我的 `database.yml` 中设置了 `pool: 5` - 在我的 Web 服务器(`puma`)配置中将 `RAILS_MAX_THREADS` 设置为 5
我的理解是:
- 我的 Web 服务器 (`rails s`) 将使用最多 5 个线程,因此最多只会有 5 个连接到我的数据库,这对于连接池设置为 5 是可以接受的。 - 我的 Sidekiq 进程将使用 5 个线程(因为并发设置为 5),这也是可以接受的,因为连接池设置为 5。
为了在同一时间内处理更多的作业并减少处理所有作业的全局时间,我决定将 sidekiq 并发性增加到 25。在生产环境中,我提供了一个 Heroku Postgres Standard 数据库,并设置了最大连接数为 120,以确保能够使用 Sidekiq 并发性。
因此,现在的设置是:
- 在 `sidekiq.yml` 中设置了 `:concurrency: 25` - 在我的 `database.yml` 中设置了 `pool: 25` - 在我的 Web 服务器(`puma`)配置中将 `RAILS_MAX_THREADS` 设置为 5。

我发现有25个 Sidekiq 工作进程在工作,但每个作业所需的时间都比较长(有时需要40分钟,而不是1分钟)!

实际上,我进行了一些测试并发现使用 Sidekiq 并发数为5、10或25时,在相同的时间内处理50个作业的结果是一样的。好像某个地方出现了5个连接的瓶颈。

我已经查看了Sidekiq文档和一些SO文章(sidekiq-是否稳定支持并发数 > 50?, Scaling sidekiq 网络架构:并发 vs 进程),但我无法解决我的问题。

所以我想知道:

  • 我的 Rails 的 database.yml 连接池和 Sidekiq 的 concurrency 是否理解正确?

  • 如何正确设置这些参数?


2
不是硬件/网络方面的人,但最终这是建立在您的硬件之上的。您有多少个处理器?例如,如果您有四个处理器,则可以将五个线程均匀分布在它们之间。当您将线程增加到25时,您最好的情况下每个处理器运行6个线程。我会逐渐增加线程,从应用程序的统计数据一直到硬件,以查看瓶颈发生的时间和位置。 - LAS
这可能对你有用 https://medium.com/appaloosa-store-engineering/active-record-sidekiq-pools-and-threads-8b11da0c082f - harshaaliaschinna
1个回答

3

为了帮助其他人,我在这里提供一个非常通用的指南:

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

例如,如果任务数量和核心数量之间存在很大差异,则调度程序将不断切换您的任务,并且实际上没有太多可获得的好处,作业只会花费相同或更长的时间。

以下是一个非常有趣的阅读链接,介绍了作业调度的工作原理 https://en.wikipedia.org/wiki/Scheduling_(computing)#Operating_system_process_scheduler_implementations

还有其他方面需要考虑,如数据存储访问,您的工作人员是否使用相同的表?它是否由锁定整个表的存储引擎支持,例如MyISAM?如果是这种情况,则不管您有多少工作人员同时运行,以及有足够的RAM和内核,他们都将排队等待正在运行的任何查询释放表上的锁,而他们本来应该一起工作的。 这也可能会发生在使用InnoDB等引擎的表上,它不会在写入时锁定整个表,但您可能有不同的工作人员访问相同的行(InnoDB使用行级锁定),或者只是一些大型索引不会锁定但会使表变慢。
我遇到的另一个问题与Rails有关(我假设您在使用它),在某些情况下会对RAM造成很大负担,因此您可能还想查看内存占用情况。
我的建议是打开日志并查看数据,您的工作人员在哪里花费了最多的时间?是网络层的问题(不太可能),还是在等待获得核心的访问权限?从数据存储中读/写?您的机器是否在交换?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接