推奨読書:350 Javaインタビューの質問:JVM + TCP +マルチスレッド+分散+アルゴリズム+メッセージキュー
テキストストレート
redisロックに関しては、次の3つが最も頻繁に使用される頻度の高い単語です。
- setnx
- redLock
- 再分配
setnx
実際、現在一般的に参照されているsetnx setnx key value
コマンドは、redis コマンドではありません。
Redisのものに代わって一般的な設定でコマンドをNX使用するパラメータ、設定このコマンドは現在、非常に多くのオプションパラメータをサポートしています。
SET key value [EX seconds|PX milliseconds] [NX|XX] [KEEPTTL]
もちろん、記事ではApiを書きませんが、基本的なパラメーターはまだ不明です。公式Webサイトにジャンプできます。
上の図は、作成者が描いたsetnxの一般的な原理です。主に、キーが存在せず正常に設定されるという機能に依存しています。プロセスAがロックを取得します。ロックのキーが削除されない場合、プロセスBは当然ロックを取得できません。
なぜそれPX 30000
を使用してタイムアウトを設定するのですか?
恐れているプロセスは不合理なああ、ロックは、それを解放するのを待ちませんでした崩壊の場合にロックを取得することができないシステムで、その結果、離れてロックする直接その場で、。
それでも、絶対に確実であるという保証はありません。
場合は、プロセスAロックリソースの操作中や不合理、タイムアウトIセットよりも、それが原因となり、他のプロセスがロックを取得するために、および他のプロセスAの counterassaultedバックは、他のプロセスをロックすることです示すように、削除されました:
まだ同じ状況ですが、 T5 時間をロックタイムアウトに変更し 、redisによってリリースされました。
プロセスBはT6でしばらくの間ロックを取得し、プロセスAは操作を完了し、delを返してロックを解放しました。
場合、プロセスBの動作が完了すると、時間がロック(図時刻T8)を解放します。
実際にロックを見つけるのは良いことです。プロセスCがT7でロックに成功すると、プロセスBはプロセスCのロックを解放します。そのため、上の工程Cを解放することができるプロセスDのロックを、プロセスD ...(入れ子人形の禁止)、どのような特定の結果を知られていません。
したがって、setnxを使用する場合、キーはメイン関数ですが、値をアイドルにすることはできません。一意のクライアントIDを設定するか、UUIDなどの乱数を使用できます。
ロックを解除するときは、最初に値を取得して、現在のプロセスによって追加されたロックであるかどうかを確認してから、削除します。疑似コード:
String uuid = xxxx;
// 伪代码,具体实现看项目中用的连接工具
// 有的提供的方法名为set 有的叫setIfAbsent
set Test uuid NX PX 3000
try{
// biz handle....
} finally {
// unlock
if(uuid.equals(redisTool.get('Test')){
redisTool.del('Test');
}
}
复制代码
今回は安定しているように見えますか?
逆に、今回の問題はより明白であり、finallyコードブロックでは、getとdelはアトミック操作ではなく、プロセスのセキュリティ問題が残っています。
なぜそれほど多くの質問があるのですか?
まず、不利な点を明確にすることによってのみ、それらをより良く改善することができます。
2番目のポイントは、実際には、上記のコードの最後の部分はまだ多くの企業で使用されています。
大小のプロジェクトのパラドックス:大企業は仕様を実装していますが、中小企業や小規模プロジェクトは厳密ではありませんが、同時実行性は高くなく、問題の可能性は大企業と同じくらい低くなっています。-魯迅
次に、ロックを削除する正しい姿勢の1つは、luaスクリプトを使用してredis eval / evalshaコマンドを実行できることです。
-- lua删除锁:
-- KEYS和ARGV分别是以集合方式传入的参数,对应上文的Test和uuid。
-- 如果对应的value等于传入的uuid。
if redis.call('get', KEYS[1]) == ARGV[1]
then
-- 执行删除操作
return redis.call('del', KEYS[1])
else
-- 不成功,返回0
return 0
end
复制代码
luaスクリプトはっきりそれを言うためにアトミック理由を保証することができます:
luaで花を書いても、実行は実行するコマンド(eval / evalsha)であり、コマンドは完了せず、他のクライアントはそれを見ることができません。
それはとても面倒なので、もっと良いツールはありますか?それは、redissonについてです。
redissonを紹介する前に、現在のsetnxがsetnxコマンドを直接言うのではなく、デフォルトでnxパラメーターを使用してsetコマンドを参照する理由を簡単に説明します。
redisのバージョンは2.6.12より前であるため、setはnxパラメーターをサポートしていません。ロックを完了するには、次の2つのコマンドが必要です。
1. setnx Test uuid
2. expire Test 30
复制代码
つまり、キーを置くことと有効期間を設定することは2つの別個のステップであり、理論的には、実行直後は1であり、プログラムがハングし、原子性は保証されません。
ただし、早くも2013年、つまり7年前に、Redisはバージョン2.6.12をリリースし、公式Webサイト(setコマンドページ)でも「SETNX、SETEX、PSETEXは将来のバージョンで非推奨になる可能性がある」と述べています。そして、完全に削除します。
著者は暴力団の記事を読んだことがあり、初心者向けの小さなインタビューガイドがあります。特定のテキストは忘れられており、一般的な意味は次のとおりです。
redisロックに関しては、setnxから始めて、最後にsetコマンドを使用してパラメーターを追加できます。これにより、自分の知識を反映できます。
以前にこの記事を読んでこのルーチンを学んだことがある場合は、この記事の作成者として、リマインダーを追加したいと思います。
勤務年数にご注意ください!まず、廃業寸前の公式サイトの指示に答えて、7年前のsetコマンドの「新機能」を紹介しましょう。卒業したばかりの人が言ったら、面接官は渡ったと思います。
あなたはロードテスターを設定し、インタビュアーもあなたを設定します。-vt Wozkisod
再分配
RedissonはJavaのredisクライアントの 1つであり、redisを簡単に操作するためのいくつかのAPIを提供します。
しかし、このクライアントを再検討すると、少し強力になる可能性があります。著者は、公式Webサイトの画像の一部のみを切り取りました。
機能のリストが多すぎると言うことができる、それはまた、いくつか見ていないJUCの下のクラスのパッケージ名を、のような私たちは分散型バージョンに従事するredissonヘルプ、AtomicLong、直接RedissonAtomicLongライン上で、クラスの名前も新しいレコードを取りません。 、非常にユーザーフレンドリー。
ロックは氷山の一角にすぎず、wikiページからは、マスタースレーブモード、センチネルモード、クラスターモードをサポートしていますが、シングルノードモードは確実にサポートされています。
この記事では、依然としてロックに焦点を当てていますが、それ以外はあまり取り上げていません。
Redissonの通常のロック実装のソースコードは主にRedissonLockであり、そのソースコードをまだ見たことのない友人は、ぜひ調べてみてください。
ソースコードのロック/ロック解除操作はすべてluaスクリプトで行われ、パッケージは非常に完璧であり、そのまま使用できます。
小さなディテールがあり、使用してロックsetnxを達成することができ、また使用のluaスクリプトは不要ではないでしょうか?著者はまた、非常に厳密に考えました。そのような強力なものは、どうやって無駄なコードを書くことができるのでしょうか
実際、著者はさらに詳しく調べました。ロックとロック解除を行うluaスクリプトは、ロックの再入可能性を含め、非常に包括的に考慮されています。これは非常に慎重であると言えます。また、テストするコードも作成しました。
jdkのReentrantLockのように本当にスムーズなので、redissonは非常に完璧です。redLockとは何ですか?
RedLock
redLock中国は直訳、と呼ばれている赤ロック。
Red Lockはツールではなく、redis officialが提案した分散ロックアルゴリズムです。
今紹介したredissonでは、redLockバージョンのロックが実装されています。それは他にあるGETLOCKの方法、そこgetRedLockの方法。
著者はおそらく赤い錠の理解を引き出しました:
Redisの高可用性デプロイメントに慣れていない場合は、問題ありません。redLockアルゴリズムには複数のインスタンスが必要ですが、これらのインスタンスは独立してデプロイされ、マスターとスレーブの関係はありません。
RedLockの作成者は、独立したものを使用する理由は、次のようなredis非同期レプリケーションによって引き起こされるロックの損失を回避するためであると指摘しました:マスターノードが来ておらず、スレーブノードに設定されたばかりのデータがハングしています。
一部の人々は、ビッグウィッグがすべて良いと思い、毎日極端な状況を考えますか?実際、高可用性、スペルは99.999 ...%桁の小数点以下です。
上記の簡単な図に戻ると、赤いロックアルゴリズムは、2N + 1個のノードが正常にロックされている限り、ロックが取得され、ロックが解除されるとすべてのインスタンスがロック解除されたと見なします。プロセスは次のとおりです。
- 5つのノードから順番にロックを要求する
- ノードをスキップするかどうかを推測する特定のタイムアウト時間によると
- 3つのノードが正常にロックされ、ロックの有効期間よりも時間がかかりません
- ロックが成功したと判断した
つまり、ロックが30秒で期限切れになり、3つのノードがロックするのに31秒かかったとすると、当然ロックは失敗します。
これは単なる例です。実際には、各ノードをそれほど長く待つべきではありません。公式Webサイトが述べたように、有効期間を10 秒とすると、1つのredisインスタンス操作のタイムアウトは5〜50 ミリ秒になります(時間に注意してください)単位)
または、有効期間を30秒に設定し、図で2つのredisノードがタイムアウトしたとします。
次に、ロックを正常にロックしたノードは合計 3秒かかったため、ロックの実際の有効性は27秒未満です。
つまり、成功した3つのロックインスタンスの3秒が差し引かれ、タイムアウトのredisインスタンスを待機する合計時間も差し引かれます。
これを見て、あなたはこのアルゴリズムについていくつか質問があるかもしれません、そしてあなたは一人ではありません。
Redis Webサイトの赤い錠の説明をもう一度見てください。
この説明ページの下部には、赤いロックに関する有名な妖精の戦いが表示されています。
つまり、Martin KleppmannとantirezのredLockに関する議論です。1人は高度な資格を持つ分散型アーキテクトで、もう1人はredisの父です。
公式の絞首刑執行人、最も致命的な。
ジョークを作るには、公式サイトに掲載できるかどうか疑わしいものであれば、貴重なはずです。
したがって、プロジェクトで赤いロックを使用する場合は、赤いロックの導入に加えて、次の2つの記事を読むことをお勧めします。
- マーティンクレップマンの質問投稿
- アンチレズの反撃
まとめ
たくさん読んだ後、それを達成する方法を見つけましたか?100%の安定性を保証することはできません。
手順はこのようなものであり、絶対的な安定性はないため、結局のところ、手動補正を行う上で重要な部分です。
テクノロジーは十分ではありません、手動で一緒に来てください〜