RubyでRedis使ってて便利だったgem
・redis-objectsの「Redis::Lock」
redis-objectsがまず便利なんだけど、その中で「Redis::Lock」。
処理が平行して実行されないようにしたい時など、処理の一部をロックしたい時に役立つ。
これは、redis公式の
これに則ってる。
簡単にいうと、SETNX(セットされていたかどうかで0or1が帰る処理)でキーを取得して、取得されていたら解放されるまでポーリング(もしくはタイムアウトを設定してタイムアウトさせる)
require 'redis-objects' @lock = Redis::Lock.new('lock-key', timeout:0.1) begin @lock.lock do # lockの最初に"setnx" "lock-key"を実行し、lockを獲得 sleep(10) end # lockの最後に"del" "lock-key"を実行し、lockを解放 rescue Redis::Lock::LockTimeout p 'ロック獲得できない時の処理' end
ちなみにlockのtimeoutを設定しない場合、timeout:5(秒)となる。
また、0.1秒ごとにSETNXでキーの解放をチェックする。
`lock': Timeout on lock lock-key exceeded 5 sec (Redis::Lock::LockTimeout)
・Resqueで同じパラメータのものはenqueしない「Resque::Plugins::UniqueJob」
https://github.com/jayniz/resque-loner
Redisというか、Resqueなんだけど。
同じパラメータのものは一度しかenqueしてほしくない時に使う。
仕組みとしては、ざっくり言うと「queue名」「パラメータ(をmd5等で一意のIDにしたもの)」をキーとしたものををenque時にredisにSETし、重複するものが既にSETされていればenqueしないという仕組み。
resque:loners:queue:cache_sweeps:job:5ac5a005253450606aa9bc3b3d52ea5b
ただ、これはenqueueの重複を防ぐだけでqueueの重複実行を防ぐものではない(queueが取り出され実行された時点で、次のenqueueは受け付けるので)。
なので、重複実行には上記のlock等を使うべき。