使用Redis鎖處理并發問題的方法

使用Redis鎖處理并發問題的方法

使用redis鎖處理并發問題,保證多進程僅有一個實例在運行,當運行中的實例down了后其它實例中的一個能頂上來,保證有且僅有一個實例在運行。

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?<p>我們來看看這段程序都解決了并發鎖中的哪些問題:</p><p>1、高并發下,多個進程無法同時獲取到鎖。這里使用的是<a style="color:#f60; text-decoration:underline;" title="redis" href="https://www.php.cn/zt/15737.html" target="_blank">redis</a>.setnx,如果鎖已經存在,其他進程是無法重置鎖并獲取到鎖的。另外當多個進程同時發現有鎖已經沒有心跳了,使用的是redis.getset將心跳重置為1,都能set成功,但是get出來的值多個進程是不一樣的,只有真正獲取到鎖的進程返回的是之前進程的心跳,而其他進程獲取到的都是1。</p><p>2、有鎖進程正常退出,可以使用atexit注冊進程退出函數刪除鎖,這里也可以不要,不過下次啟動得等新的進程等待幾次心跳</p><p>3、有鎖進程意外退出,退出后心跳不再增加,超過free_lock_try次數后,其他進程會重新設置并獲取鎖</p><p>4、所有進程全都意外退出,這個問題不是鎖來關心的,可以使用supervisor進行守護進程。</p><p>更多redis知識請關注<a href="https://www.php.cn/redis/" target="_blank">redis入門教程</a>欄目。</p>

? 版權聲明
THE END
喜歡就支持一下吧
點贊14 分享