RedisのPHPは一人だけがアクションを動作させることができる一方で、時々PHPのロックの概念を使用して、ビジネスプロセスを記述し、良い友人です。今回は、ロックを使用する必要があります。いくつかの方法は、データベースのロックを利用して、PHPがロック付きメモリ内に、ロックが飼育係を使用することができないではない、ロックし、比較的大きな消費、この時間は、我々は一般的にRedisのロック機構を行うことを選択しますがあります。
setnx
Redisのは、その文字列最も簡単なデータ構造でロックします。valは、おそらくあなたは、ロックの使用を高めるために覚えているだろうセット操作はdelコマンドを使用することでロック解除、期限切れ期限切れ時にロックが存在しない場合、次のように、擬似コードは次のとおりです:このコマンドがあるときに初めて、ロック操作は、一般的に、setnxを使用しています
if (Redis::setnx("my:lock", 1)) { Redis::expire("my:lock", 10); // ... do something Redis::del("my:lock") }
実際には、ここでの問題は、問題が真ん中setnxにあり、彼らがクラッシュし、他の行為ならば有効期限が切れ、多分このロックが解除されることはありません。更なる最適化は、ロックおよびタイムスタンプに格納することができます。タイムスタンプの長さを決定します。
セットする
公式勧告は今直接 設定し たロックを達成します。私たちは、このようになりますこと、setnxを交換するには、setコマンドを使用することができます
もし(Redisの::セット( "私:ロック"、1、 "NX"、 "EX"、10 )){ ... ん何か のRedis ::デル( "私:ロック" ) }
上記のコードは、私:ロックはロックが存在しない場合にのみ、10セットアップの有効期限を設定した後に完了している場合は1に設定されています。
これは、ロック機構を獲得することですが、ロックを削除するには直接使用デルのメカニズムが間違っています。それは、誤って削除し、他の誰かのロックにつながる可能性があるため。
例えば、私の10Sのロックは、私は長い10秒以上の時間を扱う、10Sに、ロックは自動的に期限切れになる、と他の人が連れ去らし、再びそれをロックされていました。したがって、この時間は、私は再びロックが人によって設立され、削除のRedis ::デルを呼び出します。
公式ロック解除コマンドはまた、推奨のluaスクリプトを使用することが推奨され、最初に行わ取得、その後、デル
プログラムは次のようになります。
$トークン = ランド(1、100000 )。 ファンクションロック(){ 返すのRedisを::セット( "私:ロック"、$トークン、 "NX"、 "EX"、10 ); } 関数のアンロック(){ $スクリプト = ` 場合 redis.call == ARGV [1(KEYS [1]、 "GET")] 次に、 戻り redis.call( "デル" KEYS [1 ]) 他 戻り 0 端 ` 返す Redisのを:: のeval($スクリプト、 "私:ロック"、$トークン) } の場合(ロック()){ //何かを行う ロック解除を(); }
トークンここでの私のRedisにロックは、乱数である:現存するロックトークンがある最初のトークンをどのようにロックを取得する場合ならば、アンロックは、と私はトークンを削除することは一貫説明ですこのロックは、それ以外の場合は、私はそれには何もすべきではない、他の人が設定され、ロックの期限が切れていることを示して、私の前に設定されています。
だから、:ロックを達成した直接設定、setnxを使用しないでください。