redisトランザクションマルチプロセスシミュレーション秒殺在庫を保証する正しいluaスクリプトとwatchの方法
3つの方法で実現 lpopの原子操作10個の商品についてlpush 10個のデータ買い占め開始についてlpopで在庫 がまだ存在するか否かを判断する. watchインプリメンテーションの下には、コードインプリメンテーションwatchの在庫キーがあり、multi後にキーが他のクライアントによって変更されると、トランザクション操作はWatchError異常 を放出する. luaスクリプトの下にコード実装 があります.
watchメソッド実装
import redis
from redis import WatchError
from concurrent.futures import ProcessPoolExecutor
r = redis.Redis(host='127.0.0.1', port=6379, password='123')
# ,
# , , True
# , , False
def decr_stock():
# python redis pipeline
with r.pipeline() as pipe:
while True:
try:
# watch , multi key , WatchError
pipe.watch('stock:count')
count = int(pipe.get('stock:count'))
if count > 0: #
#
pipe.multi()
pipe.decr('stock:count')
#
# execute , decr
print pipe.execute()[0]
return True
else:
return False
except WatchError, ex:
# WatchError , watch
print ex
pipe.unwatch()
def worker():
while True:
#
if not decr_stock():
print "=============="
break
#
# 100
r.set("stock:count", 100000)
print r.get("stock:count")
import time
testa = time.time()
#
with ProcessPoolExecutor(max_workers=5) as pool:
for _ in range(10):
pool.submit(worker)
print time.time() - testa
luaスクリプトのメソッド実装
import redis
from redis import WatchError
from concurrent.futures import ProcessPoolExecutor
r = redis.Redis(host='127.0.0.1', port=16379, password='joyame!@#')
# ,
# , , True
# , , False
def decr_stock():
lua_2 = """
if (tonumber(redis.call("GET","stock:count")) > tonumber(0)) then
redis.call("DECR","stock:count")
return true
else
return nil
end
"""
# python redis pipeline
with r.pipeline() as pipe:
while True:
try:
script_2 = r.register_script(lua_2)
a = script_2()
if a >= 0:
print a
return True
else:
return False
except WatchError, ex:
# WatchError , watch
print ex
pipe.unwatch()
def worker():
while True:
#
if not decr_stock():
print "=============="
break
#
# 100
r.set("stock:count", 1000)
import time
testa = time.time()
#
with ProcessPoolExecutor(max_workers=5) as pool:
for _ in range(10):
pool.submit(worker)
print time.time() - testa