遵循这些规则,以提高你的Sidekiq体验:
1.保证任务的参数小而简单
sidekiq将传递给perform_async的参数不变的传递给Redis。我见过很多人这样做:
quote = Quote.find(quote_id)
SomeWorker.perform_async(quote)
你这样做是把整个Quote对象序列化后传递给Redis,如果你的队列在复制quote对象的同时quote对象发生了变化怎么办呢?不要这样保存带有状态的对象,而是应该保存一个标识符,当你真正需要这些对象的时候,在你执行的方法中再去查找对象。
SomeWorker.perform_async(quote_id)
传递给perform_async的参数必须由简单的JSON数据类型组成:string, integer, float, boolean, null, array, hash。Sidekiq client API使用JSON.dump向Redis发送数据。Sidekiq server从Redis获取JSON数据,再通过JSON.load把数据转换到Ruby类型,然后再传递给你执行的方法。不要传递符号,命名参数或者复杂的Ruby对象(比如日期或时间),因为在dump/load转换的过程中,他们可能会改变。(不知道这么翻译对不对,原话如下:Don’t pass symbols, named parameters or complex Ruby objects (like Date or Time!) as those will not survive the dump/load round trip correctly.)
2.保证任务的幂等性和事务性
(幂等百科解释传送门)
幂等的意思是你的任务可以被安全的多次执行,比如,通过错误重试功能,可能你的任务执行了一半的时候抛出了一个错误,然后一次次的执行直到最后执行成功。比如说,你有一个任务,功能是取消一个信用卡交易并且邮件通知卡主,让他们知道费用已经退还了:
def perform(card_charge_id)
charge = CardCharge.find(card_charge_id)
charge.void_transaction
Emailer.charge_refunded(charge).deliver
end
如果由于一个bug导致邮件发送失败会怎样?void_transaction方法能处理费用已经退还的这种情况吗?你可以通过数据库事务来保证错误发生后,你的数据能够回滚,或者你也可以自己写代码来保证。记住,sidekiq会至少执行一次你的任务。
3.拥抱并发
Sidekiq是专门为并发而设计的,所以好好设计你的任务,这样你就可以并行执行很多任务了。Sidekiq有基本的并发调整功能 (e.g. targeting a sidekiq process at a queue with a defined number of threads) but your system architecture is much simpler if you don’t have such specialization.
你可以通过一个连接池来限制一个资源受限server的连接总数。
Sidekiq will not provide features which hack around a lack of concurrency in your jobs.
英语不好,翻得累死了。