searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

基于MySQL数据库实现分布式锁

2023-12-06 06:48:54
24
0

什么是分布式锁

分布式锁,顾名思义就是分布式系统中的锁。锁是单体应用中解决共享资源访问问题的工具。而分布式锁,就是为了解决分布式系统中共享资源访问的问题,防止分布式系统中的多个进程之间相互干扰。

使用场景

在分布式系统里,我们有时需要执行某些定时任务。为了确保分布式系统中只有一个进程执行定时任务,所以需要分布式锁来进行控制。

通常,我们一般会使用Redis分布式锁、Zookeeper分布式锁的解决方案。但是由于定时任务的执行对性能要求不高且不希望引入新组件,我们有时需要基于现有数据库的解决方案,因此这里介绍的是基于MySQL实现的分布式锁方案。

实现方案

一种简单实现是基于MySQL数据库的唯一索引实现的,其核心思想是通过表的唯一索引进行互斥。首先在数据库中创建表,并创建唯一索引;想要执行某个定时任务,就需要向表中插入数据;成功插入则获取锁,执行完成后删除对应的行数据释放锁。

数据库表:

CREATE TABLE `task_lock`
(
    `id`          bigint      NOT NULL AUTO_INCREMENT COMMENT '主键',
    `task_name`   varchar(64) NOT NULL DEFAULT '' COMMENT '任务名',
    `executor`    varchar(64) NOT NULL DEFAULT '' COMMENT '任务执行者',
    `description` varchar(64) NOT NULL DEFAULT '' COMMENT '任务描述',
    `status`      varchar(64) NOT NULL DEFAULT '' COMMENT '任务状态',
    `create_time` datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `exp_time`    datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '过期时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `idx_task` (`task_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='分布式任务表';

获取锁:

@Transactional
    public boolean acquireLock(String lockName, String owner, Long expTimeMin) {
        LocalDateTime now = LocalDateTime.now();
        TaskLock taskLock = new TaskLock(lockName, owner, now, getExpTime(now, expTimeMin));
        int rows = 0;
        try{
            rows = taskLockMapper.insert(taskLock);
        }catch (Exception e){
            log.error("insert lock {} ex:{},",lockName,e.getMessage());
        }
        if (rows <= 0) {
            TaskLock expLock = selectExpireLock(lockName);
            if (null == expLock) return false;
            rows = updateExpireLock(expLock, taskLock);
        }
        return rows > 0;
    }

释放锁:

@Transactional
    public void releaseLock(String lockName, String owner){
        LambdaQueryWrapper<TaskLock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskLock::getTaskName, lockName);
        wrapper.eq(TaskLock::getExecutor, owner);
        taskLockMapper.delete(wrapper);
    }

总结:

使用MySQL实现分布式锁的好处是项目不用增加额外的依赖,满足项目对于分布式锁的基本需要。

0条评论
0 / 1000
1****m
3文章数
0粉丝数
1****m
3 文章 | 0 粉丝
1****m
3文章数
0粉丝数
1****m
3 文章 | 0 粉丝
原创

基于MySQL数据库实现分布式锁

2023-12-06 06:48:54
24
0

什么是分布式锁

分布式锁,顾名思义就是分布式系统中的锁。锁是单体应用中解决共享资源访问问题的工具。而分布式锁,就是为了解决分布式系统中共享资源访问的问题,防止分布式系统中的多个进程之间相互干扰。

使用场景

在分布式系统里,我们有时需要执行某些定时任务。为了确保分布式系统中只有一个进程执行定时任务,所以需要分布式锁来进行控制。

通常,我们一般会使用Redis分布式锁、Zookeeper分布式锁的解决方案。但是由于定时任务的执行对性能要求不高且不希望引入新组件,我们有时需要基于现有数据库的解决方案,因此这里介绍的是基于MySQL实现的分布式锁方案。

实现方案

一种简单实现是基于MySQL数据库的唯一索引实现的,其核心思想是通过表的唯一索引进行互斥。首先在数据库中创建表,并创建唯一索引;想要执行某个定时任务,就需要向表中插入数据;成功插入则获取锁,执行完成后删除对应的行数据释放锁。

数据库表:

CREATE TABLE `task_lock`
(
    `id`          bigint      NOT NULL AUTO_INCREMENT COMMENT '主键',
    `task_name`   varchar(64) NOT NULL DEFAULT '' COMMENT '任务名',
    `executor`    varchar(64) NOT NULL DEFAULT '' COMMENT '任务执行者',
    `description` varchar(64) NOT NULL DEFAULT '' COMMENT '任务描述',
    `status`      varchar(64) NOT NULL DEFAULT '' COMMENT '任务状态',
    `create_time` datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `exp_time`    datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '过期时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `idx_task` (`task_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='分布式任务表';

获取锁:

@Transactional
    public boolean acquireLock(String lockName, String owner, Long expTimeMin) {
        LocalDateTime now = LocalDateTime.now();
        TaskLock taskLock = new TaskLock(lockName, owner, now, getExpTime(now, expTimeMin));
        int rows = 0;
        try{
            rows = taskLockMapper.insert(taskLock);
        }catch (Exception e){
            log.error("insert lock {} ex:{},",lockName,e.getMessage());
        }
        if (rows <= 0) {
            TaskLock expLock = selectExpireLock(lockName);
            if (null == expLock) return false;
            rows = updateExpireLock(expLock, taskLock);
        }
        return rows > 0;
    }

释放锁:

@Transactional
    public void releaseLock(String lockName, String owner){
        LambdaQueryWrapper<TaskLock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskLock::getTaskName, lockName);
        wrapper.eq(TaskLock::getExecutor, owner);
        taskLockMapper.delete(wrapper);
    }

总结:

使用MySQL实现分布式锁的好处是项目不用增加额外的依赖,满足项目对于分布式锁的基本需要。

文章来自个人专栏
天翼云开发者社区
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0