分散ロックを実装するには、一般に 3 つの方法があります: 1. データベースのオプティミスティック ロック、2. Redis ベースの分散ロック、3. ZooKeeper ベースの分散ロック。
ここでは、Redis に基づく分散ロックの実装を紹介します。
分散ロックのプロパティ:
信頼性。 まず第一に、分散ロックを確実に利用できるようにするには、ロックの実装が少なくとも次の 4 つの条件を同時に満たしていることを確認する必要があります。
相互排他性## #。常に 1 つのクライアントだけがロックを保持できます。
デッドロックは発生しません。クライアントがアクティブにロックを解除せずにロックを保持したままクラッシュした場合でも、その後他のクライアントがそのロックをロックできることが保証されます。 フォールトトレランスを備えています。ほとんどの Redis ノードが正常に実行されている限り、クライアントはロックおよびロック解除を行うことができます。 トラブルは終わるはずだ。ロックとロック解除は同じクライアントで行う必要があり、他のクライアントが追加したロックをクライアント自身がロック解除することはできません。
コード実装コンポーネントの依存関係まず、Maven を介して Jedis オープン ソース コンポーネントを導入し、次のコードを pom.xml ファイルに追加する必要があります:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
コードをロックするための正しい姿勢
話は安いので、コードを見せてください。最初にコードを示し、次にこの方法で実装する理由をゆっくりと説明します。
public class RedisTool { private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; /** * 尝试获取分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @param expireTime 超期时间 * @return 是否获取成功 */ public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) { String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } }
ご覧のとおり、ロックに必要なコードは jedis.set(String key, String value, String nxxx) の 1 行だけです。 , String expx, int time )、この set() メソッドには合計 5 つの仮パラメータがあります:
最初のパラメータは key です。key は一意であるため、key をロックとして使用します。
2 つ目は value です。渡すのは requestId です。多くの子供には理解できないかもしれません。ロックとしてのキーがあれば十分ではないでしょうか。なぜ value を使用する必要があるのでしょうか?理由は、上で信頼性について説明したときに、分散ロックはベルのロックを解除するための 4 番目の条件を満たしている必要があり、ベルを持っている人がベルを結んだ人である必要があるためです。ロックを追加すると、ロックを解除するときの基盤ができます。 requestId は、UUID.randomUUID().toString() メソッドを使用して生成できます。
3 番目のパラメータは nxxx です。このパラメータに NX を入力します。これは、SET IF NOT EXIST を意味します。つまり、キーが存在しない場合はセット操作を実行します。キーがすでに存在する場合は、いいえを実行します。操作が実行されます;
4 番目のパラメータは expx です。渡すパラメータは PX です。これは、このキーに有効期限設定を追加することを意味します。特定の時間は 5 番目のパラメータによって決まります。
5 番目のパラメータは時間で、4 番目のパラメータに対応し、キーの有効期限を表します。
一般に、上記の set() メソッドを実行すると、次の 2 つの結果しか得られません: 1. 現在ロックがありません (キーが存在しません)。その後、ロック操作を実行し、ロックの有効期間を設定します。 、値はロックされたクライアントを表します。 2. ロックはすでに存在するため、操作は実行されません。
当社のロック コードは、信頼性のセクションで説明されている 3 つの条件を満たしています。まず、set() は NX パラメータを追加します。これにより、キーがすでに存在する場合、関数が正常に呼び出されないことが保証されます。つまり、1 つのクライアントのみがロックを保持でき、相互排他が満たされます。次に、ロックの有効期限を設定しているため、後でロック所有者がクラッシュしてロックが解除されなかった場合でも、有効期限に達するとロックは自動的にロック解除され (つまり、キーが削除され)、デッドロックは発生しません。起こる。最後に、ロックされたクライアントのリクエスト ID を表す requestId に値を割り当てるため、クライアントがロックを解除するときに、それが同じクライアントであるかどうかを検証できます。ここでは Redis スタンドアロン展開のシナリオのみを考慮するため、当面はフォールト トレランスについては考慮しません。
以上がRedis 分散ロックのタイムアウトはどのくらいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。