SQL を使用して単純な分散ロックを実装する
分散ロックと通常のロックの主な違いは、参加するサブジェクトが異なるノードにまたがるため、ノード障害とネットワーク障害を考慮する必要があることです。問題の重要なポイントを理解するには、Redis、ZooKeeper など、さまざまなものを使用して問題を実装できます。ただし、実際には SQL を使用して実装するのは非常に簡単です。以下では、例として PostgreSQL を使用して説明します。
1. 方法 1: セッション ロック
PostgreSQL で独自の排他的セッション レベルの勧告ロックを使用します。
pg_advisory_lock(key bigint)
pg_advisory_unlock(key bigint)
pg_try_advisory_lock(key bigint)
詳細なリファレンス: http://www.postgres.cn/docs/9.4/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS-TABLE
この種のロックはセッションレベルです。ロックを解放する前に、ロックの取得者は常にセッション、つまり接続を保持する必要があります。そうでない場合、ロックは解放されます。
この機能は、ロック取得者が失敗した場合のロック解放の問題を自然に解決します。
ただし、長時間保持する必要があるロックの場合、長い接続が生成され、データベース接続の数が多くても、通常は数千しか必要ありません。注目されること。考慮する必要があるもう 1 つの問題は、ネットワークまたはノードに障害が発生した場合、接続の両端がそれをすぐに認識できない可能性があるため、幸いなことに、PostgreSQL クライアントとサーバーの両方がこの設定をサポートしていることです。
サーバーのパラメーターは次のとおりです:
tcp_keepalives_idle
tcp_keepalives_interval
tcp_keepalives_count
2. ロックを取得したクライアントがクラッシュしてロックが解除されるのを防ぐために、ロック オブジェクトは永続的です。解放することはできません。各ロックには有効期限があります。
PostgreSQLでは以下の方法で実装できます
テーブルを作成します
postgres=# create table distlock(id int Primary key,expired_time Interval,owner text,ts timestamptz);
-
CREATE TABLE
-
postgres=# distlock(id) 値に挿入します(1);
-
INSERT 0 1
-
ロックと更新
postgres=# distlock set owner='node1',ts=now(),expired_time= を更新します間隔 '20 秒' where id=1 and (owner='node1' または owner is null or now() > ts +expired_time);
-
UPDATE 1
- ロックを取得したクライアントが、長期間のロック 定期的に同じ方法を実行してロックを更新する必要があります。そうしないと、ロックが失われます。
この時点では、他のクライアントはロックの取得に失敗します
postgres=# update distlock set owner='node2',ts=now(),expired_time=interval '20 Second' where id=1 and (owner= 'node2 ' または所有者が null または now() > ts +expired_time);
-
UPDATE 0
-
ロックの有効期限が切れると、ロックは正常に取得されます
postgres=# update distlock set owner='node2 ',ts=now (),expired_time=interval '20 Second' where id=1 and (owner='node2' または owner が null または now() > ts +expired_time);
-
UPDATE 1
-
ロックを解除します
postgres=# update distlock set owner=null,ts=now() where id=1 and owner='node2';
-
UPDATE 1
-
3 が配布されていることがわかります。ロックはリレーショナル データベースを使用して実装されます。これは複雑ではありません。特に、上記のテーブルベースのロックの実装と信頼性の高い HA 展開を組み合わせると、ロック情報の耐久性と損失の防止が保証されます。ただし、テーブルの更新を使用してロックを実装するのは比較的負荷が高く、非常に高いロック パフォーマンスを必要とするシナリオには適していません。 。
http://www.bkjia.com/PHPjc/1117252.html
www.bkjia.com本当http://www.bkjia.com/PHPjc/1117252.html技術記事 SQL を使用して単純な分散ロックを実装する場合、分散ロックと通常のロックの主な違いは、参加するサブジェクトが異なるノードにまたがるため、ノード障害とネットワーク障害を考慮する必要があることです。調べて聞いてください...