Mysql数据库实现分布式锁
使用 MySQL 数据库实现分布式锁可以确保在多实例环境中定时任务不重复执行。
创建锁表
CREATE TABLE distributed_lock (
lock_name VARCHAR(64) PRIMARY KEY,
locked_by VARCHAR(64),
locked_at DATETIME,
timeout_at DATETIME
);
获取锁
在获取锁时,你需要尝试插入一条记录到 distributed_lock
表中。如果插入成功,表示获得锁;如果失败,表示锁已经被其他实例占用。以下是一个获取锁的示例 SQL 语句:
INSERT INTO distributed_lock (lock_name, locked_by, locked_at, timeout_at)
VALUES ('your_lock_name', 'instance_id', NOW(), DATE_ADD(NOW(), INTERVAL 10 SECOND))
ON DUPLICATE KEY UPDATE
locked_by = VALUES(locked_by),
locked_at = VALUES(locked_at),
timeout_at = VALUES(timeout_at)
WHERE timeout_at < NOW();
释放锁
释放锁时,你可以简单地删除该锁的记录,或者更新 timeout_at
字段,以表示锁的释放。以下是释放锁的示例 SQL 语句:
DELETE FROM distributed_lock WHERE lock_name = 'your_lock_name';
定时任务逻辑
在你的定时任务中,首先调用获取锁的逻辑,如果成功获得锁,则执行任务逻辑,并在任务结束后释放锁。
public void executeScheduledTask() {
boolean locked = acquireLock("your_lock_name", "instance_id");
if (locked) {
try {
// 执行定时任务逻辑
} finally {
releaseLock("your_lock_name");
}
} else {
// 锁未获得,跳过执行
}
}
实现逻辑
下面是一个简单的获取锁和释放锁的方法示例:
public boolean acquireLock(String lockName, String instanceId) {
String sql = "INSERT INTO distributed_lock (lock_name, locked_by, locked_at, timeout_at) " +
"VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 10 SECOND)) " +
"ON DUPLICATE KEY UPDATE locked_by = VALUES(locked_by), " +
"locked_at = VALUES(locked_at), timeout_at = VALUES(timeout_at) " +
"WHERE timeout_at < NOW()";
// 执行 SQL 语句并返回结果
}
public void releaseLock(String lockName) {
String sql = "DELETE FROM distributed_lock WHERE lock_name = ?";
// 执行 SQL 语句
}
锁的过期机制
在获取锁时,可以设置一个过期时间(如 10 秒),这样即使某个实例在执行任务时崩溃,其他实例仍然能够在锁超时后重新获取锁。
注意
- 确保定时任务执行时间不超过锁的过期时间。
- 定期清理超时未释放的锁记录,防止数据库表数据膨胀。
原文地址:https://blog.csdn.net/MogulNemenis/article/details/142464406
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!