検索
ホームページJava&#&チュートリアルJava は Redis に基づいて分散ロックを実装します

分散ロックは、Zookeeper、Redis など、さまざまな方法で実装できます。いずれの場合でも、基本原則は同じです。つまり、ロックを表すために状態値が使用され、ロックの占有と解放は状態値によって識別されます。

Java は Redis に基づいて分散ロックを実装します

1. Redis が分散ロックを簡単に実装できる理由

1. Redis は単一プロセス、単一スレッド モードであり、キュー このモードは同時アクセスをシリアル アクセスに変換し、複数のクライアントの Redis への接続間に競合はありません。

2. Redis の SETNX コマンドを使用すると、簡単に分散ロックを実装できます。

setNX(存在しない場合はSET)

構文: SETNXキー値

戻り値: 設定が成功した場合は1が返され、設定が失敗した場合は0が返されます。戻ってきた。

キーが存在しない場合にのみ、キーの値を value に設定し、1 を返します。指定されたキーがすでに存在する場合、SETNX は何も実行せず、0 を返します。

要約すると、setnx の戻り値を使用してロックが取得されているかどうかを判断できます。Redis はシングルスレッドであるため、同時アクセスについて心配する必要はありません。1 を返した場合、ロックが取得され、0 が返されます。取得されませんでした。業務が終了したらロックを解除する必要がありますが、ロック解除のロジックは非常に単純で、前回設定したキーを削除し、次回からキーを設定することでロックを取得できるようになります。

2. 分散ロックの実装

分散ロックは Redis 独自の関数 setNX を通じて実装できることはすでにわかっています。具体的な実装手順は次のとおりです。

CentOS7 Linux 仮想マシンに Redis サービスをインストールしました。IP アドレスは 192.168.246.130、サービス ポートは 6379 です。

次は、redis を介して分散ロックを実装する Java の例です:

import redis.clients.jedis.Jedis;
public class RedisLock {
	//锁的key
	private static final String key = "DistributedRedisLock";
	private static Integer count = 0;
	public static void main(String[] args) {
		for(int i=0;i<1000;i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					//获取Redis连接
					Jedis jedis = new Jedis("192.168.246.130", 6379);
					try{
						while(true){
							//获取锁
							if(jedis.setnx(key, Thread.currentThread().getName()) == 1){
								try{
									System.out.println("线程("+Thread.currentThread().getName()+")获取到锁,开始执行操作");
									count++;
									System.out.println(count);
									break;
								}finally{
									System.out.println("操作执行完成,释放锁");
									//操作执行完一定要释放锁,所以在finally块中执行
									jedis.del(key);
								}
							}else{
								//返回的不是1,说明已经有某个线程获取到了锁
								try {
									//等待100毫秒之后重试
									Thread.sleep(100l);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
						}
					}catch(Exception e){
						e.printStackTrace();
					}finally{
						//释放Redis连接
						jedis.disconnect();
					}
				}
			}).start();
		}
	}
}

上記のコードの出力は次のとおりです:

线程(Thread-320)获取到锁,开始执行操作
1
操作执行完成,释放锁
线程(Thread-463)获取到锁,开始执行操作
2
操作执行完成,释放锁
线程(Thread-997)获取到锁,开始执行操作
3
操作执行完成,释放锁
...
线程(Thread-409)获取到锁,开始执行操作
998
操作执行完成,释放锁
线程(Thread-742)获取到锁,开始执行操作
999
操作执行完成,释放锁
线程(Thread-286)获取到锁,开始执行操作
1000
操作执行完成,释放锁

上記のコードは単一のアプリケーション内にありますが、複数のスレッドでテストされましたが、分散環境でロックを取得するために複数のアプリケーションと複数のスレッドが使用された場合でも、結果は依然として正しいです。

3. デッドロック問題を解決する

前のコード例は、原理を説明するための単なるテスト コードです。例自体は非常に単純なので、次のようなものがあります。いくつかの考慮されていない側面があります。例えば、ロック取得後、業務実行中に環境問題が発生してRedisとの接続が切断され、finallyブロックでロックが解除できず、ロック取得を待っていた他のスレッドが無限に待機してしまう、といった場合です。デッドロック現象が起こるのです。

解決策:

Redis でロックの有効期限を設定できるため、ロックを解放できない場合でも、一定の時間が経過すると自動的にロックが解放されます。期間。

コードに関しては、ロックを取得した後に次のコードを try ステートメント ブロックに追加するだけです:

jedis.expire(key, 10); //这里给锁设置10秒的过期时间

より良い解決策:

1 つの解決策はあまり良くありません。ビジネス オペレーションの処理時間が非常に長く、設定された有効期限を超えると、ロックが自動的に解放され、その後、finally ブロックでロックを解放する操作が実行されると、ロックが解除されてしまいます。スレッドが保持しているロックにより、他のスレッドが保持しているロックが解放されるため、同時実行性の問題が発生します。したがって、ロックを解除するときにロックの有効期限が切れているかどうかを判断し、期限が切れている場合は再度ロックを解除する必要はありません。

コード内で、ロックを取得した後の操作を次のコードに変更します:

long start = System.currentTimeMillis(); //获取起始时间毫秒数
try{
  jedis.expire(key, 10);
  ...
}finally{
  ...
  if(System.currentTimeMillis() < start+10*1000){
     //如果之前设置的锁还未过期,则释放掉
     jedis.del(key);
  }
}

以上がJava は Redis に基づいて分散ロックを実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はCSDNで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?Mar 17, 2025 pm 05:46 PM

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?Mar 17, 2025 pm 05:45 PM

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?Mar 17, 2025 pm 05:44 PM

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?Mar 17, 2025 pm 05:43 PM

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Mar 17, 2025 pm 05:35 PM

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール