场景引入:
凌晨3点,你的秒杀系统突然崩溃!😱 原因是两个用户同时抢到了同一件库存为1的商品,这时候,一个幕后英雄站了出来——Redis分布式锁,而它的核心技能就是setnx
命令,今天我们就来拆解这个“并发世界里的门神”!
想象一下多人共用一间更衣室🚪,分布式锁就是那个“有人/无人”的挂牌,在微服务或集群环境中,它能确保同一时间只有一个服务实例能操作共享资源(比如库存、订单)。
核心要求:
✔️ 互斥性(锁只能被一个客户端持有)
✔️ 防死锁(持有者崩溃后自动释放)
✔️ 高性能(别让锁成了瓶颈)
setnx
命令详解 🛠️setnx
(SET if Not eXists)是Redis的原子操作,天生适合实现锁:
# 语法:SETNX key value # 返回1表示抢锁成功,0表示失败 127.0.0.1:6379> SETNX "lock:order_123" "client_abc" (integer) 1
为什么是原子操作?
Redis单线程执行命令,setnx
在判断key是否存在和设置值时不可分割,彻底避免并发问题。
❌ 错误示范:
SETNX "lock:stock" "1" # 抢到锁后...程序崩溃了,锁永远不释放!
✅ 加过期时间(Redis 2.6.12后推荐):
SET lock:stock "client_xyz" NX EX 30 # 自动30秒过期
Redis集群主节点挂掉时,从节点可能尚未同步锁数据,导致其他客户端也能获取锁。
Redlock算法(Redis官方方案):
(但争议较大,实际可用红锁或ZK等替代方案)
def deduct_stock(): lock_key = "lock:item_1001" if redis.set(lock_key, "1", nx=True, ex=10): # 尝试加锁 try: stock = db.query("SELECT stock FROM items WHERE id=1001") if stock > 0: db.execute("UPDATE items SET stock=stock-1") finally: redis.delete(lock_key) # 释放锁
多个服务节点同时跑定时任务时,用锁确保只有一个节点执行:
SETNX "lock:clean_expired_orders" "node1" EX 3600
用户重复提交订单时,用订单ID作为锁key:
SETNX "order:idempotent_20250801123456" "1" EX 30
-- Lua脚本保证原子性 if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) end
Redis的setnx
是分布式锁的轻量级解决方案,适合高并发、短耗时场景,对于强一致性要求高的系统(如金融交易),可考虑ZooKeeper或ETCD。
最后一句忠告:
分布式锁不是银弹!能用乐观锁(如CAS)解决的场景,就别用分布式锁~ 💡
(本文技术要点更新至2025年8月)
本文由 蓝悦爱 于2025-08-01发表在【云服务器提供商】,文中图片由(蓝悦爱)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://up.7tqx.com/wenda/499733.html
发表评论