最近看<<redis实战>> 里面有一个不错的redis分布式锁的实现,但是只是同步实现版本, 由于工作中用python的协程化框架,故简单改造下,代码如下:
import math
import time
import uuid
import asyncio
import aioredis
from aioredis.errors import WatchVariableError
async def acquire_lock(conn, lockname, acquire_timeout=10, lock_timeout=10):
identifier = str(uuid.uuid4())
lockname = 'lock:' + lockname
lock_timeout = int(math.ceil(lock_timeout))
end = time.time() + acquire_timeout
while time.time() < end:
if await conn.set(
lockname,
identifier,
expire=lock_timeout,
exist=conn.SET_IF_NOT_EXIST):
return identifier
await asyncio.sleep(1)
return False
async def release_lock(conn, lockname, identifier):
lockname = 'lock:' + lockname
while True:
try:
await conn.watch(lockname)
if await conn.get(lockname) == identifier:
pipe = conn.multi_exec()
pipe.delete(lockname)
await pipe.execute()
return True
await conn.unwatch()
break
except WatchVariableError:
pass
return False
async def main():
redis_pool = await aioredis.create_redis_pool(
("127.0.0.1", 6379),
db=14,
password=None,
encoding="utf-8")
identifier = await acquire_lock(redis_pool, 'foo_bar')
print(await acquire_lock(redis_pool, 'foo_bar'))
await release_lock(redis_pool, 'foo_bar', identifier)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())