前提
- 排他制御: 同時処理を防ぐ仕組み(参考: https://wa3.i-3-i.info/word11316.html)で、セマフォで実現。
- セマフォ: 同時処理可能なプログラム数を管理する仕組み(参考: https://wa3.i-3-i.info/word13357.html)
- ミューテックス: 0~1しかないセマフォで、デッドロックを防止する仕組みが組みこまれているもの(参考: https://wa3.i-3-i.info/word13360.html)。排他制御で使われる。
- ブロッキング・ノンブロッキング: ざっくりとは同期処理・非同期処理のこと。
概要 gem「redis-mutex」
Redisを使ったRubyでのミューテックス。
同期処理・非同期処理ともにサポート。
例えば以下のように使う。
# [引数]
# - lock_name: ロック名
def sample_process(lock_name)
# ロック名「lock_name」のロック状態を獲得しようとし、獲得できたらブロック内の処理を実行。設定時間内に獲得できなかったら例外を返す
RedisMutex.with_lock(lock_name) do
# <ロック状態を獲得できたときにさせたい処理>
end
rescue RedisMutex::LockError
# <ロック状態を獲得できなかったときにさせたい処理>
end
ロック状態の獲得試行に際し、デフォルトでは以下の設定になっている。
- ロック状態が解放されるまで待てる最大の時間は1秒で、0.1秒ごとにロック状態が解放されたかを確認
- 1処理のロック状態は最大10秒で期限切れ(例外発生しちゃったりとかで元々ロックを保持していた処理がロックを解放しなかったときへの対応。このとき、元々ロックを保持していた処理がっもし続いているならばそのまま進むっぽいぞ・・・ソース見た感じ)
通常10秒以内にロック対象の処理は終わって、ロック解放されるっしょ!解放されてないってことは、例外発生して元々ロックを保持してた処理が死んでるってことっしょ!という前提で実装されてる気がする。
処理が死んでなくて10秒以上経過するようなケースがありうるならば、別途対応しないといけなさそう。