Python Redis如何執(zhí)行Lua腳本
問(wèn)題描述
Python Redis 執(zhí)行 Lua 腳本可實(shí)現(xiàn)原子性
官方文檔表示,Redis 使用相同的 Lua 解釋器來(lái)運(yùn)行所有命令,Redis 保證腳本以原子方式執(zhí)行:
- 在執(zhí)行腳本時(shí)不會(huì)執(zhí)行其他腳本或 Redis 命令。
- 這種語(yǔ)義類(lèi)似于
MULTI/EXEC的語(yǔ)義,從所有其他客戶(hù)的角度來(lái)看,腳本的效果要么仍然不可見(jiàn),要么已經(jīng)完成。
解決方案
安裝
pip install redis
代碼
from redis import Redis
redis = Redis()
script = """
redis.call('SETEX', 'key', 100, 'value')
"""
redis.register_script(script)() # 執(zhí)行腳本
效果

傳遞參數(shù)
Script 類(lèi)調(diào)用函數(shù)原型:
def __call__(self, keys=[], args=[], client=None)
from redis import Redis
redis = Redis()
script = """
local key = KEYS[1]
local seconds = ARGV[1]
local value = ARGV[2]
redis.call('SETEX', key, seconds, value)
"""
cmd = redis.register_script(script)
cmd(keys=['key'], args=[100, 'value']) # 執(zhí)行腳本
效果同上
分布式鎖
1.加鎖并設(shè)過(guò)期時(shí)間 SET lock_resource_name $uuid NX PX $expire_time,同時(shí)啟動(dòng)守護(hù)線程為快要過(guò)期單還沒(méi)執(zhí)行完畢的客戶(hù)端的鎖續(xù)命;
2.客戶(hù)端執(zhí)行業(yè)務(wù)邏輯操作共享資源;
3.通過(guò) Lua 腳本釋放鎖,先 get 判斷鎖是否是自己加的,再執(zhí)行 DEL。
判斷+刪除
import time
from uuid import uuid4
from redis import Redis
redis = Redis()
# 判斷是否自己創(chuàng)建的鎖,是的話則釋放
script = """
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
else
return 0
end
"""
def do_something():
name = 'lock' # 鎖名,此處故意寫(xiě)死讓別的進(jìn)程進(jìn)來(lái)占用
uuid = str(uuid4())
# 上鎖
if redis.set(name=name, value=uuid, nx=True, ex=25): # 鎖不存在才能上鎖成功,過(guò)期時(shí)間應(yīng)為業(yè)務(wù)時(shí)間的五倍,此處故意寫(xiě)小,模擬過(guò)期釋放
print('上鎖')
try:
print('處理業(yè)務(wù)', uuid)
time.sleep(10)
except Exception as e:
print(e)
finally:
# 釋放鎖
cmd = redis.register_script(script)
res = cmd(keys=[name], args=[uuid]) # 執(zhí)行腳本
if res:
print('鎖已釋放')
else:
print('不是自己的鎖')
else:
print('鎖已存在')
if __name__ == '__main__':
do_something()
模擬過(guò)程:
- 運(yùn)行程序1
- 手動(dòng)迅速刪掉這個(gè)鎖
- 運(yùn)行程序2
效果:

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Caffeine實(shí)現(xiàn)類(lèi)似redis的動(dòng)態(tài)過(guò)期時(shí)間設(shè)置示例
這篇文章主要為大家介紹了Caffeine實(shí)現(xiàn)類(lèi)似redis的動(dòng)態(tài)過(guò)期時(shí)間示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
redis數(shù)據(jù)結(jié)構(gòu)之壓縮列表
這篇文章主要介紹了redis數(shù)據(jù)結(jié)構(gòu)之壓縮列表,壓縮列表是列表list和hash數(shù)據(jù)結(jié)構(gòu)的底層實(shí)現(xiàn)之一,是redis為了節(jié)約內(nèi)存而開(kāi)發(fā)的,由一系列特殊編碼的連續(xù)內(nèi)存塊組成的順序型數(shù)據(jù)結(jié)構(gòu),下面詳細(xì)內(nèi)容需要的小伙伴可以參考一下2022-03-03
一文詳解如何使用Redis實(shí)現(xiàn)分布式鎖
這篇文章主要介紹了一文詳解如何使用Redis實(shí)現(xiàn)分布式鎖,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09
Redis7.2.x主從復(fù)制的實(shí)現(xiàn)示例
本文主要介紹了Redis7.2.x主從復(fù)制的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06
為何Redis使用跳表而非紅黑樹(shù)實(shí)現(xiàn)SortedSet
本篇文章主要介紹了為何Redis使用跳表而非紅黑樹(shù)實(shí)現(xiàn)SortedSet,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
在CentOS 7環(huán)境下安裝Redis數(shù)據(jù)庫(kù)詳解
Redis是一個(gè)開(kāi)源的、基于BSD許可證的,基于內(nèi)存的、鍵值存儲(chǔ)NoSQL數(shù)據(jù)本篇文章主要介紹了在CentOS 7環(huán)境下安裝Redis數(shù)據(jù)庫(kù)詳解,有興趣的可以了解一下。2016-11-11
Web-ssrfme:redis 未授權(quán)訪問(wèn)攻擊的問(wèn)題解決
本文主要介紹了Web-ssrfme:redis 未授權(quán)訪問(wèn)攻擊的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
淺談Redis跟MySQL的雙寫(xiě)問(wèn)題解決方案
項(xiàng)目中有遇到這個(gè)問(wèn)題,跟MySQL中的數(shù)據(jù)不一致,記錄一下,本文主要介紹了Redis跟MySQL的雙寫(xiě)問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
Redis分布式鎖如何設(shè)置超時(shí)時(shí)間
這篇文章主要介紹了Redis分布式鎖如何設(shè)置超時(shí)時(shí)間,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11

