自学内容网 自学内容网

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)!