1. ホーム
  2. データベース
  3. レディス

Redisの分散ロックについて簡単に説明します

2022-01-24 09:29:55

現在、多くの大規模なWebサイトやアプリケーションが分散配置されており、分散シナリオにおけるデータの整合性は常に重要なトピックとなっています。

{分散シナリオにおけるデータの一貫性の問題は重要なトピックであった。 CAP理論に基づくと、一貫性、可用性、パーティション耐性を同時に満たす分散システムは存在せず、最大でも2つ同時に満たすことが可能である。

データの究極の一貫性を確保するためには、分散トランザクション、分散ロックなど、それを支える多くの技術的なソリューションが必要です。通常、分散ロックを行うためにredisを選ぶ人が多いですが、それだけで安心できるでしょうか?

1.分散ロックとは

分散型とスタンドアロン型の最大の違いは、マルチスレッドではなくマルチプロセスであることと、データのコピーが1つしかない(または制限がある)ことで、スタンドアロン型の共有メモリでは一貫した書き込みの問題が解決できなくなり、ロック技術を使ってある瞬間にデータを変更するプロセス数を制御する必要があります。

分散モデルの場合も、分散ロックによってトークンをメモリに格納することができますが、そのメモリはプロセスによって割り当てられたものではなく、パブリックメモリ(Redis、Memcache)です。データベースやファイルなどを使ってロックを行うことに関しては、トークンの相互排他性が保証されていれば、スタンドアロンの実装と同じである。

2. 分散ロックが持つべき機能

    {について リエントラントロックが望ましい(デッドロックを回避するため)
  • ブロッキングロックが望ましい(ビジネス要件によって決定される) {を使用します。 {を使用します。 好ましくはフェアロック(ビジネス要件によって決定される)。 {を使用します。 {を使用します。 高可用性、高性能のロック取得およびロック解除機能を有すること {を使用します。

3. データベースに基づく分散ロックが可能

    {を使用します。 楽観的なロックに基づいて、CASが、大規模な並行処理の場合には、主キーの競合防止を使用して挿入の場合には、次のようなロックの動作が発生する可能性があります。 {を使用します。 {を使用します。 悲観的なロックに基づいて、つまり、排他的ロックは、様々な問題が発生します(データベースを操作すると、オーバーヘッドの一定量を必要とする、データベースの行レベルのロックの使用は、必ずしも信頼性が、パフォーマンスが信頼されていないです)。

分散型の特性は、特に、項目ごとに一致する必要がある場合は、高可用性(一点の存在)、高いパフォーマンスが困難です。

4. Redisをベースにした分散ロックを行う

setnx(set if not existing)コマンドで、先着順で1クライアントのみにロックを占有させ、使い切ったらdelコマンドで解放します。

中間ロジックの実行中に例外が発生した場合、del命令が実行されず、デッドロックに陥る可能性があります。

そうだ、ロックに有効期限をつけよう!(例外が発生しても、数秒後に自動的にロックが解除されることが保証されている)。

しかし、redisサーバーはsetnxとexpireの間で突然ハングアップしてしまうのですが、これを打開する方法は?

問題の根本は、setnxとexpireがアトミックな命令ではなく、2つの命令であることにあります。この問題を解決するために、Redisオープンソースコミュニティはたくさんの分散ロックソリューションを考え出しました。この混乱に対処するため、Redis 2.8 では set 命令に拡張機能を追加し、setnx 命令と expire 命令を一緒に実行できるようにして、分散ロックの混乱を一挙に解決しています。

{setnx命令とexpire命令を一緒に実行することができます。 つまり、setnxとexpireの組み合わせは、分散ロックの魔法なのです。

4.1 タイムアウト問題

ロックの追加と解放の間のロジックの実行に時間がかかりすぎて、タイムアウトの制限を超えた場合はどうすればよいですか?

これは、最初のスレッドが保持するロックは期限切れだが、クリティカルゾーンのロジックはまだ実行を終えていないことを意味し、その時点で2番目のスレッドが早期にロックを奪還し、各リクエストが厳密にシリアル方式でクリティカルゾーンのコードを実行することになります。

Redisの分散ロックはタイムアウトの問題を解決するものではないので、長時間のタスクには分散ロックを使用しないことが推奨されます。

少し安全な方法としては、setコマンドのvalueパラメータに乱数を設定し、ロックを解除する際にその乱数が同じかどうか照合し、同じであればキーを削除する方法があります。

{{コード
[...] 
[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 
[...] 
[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...]  [...] 

[...] 
[...] 
[...] 
[...] 
[...] 
[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...]  [...]  [...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...]  [...] 

[...] 
[...] 
[...]  [...]  [...]  [...] 

[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 
[...] 

[...] 
[...] 
[...] 
[...] 

[...]