基于Mongodb分布式锁简单实现,解决定时任务并发执行问题
2023/4/18 18:22:02
本文主要是介绍基于Mongodb分布式锁简单实现,解决定时任务并发执行问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
我们日常开发过程,会有一些定时任务的代码来统计一些系统运行数据,但是我们应用有需要部署多个实例,传统的通过配置文件来控制定时任务是否启动又太过繁琐,而且还经常出错,导致一些异常数据的产生
网上有很多分布式锁的实现方案,基于redis、zk、等有很多,但是我的就是一个用了mysql和mongo的小应用,不准备引入其他三方中间件来解决这个问题,撸一个简单的分布式锁来解决定时任务并发执行的问题,加锁操作的原子性和防死锁也都要支持,这里我使用mongodb写了AllInOne的工具类
All in one Code
先上代码
@Component @Slf4j public class MongoDBLock { private static final int DEFAULT_LOCK_TIMEOUT = 30;//锁的默认超时时间,单位秒 private MongoTemplate mongoTemplate; private int lockTimeout; public MongoDBLock(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; this.lockTimeout = DEFAULT_LOCK_TIMEOUT; } /** * 尝试获取分布式锁 * * @param lockKey 锁的key * @return true:获取锁成功,false:获取锁失败 */ private boolean acquireLock(String lockKey) { LockDocument document = new LockDocument(); document.setId(lockKey); document.setExpireAt(Instant.ofEpochMilli(Instant.now().toEpochMilli() + lockTimeout * 1000)); try { mongoTemplate.insert(document); return true; } catch (Exception e) { } return false; } /** * 释放分布式锁 * * @param lockKey 锁的key */ private void releaseLock(String lockKey) { Query query = new Query(Criteria.where("key").is(lockKey)); mongoTemplate.remove(query, LockDocument.class); log.info("程序执行成功,释放分布式锁,lockKey:{}",lockKey); } /** * 分布式锁入口方法,参数lockName为锁的名称,lockKey为需要加锁的key,执行完成后自动释放锁 * * @param lockKey * @param task * @param <T> * @throws Exception */ public <T> void executeWithLock(String lockKey, ITask<T> task) throws Exception { boolean locked = acquireLock(lockKey); if (locked) { log.info("获取分布式锁成功,lockKey:{}",lockKey); try { task.execute(); } finally { releaseLock(lockKey); } } else { log.warn("获取分布式锁失败,lockKey:{}", lockKey); throw new AppException("获取分布式锁失败!"); } } @Data @Document(collection = "lock_collection") static class LockDocument { @Id private String id; @Indexed(expireAfterSeconds = DEFAULT_LOCK_TIMEOUT) private Instant expireAt; } @FunctionalInterface public interface ITask<T> { T execute() throws Exception; } }
调用示例
@Resource MongoDBLock mongoDBLock; mongoDBLock.executeWithLock("key", () -> { // do some thing return null; });
原理
- 使用key作为主键,利用mongodb的insert原子性保障LockDocument不会重复插入
- LockDocument中expireAt字段利用的mongodb索引过期机制,解决死锁问题,这里设置超时时间是30秒,并在执行完成之后会主动释放锁
这篇关于基于Mongodb分布式锁简单实现,解决定时任务并发执行问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享
- 2024-12-10搭建个人博客网站之一、使用hugo创建个人博客网站