Redis を使用して分散ロックを実装する方法を詳しく説明した記事
推奨学習: Redis ビデオ チュートリアル
1. 分散ロックとは
マルチスレッド コードを作成すると、異なるスレッドがリソースをめぐって競合することがあります。リソースの競合によるエラーを避けるために、リソースをロックします。ロックを取得したスレッドのみが実行を続行できます。
プロセス内のロックは、本質的にはメモリ内の変数です。スレッドがロックを適用する操作を実行するときに、ロックを表す変数の値を 1 に正常に設定できた場合、それは次のことを意味します。ロックが取得されました その他 スレッドはロックを取得しようとするとブロックされます ロックを所有するスレッドが操作を完了すると、ロックの値が 0 に設定され、ロックが解放されます。
上で話しているのは、サーバーのプロセス内の異なるスレッド間のロックです。このロックはメモリに配置され、分散アプリケーション、たとえば異なるアプリケーションの場合は、 (プロセスまたはスレッド) は異なるサーバーにデプロイされるため、ロックはメモリ内の変数で表すことができません。
ロックはサーバー上の共有メモリ空間で表すことができるため、分散アプリケーションの場合、共有ストレージ システムを使用して共有ロックを保存できます。これが分散ロックです。インメモリ データベースとして, Redis
は非常に高速に実行され、分散ロックを実装するための共有ストレージ システムとして非常に適しています。
2. Redis を使用して分散ロックを実装する
ロックの場合、実際にはロックとロックの解放の 2 つの操作しかありません。 Redis
を通じてそれを実現する方法を見てみましょう?
2.1 setnx
ロック#Redis
コマンドは、キー値が存在するかどうかを判断します。存在する場合は、存在しない場合は値を作成して割り当て、1 を返すため、setnx
を実行して代表的なロック キーの値を設定できます。設定が成功した場合はロックが取得されたことを意味し、失敗した場合はロックを取得できません。
# 使用key为lock来表示一个锁 setnx lock 1
2.2 ロックの解除
操作実行後、ロックを解除したい場合は、Redis
のキー値を直接変更します。 lock
削除するだけで、他のプロセスが setnx
コマンドを通じてリセットしてロックを取得できるようになります。
# 释放锁 del lock
上記の 2 つのコマンドを通じて、単純な分散ロックを実装しましたが、ここで問題があります。プロセスが setnx
コマンドを通じてロックされている場合、特定の If the操作が失敗し、時間内にロックを解放する方法がない場合、他のプロセスがロックを取得できなくなり、システムは実行を続行できなくなります。この問題を解決する方法は、有効期間を設定することです。この有効期間が経過すると、ロックは自動的に解除されます。
2.3 ロックの有効期間を設定する
ロックの有効期間を設定するのは非常に簡単で、expire
コマンドを使用するだけです。 Redis
の例:
# 加锁 setnx lock 1 # 给锁设置10s有效期 expire lock 10
ただし、別の問題が発生します。ロックを設定した後、expire
コマンドを実行する前にプロセスがハングした場合、expire
実行が成功しなかった場合は、ロックが解放されていないため、上記の 2 つのコマンドが同時に実行されていることを確認する必要があります。
LUA
言語で記述したスクリプトを使用する方法と、Redis
の set
コマンドを使用する方法の 2 つがあります。 ## set コマンドの後に
nx パラメータを指定すると、実行効果は
setnx と一致し、
set コマンドの後に次のパラメータを指定できます。
ex パラメータ。有効期限を設定します。これにより、
set コマンドを使用して
setnx と
expire をマージできるようになります。実行のアトミック性を保証できます。
# 判断是否键值是否存在,ex后面跟着的是键值的有效期,10s set lock 1 nx ex 10
A、
B、
C## という 3 つの異なるサーバー上にプロセスが存在します。 # 操作を実行するには、ロックを取得し、実行後にロックを解放する必要があります。 <p>现在的情况是<code>进程A
执行第2步时卡顿了(上面绿色区域所示),且时间超出了锁有效期,所以进程A
设置的锁自动释放了,这时候进程B
获得了锁,并开始执行操作,但由于进程A
只是卡顿了而已,所以会继续执行的时候,在第3步的时候会手动释放锁,但是这个时候,锁由线程B
所拥有,也就是说进程A删除的不是自己的锁,而进程B的锁,这时候进程B
还没执行完,但锁被释放后,进程C
可以加锁,也就是说由于进程A卡顿释放错了锁,导致进程B和进程C可以同时获得锁。
怎么避免这种情况呢?如何区分其他进程的锁,避免删除其他进程的锁呢?答案就是每个进程在加锁的时候,给锁设置一个唯一值,并在释放锁的时候,判断是不是自己设置的锁。
2.4 给锁设置唯一值
给锁设置唯一值的时候,一样是使用set
命令,唯一的不同是将键值1改为一个随机生成的唯一值,比如uuid。
# rand_uid表示唯一id set lock rand_id nx ex 10
当锁里的值由进程设置后,释放锁的时候,就需要判断锁是不是自己的,步骤如下:
- 通过
Redis
的get
命令获得锁的值 - 根据获得的值,判断锁是不是自己设置的
- 如果是,通过
del
命令释放锁。
此时我们看到,释放锁需要执行三个操作,如果三个操作依次执行的话,是没有办法保证原子性的,比如进程A
在执行到第2步后,准备开始执行del
命令时,而锁由时有效期到了,被自动释放了,并被其他服务器上的进程B
获得锁,但这时候线程A
执行del
还是把线程B
的锁给删掉了。
解决这个问题的办法就是保证上述三个操作执行的原子性,即在执行释放锁的三个操作中,其他进程不可以获得锁,想要做到这一点,需要使用到LUA脚本。
2.5 通过LUA脚本实现释放锁的原子性
Redis
支持LUA
脚本,LUA
脚里的代码执行的时候,其他客户端的请求不会被执行,这样可以保证原子性操作,所以我们可以使用下面脚本进行锁的释放:
if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end
将上述脚本保存为脚本后,可以调用Redis
客户端命令redis-cli
来执行,如下:
# lock为key,rand_id表示key里保存的值 redis-cli --eval unlock.lua lock , rand_id
推荐学习:Redis视频教程
以上がRedis を使用して分散ロックを実装する方法を詳しく説明した記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









