ホームページ  >  記事  >  データベース  >  Redis ロックを使用して同時実行の問題に対処する方法

Redis ロックを使用して同時実行の問題に対処する方法

尚
転載
2020-05-07 09:09:545993ブラウズ

Redis ロックを使用して同時実行の問題に対処する方法

Redis ロックを使用して同時実行の問題を処理し、複数のプロセスのうち 1 つのインスタンスだけが実行されるようにします。実行中のインスタンスがダウンしても、他のインスタンスの 1 つが起動して、実行中のインスタンスが存在するだけです。

import redis
r = redis.Redis(...)

last_heart = 0		# 记录上一次得到的锁心跳
free_lock_try = 6	# 锁无心跳的最大次数 

while not r.setnx('mylock', 1):
    now_heart = r.get('mylock')
    print(f"没获取到锁,now_heart={now_heart},last_heart={last_heart},free_lock_try={free_lock_try}")
    if now_heart == last_heart:
        free_lock_try = free_lock_try - 1
        if free_lock_try == 0:	# 锁已经1分钟没有心跳了
            old_heart = r.getset('mylock', 1)	# 将lock重置为1,并返回set之前的心跳值
            if old_heart < now_heart:
                time.sleep(10)
                continue
            else:
                break	# 成功获取到锁,退出循环
    else:
        free_lock_try = 6	# 锁有心跳,重置free_lock_try值
        last_heart = now_heart
    time.sleep(10)

def producer_exit():
    """程序正常退出时候自动清理锁"""
    r.delete(&#39;mylock&#39;)
import atexit
atexit.register(producer_exit)

# 业务代码
while True:
  r.incr(&#39;mylock&#39;)	# 让锁心跳加一
  ...

このプログラムが同時ロックでどのような問題を解決するかを見てみましょう:

1. 同時実行性が高い場合、複数のプロセスが同時にロックを取得できません。ここでは Redis.setnx を使用します。ロックが既に存在する場合、他のプロセスはロックをリセットしてロックを取得できません。さらに、複数のプロセスが同時にロックがありハートビートがないことを検出すると、redis.getset を使用してハートビートを 1 にリセットします。設定は成功する可能性がありますが、複数のプロセスによって取得される値は異なります。実際にロックが取得され、プロセスは前のプロセスのハートビートを返し、他のプロセスは 1 を取得します。

2. ロックのあるプロセスは正常に終了します。atexit を使用して、ロックを削除するプロセス終了関数を登録できます。ここで行う必要はありませんが、新しいロックを待つ必要があります。

3. ロックされたプロセスが予期せず終了し、終了後にハートビートが増加しなくなります。free_lock_try の数を超えると、他のプロセスがリセットして、ロックされたプロセスを取得します。 lock

4. すべてのプロセスが予期せず終了します。この問題はロックには関係ありません。スーパバイザを使用してデーモン プロセスを実行できます。

redis の詳細については、redis 入門チュートリアル 列に注目してください。

以上がRedis ロックを使用して同時実行の問題に対処する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はhaoflyで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。