在我们业务开发过程中,经常会有需求做一些定时任务,但是由于定时任务的特殊性,以及一些方法的幂等性要求,在分布式多节点部署的情况下,某个定时任务只需要执行一次。
1. 背景介绍
ShedLock是一个轻量级的分布式定时任务锁组件,使用其可以满足我们上面的技术需求,ShedLock官方简单自我介绍:
ShedLock makes sure that your scheduled tasks are executed at most once at the same time. If a task is being executed on one node, it acquires a lock which prevents execution of the same task from another node (or thread). Please note, that if one task is already being executed on one node, execution on other nodes does not wait, it is simply skipped.
Shedlock从严格意义上来说不是一个分布式任务调度框架,而是一个分布式锁。所谓的分布式锁,解决的核心问题就是各个节点中无法通信的痛点。各个节点并不知道这个定时任务有没有被其他节点的定时器执行,所以理论上只需要有一个各个节点都能够访问到的资源,用这个资源去标记这个定时任务有没有执行就可以了。
2. Shedlock实现
Shedlock实现分布式锁,可以依赖如下组件:
- JdbcTemplate
- Mongo
- DynamoDB
- DynamoDB 2
- ZooKeeper (using Curator)
- Redis (using Spring
- RedisConnectionFactory)
- Redis (using Jedis)
- Hazelcast
- Couchbase
- ElasticSearch
- CosmosDB
- Cassandra
- Multi-tenancy
本文主要以来Redis为公共存储,实现定时任务的分布式锁。首先,我们假设你的Spring Boot项目已经引入了Redis,在项目的pom文件中加入依赖:
1 | <dependency> |
开启定时任务锁:
1 |
|
- defaultLockAtMostFor = “PT30S”表示默认锁的最大占用时间是30s;
其次,在定时任务方法上,加上注解@SchedulerLock:
1 | /** |
启动多个节点,会发现,每次定时任务只有一个节点执行,定时任务执行后,在Redis里会看到两个key:job-lock:default:testTask-1和job-lock:default:testTask-2。
3. Shedlock原理分析
Shedlock通过AOP,拿到TaskScheduler的行为做代理,并加入分布式锁实现所需要的功能。
上锁入口在RedisLockProvider.java:
1 |
|
可以看出上锁,其实就是Redis的set操作的过程。
任务执行的入口,可以参考net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor:
1 |
|
首先判断lock是否可用,然后再执行任务task.call()。
以上内容就是关于Spring Boot(八)之定时任务锁Shedlock的全部内容了,谢谢你阅读到了这里!
Author:zhaoyh