1. [スタート]メニューを起動し、[cmd]と入力し、[コマンドプロンプト]を右クリックし、[管理者として実行]を選択します。 2. 次のコマンドを順番に入力します (注意してコピーして貼り付けてください): SCconfigwuauservstart=auto、Enter キーを押す SCconfigbitsstart=auto、Enter キーを押す SCconfigcryptsvcstart=auto、Enter キーを押す SCconfigtrustedinstallerstart=auto、Enter キーを押す SCconfigwuauservtype=share、Enter キーを押す netstopwuauserv 、enter netstopcryptS を押す

GolangAPI のキャッシュ戦略により、パフォーマンスが向上し、サーバーの負荷が軽減されます。一般的に使用される戦略は、LRU、LFU、FIFO、TTL です。最適化手法には、適切なキャッシュ ストレージの選択、階層型キャッシュ、無効化管理、監視とチューニングが含まれます。実際には、データベースからユーザー情報を取得する API を最適化するために LRU キャッシュが使用されます。それ以外の場合は、データベースからデータを取得した後にキャッシュを更新できます。

PHP 開発では、キャッシュ メカニズムにより、頻繁にアクセスされるデータがメモリまたはディスクに一時的に保存され、データベース アクセスの数が削減され、パフォーマンスが向上します。キャッシュの種類には主にメモリ、ファイル、データベース キャッシュが含まれます。キャッシュは、組み込み関数またはサードパーティのライブラリ (cache_get() や Memcache など) を使用して PHP に実装できます。一般的な実用的なアプリケーションには、データベース クエリ結果をキャッシュしてクエリ パフォーマンスを最適化したり、ページ出力をキャッシュしてレンダリングを高速化したりすることが含まれます。キャッシュ メカニズムにより、Web サイトの応答速度が効果的に向上し、ユーザー エクスペリエンスが向上し、サーバーの負荷が軽減されます。

まず、システム言語を簡体字中国語表示に設定して再起動する必要があります。もちろん、以前に表示言語を簡体字中国語に変更したことがある場合は、この手順をスキップできます。次に、レジストリ regedit.exe の操作を開始し、左側のナビゲーション バーまたは上部のアドレス バーで HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlNlsLanguage に直接移動し、InstallLanguage キーの値と Default キーの値を 0804 に変更します (英語に変更する場合)。まずシステムの表示言語を en-us に設定し、システムを再起動してから、すべてを 0409 に変更します) この時点でシステムを再起動する必要があります。

Redis キャッシュを使用すると、PHP 配列ページングのパフォーマンスを大幅に最適化できます。これは、次の手順で実現できます。 Redis クライアントをインストールします。 Redisサーバーに接続します。キャッシュ データを作成し、データの各ページをキー「page:{page_number}」を持つ Redis ハッシュに保存します。キャッシュからデータを取得し、大規模な配列での高コストの操作を回避します。

1. まず、デスクトップ上の[このPC]アイコンをダブルクリックして開きます。 2. 次に、マウスの左ボタンをダブルクリックして [C ドライブ] に入ります。システム ファイルは通常、自動的に C ドライブに保存されます。 3. 次に、C ドライブで [windows] フォルダーを見つけ、ダブルクリックしてに入ります。 4. [windows]フォルダーに入ったら、[SoftwareDistribution]フォルダーを見つけます。 5. 入力後、win11 のダウンロード ファイルとアップデート ファイルがすべて含まれている [ダウンロード] フォルダーを見つけます。 6. これらのファイルを削除したい場合は、このフォルダー内で直接削除してください。

Redis は、高性能のキー/値キャッシュです。 PHPRedis 拡張機能は、Redis サーバーと対話するための API を提供します。 Redis に接続し、データを保存および取得するには、次の手順を使用します。 接続: Redis クラスを使用してサーバーに接続します。ストレージ: set メソッドを使用してキーと値のペアを設定します。取得: get メソッドを使用してキーの値を取得します。

エラーの原因とソリューションPECLを使用してDocker環境に拡張機能をインストールする場合、Docker環境を使用するときに、いくつかの頭痛に遭遇します...
