基于数据库唯一索引 + 过期时间的分布式锁

多个服务抢同一行记录,谁插入成功谁拿锁;插入失败说明锁被占,再看它是否过期,过期就可以抢过来。

1. 建锁表

复制代码
CREATE TABLE distributed_lock (
  lock_key VARCHAR(64) PRIMARY KEY,
  owner VARCHAR(64) NOT NULL,
  expire_at DATETIME NOT NULL
);
  • lock_key:锁的名字,比如 order:123

  • owner:谁持有锁,比如 UUID

  • expire_at:过期时间,防止死锁

2. 加锁流程

先尝试插入:

复制代码
INSERT IGNORE INTO distributed_lock(lock_key, owner, expire_at)
VALUES ('order:123', 'uuid-1', NOW() + INTERVAL 30 SECOND);
  • 插入成功:拿到锁

  • 插入失败:说明已经有这行记录,锁被占了

然后尝试抢过期锁:

复制代码
UPDATE distributed_lock
SET owner = 'uuid-1', expire_at = NOW() + INTERVAL 30 SECOND
WHERE lock_key = 'order:123' AND expire_at < NOW();
  • 更新成功:说明旧锁过期了,你抢到了

  • 更新失败:说明锁还在有效期内,你没抢到

3. 释放锁

只删自己的锁,防止误删别人的:

复制代码
DELETE FROM distributed_lock
WHERE lock_key = 'order:123' AND owner = 'uuid-1';

4. 续期

业务还没执行完,但锁快过期了:

复制代码
UPDATE distributed_lock
SET expire_at = NOW() + INTERVAL 30 SECOND
WHERE lock_key = 'order:123' AND owner = 'uuid-1';

5. 关键点

  • lock_key 必须是主键或唯一索引,这是互斥的核心。

  • 必须有过期时间,否则服务挂了锁永远不释放。

  • 释放和续期都要带 owner,不能删别人的锁。

  • 必须读写主库,不能读从库,否则主从延迟会误判。

  • 适合并发不高的场景,高并发还是 Redis / ZooKeeper 更合适。

总结:

插入成功 = 拿锁;插入失败 = 看是否过期;过期就 UPDATE 抢锁;释放用 DELETE 带 owner 校验。

相关推荐
qq_284274057 小时前
机械原理笔记:平面机构自由度计算(复合铰链、局部自由度、虚约束)与四杆机构入门(含考点)
笔记·学习·平面·自动化·制造
qq_284274058 小时前
数控铣床与加工中心笔记:铣刀与刀柄系统、G54试切对刀、镜像加工指令、孔加工工艺(钻扩铰镗)与固定循环G73/G83/G81/G76/G87/G84
笔记·学习·自动化·制造
Titan20249 小时前
MySQL访问个人学习笔记
笔记·学习·mysql
小雪崩10 小时前
嵌入式学习 day64:字符设备驱动
学习
个 人 练 习 生10 小时前
C++ string 类模拟实现:从底层理解字符串(上)
开发语言·c++·经验分享·学习·程序人生
坤坤子吖10 小时前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习
词却12 小时前
OpenCV学习:MediaPipe 人脸网格检测
opencv·学习
李日华大战鸡红12 小时前
FOC SVPWM过调制(学习记录)
stm32·单片机·学习
AI职业加油站12 小时前
AI 校招现状:大模型应用工程师证书,助力简历能力证明
大数据·运维·人工智能·学习·职场发展
陈年老古董13 小时前
Hive 函数学习笔记(上):单行函数与炸裂函数
hive·笔记·学习