Redis异步锁获取卡住问题排查:代码是否存在语法错误?
Redis异步锁无法通过acquire步骤的问题分析
你的代码没有语法错误,但存在导致锁阻塞的逻辑缺陷,同时有几个排查方向:
核心问题:未正确处理异常场景下的锁释放
在update函数中,当int(k) < 0触发ValueError时,await lock.release()不会被执行,导致锁被永久持有,后续所有任务都会阻塞在lock.acquire()步骤。
修复方案:使用async with自动管理锁
async with上下文管理器会在代码块结束(包括异常抛出时)自动释放锁,彻底避免锁泄漏问题,修改后的代码如下:
import redis.asyncio as redis import tqdm import asyncio # 建议显式指定Redis连接参数,避免环境默认值差异 r = redis.Redis(host="localhost", port=6379, decode_responses=True) async def update(): # 用async with自动处理锁的获取与释放 async with r.lock("lock"): k = await r.get("key") if int(k) < 0: raise ValueError(f"Value {k} is negative") await r.setex("key", 3600, -1) await asyncio.sleep(0.5) await r.setex("key", 3600, 1) async def main(): total = 100 chunksize = 10 await r.setex("key", 3600, 1) aws = [update() for _ in range(total)] with tqdm.tqdm(total=total) as pbar: for idx in range(0, total, chunksize): end = min(idx + chunksize, total) chunk = aws[idx:end] await asyncio.gather(*chunk) pbar.update(end - idx) if __name__ == "__main__": asyncio.run(main())
其他排查方向
- Redis连接验证:确认Redis服务正常运行,且代码中的连接参数(host、port、密码等)与实际环境匹配,避免因连接失败导致的隐性阻塞。
- 残留锁清理:如果之前的异常运行导致锁残留,可以通过Redis客户端执行
DEL lock手动删除锁键,再重新测试。
内容的提问来源于stack exchange,提问作者monopoly
相关产品推荐
相关产品推荐

