redis-mutexで排他制御
例えばサーバが2台あったとして同じ時間に全く同じ内容のcronスクリプトが実行されるとする、その処理がDBのバッチ処理など大きなコストを必要とするなら両方のサーバで実行されるのは無駄でしかないし場合によってはデータの不整合なども発生するかもしれない。そんな時はredis-mutexを使って排他制御を行うことができる。
なにはともあれredisをインストール ※Macの場合のインストール方法です
$ brew install redis
redis-mutexというgemをインストール。
$ gem install redis-mutex Successfully installed redis-mutex-2.1.1
排他制御を行いたい部分をRedis::Mutex.with_lockブロックで囲むだけでOK、簡単ですね。
#!/usr/bin/env ruby require 'redis-mutex' def main Redis::Classy.db = Redis.new(host:"localhost", port: "6379") Redis::Mutex.with_lock(:your_lock_name, block: 0) do sleep 5 puts "Do exclusively!" end rescue puts 'failed to acquire lock!' end if __FILE__ == $0 main() end
このスクリプトをコンソールを2つ開いてそれぞれ実行すると最初に実行したほうだけwith_lockブロックで囲んだコードが実行されます。
# 1番目に実行 $ ./redis-mutex-example.rb Do exclusively! # 2番目に実行 $ ./redis-mutex-example.rb failed to acquire lock!
実装にはredisのSETNXとSETEXを使っていると思われる。redisはrebuld.fmでredis-mutexの作者の江島さんが言ってたようにサーバの垣根をも超えたスーパーグローバル変数みたいな感じの使い方ができるし、リアルタイムランキングの実装にも向いてるし、RDBMSではちょっとやりにくい部分をうまく補ってくれるツールな感じ。AWSのElasticacheでもサポートされて今後どんどん伸びていきそうなKVSですね。