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

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

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 校验。

相关推荐
海海不掉头发1 小时前
CSDN博客_时序预测9模型复现对比
人工智能·学习·软件工程
蓝祁子yoky3 小时前
Qt学习日记 Day13:网络编程(一)-TCP基础与Socket实战
网络·qt·学习
架构师伯子明4 小时前
Ros 学习十三:IK Demo
学习
小羊没烦恼!4 小时前
关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
java·服务器·网络·学习·负载均衡
幼儿园蛋小黄4 小时前
从 STM32N647 的 AI 部署入门嵌入式:一条可落地的学习路线
人工智能·stm32·学习
Y.9996 小时前
电脑黑屏只有鼠标能动
学习
架构师伯子明6 小时前
FFmpeg C++学习(一):编译和demo
开发语言·c++·学习
叼烟扛炮6 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain
程序员梅雨6 小时前
【从零开始学习数据仓库 | 第二篇】: 拉链表 & 数仓分层
大数据·数据仓库·学习
一木 之林7 小时前
Dify学习笔记 04 · 检索底座:Embedding、Rerank与向量数据库(第46-54集)
笔记·学习·embedding·dify