Rails Rails job 默认的 Active Job 如何不并发调同一方法 顺序执行方法

kastrcn · 2018年11月08日 · 最后由 Rei 回复于 2018年11月11日 · 1901 次阅读

问题

X-Y Problem http://coolshell.cn/articles/10804.html

x:

如何不并发调同一方法 顺序执行方法

y:

默认的 job 如何设置进行排队执行 perform 里面的任务 等上一个执行完才能执行下一个任务如何执行 而不是同时执行

queue_as :default
def perform(*args)
  # Do something later
end

解决办法

1. 加锁

文件锁、变量锁、redis 锁

2.设置线程

config.active_job.queue_adapter = ActiveJob::QueueAdapters::AsyncAdapter.new(
  min_threads: 1,
  max_threads: 1
)

3.方法结束前入队

在这个任务完成的时候,入队下一个任务,这样可以得到间隔时间恒定的任务。

采取方案

在这个任务完成的时候,入队下一个任务,这样可以得到间隔时间恒定的任务。

什么场景会有这样的需求用于 Active Job

顺着楼主思路回答就是添加配置:

config.active_job.queue_adapter = ActiveJob::QueueAdapters::AsyncAdapter.new(
  min_threads: 1,
  max_threads: 1
)

X-Y Problem http://coolshell.cn/articles/10804.html

生产环境使用 Sidekiq 的话可以创建一个长度为 1 的队列专门用来跑这类任务,这样不会影响到并行的其它任务。有这种需求直接在开发环境就用 Sidekiq 吧

@Rei 多谢 根据 2 楼链接加上 x

定时处理某个文件夹下 一批文件 读取=》解析=》存数据库

一开始用的 whenever 定时器定时器处理

当之前的定时任务没有执行完成又开了新的定时任务

这样会造成同时有两个线程在读取一份文件

后来查到 Active Job 有排队功能 以为会等上一个执行完才能执行下一个任务 但并不是


x:

如何不并发调同一方法 顺序执行方法

gem 'sidekiq-unique-jobs'

kastrcn 回复
  1. flock or redis lock
  2. k8s job 可以配置

看看具体的 adaptor 是如何实现的

ActiveJob 目的是为了并发/异步执行,改成长度为 1 的队列,未免削足适履,更合适的解决方案是用 flock,用 Exclusive lock 和 None blocking 来保证一个文件只能被一个 JobWorker 处理,同时也有并发处理多文件的能力

f = File.open(...)
if f.flock(File::LOCK_EX | File::LOCK_NB)
  ...
end

还有一种做法是在这个任务完成的时候,入队下一个任务,这样可以得到间隔时间恒定的任务。

kastrcn 关闭了讨论。 11月14日 11:55
需要 登录 后方可回复, 如果你还没有账号请 注册新账号