首页 > 解决方案 > 使用 Sidekiq 缓冲和批处理作业

问题描述

我有一个运行非常频繁的 sidekiq 作业,每个作业使用 Rails 中的 ActiveRecord 更新单个 MySQL 数据库记录:

HTTP request
  -> RecordUpdateWorker(id, value)
  -> Record.find(id).update(value: value)

它导致数据库中的死锁锁定超时。似乎没有重复的工作,但 ID 彼此靠近,所以我只能猜测这是由于Gap Locks造成的。无论如何,我对解决方案的想法是“缓冲”作业并减少批量执行它们的频率。无需立即执行它们,因此对于此用例,它不会引起问题。

HTTP Request
  -> Add Record to Buffer
  -> Occasionally run RecordUpdateWorker()
  -> Record.where(id: ids_from_buffer).update_all(value: values_from_buffer)
  # I'd have lots of flexibility to tune the transaction size, etc here 

有什么方法可以通过 sidekiq 或 sidekiq 插件来实现这一点?我已经在其他地方使用批处理(Sidekiq Pro),但它似乎不适合这个用例。一个明显的解决方案是仅使用自定义 Redis 队列和重复作业(或类似until_and_while_executingsidekiq-unique-jobs 中的锁定),但如果有标准方法来完成此操作,我宁愿使用它。

我已经查看了 sidekiq 文档,包括专业版和企业版,但没有找到与此描述完全匹配的任何内容。

编辑:将死锁更改为锁定超时,因为我不确定这是一个死锁场景。

标签: ruby-on-railsrubysidekiq

解决方案


推荐阅读