ShedLock锁,防止spring定时调度@Scheduled注解在分布式环境下重复执行

更新时间:2023-07-12 18:31:50 阅读: 评论:0

ShedLock锁,防⽌spring定时调度@Scheduled注解在分布式环境下重复执⾏
多个微服务,其业务的逻辑是⼀样的,⾃然包括定时任务。负载均衡在执⾏的时候,到达某个节点以后,定时任务都会执⾏,可以控制的思路就是使⽤队列的⽅式去操作。
如下有两种思路:
where
将负载均衡的定时任务,从原先的直接执⾏业务逻辑修改为先将业务逻辑请求到队列中,然后让空闲的微服务去队列中⾃动领取;
将负载均衡的定时任务,加锁进⾏操作。
ShedLock
ShedLock就是⼀种巧妙使⽤锁的⽅式的,在GitHub中的地址:GitHub - lukas-krecan/ShedLock: Distributed lock for your scheduled tasks
ShedLock does one and only one thing. It makes sure 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). Plea note, that if one task is already being executed on one node, execution on other nodes does not wait, it is simply skipped.
Currently, Spring scheduled tasks coordinated through Mongo, JDBC databa, Redis, Hazelcast or ZooKeeper are supported. More scheduling and coordination mechanisms and expected in the future.
ShedLock is not a distributed scheduler
Plea note that ShedLock is not and will never be full-fledged scheduler, it’s just a lock. If you need a distributed scheduler, plea u another project. ShedLock is designed to be ud in situations where you have scheduled tasks that are not ready to be executed in parallel, but can be safely executed repeatedly. For example if the task is fetching records from a databa, processing them and marking them as procesd at the end without using any transaction. In such ca ShedLock may be right for you.
By tting lockAtMostFor we make sure that the lock is relead even if the node dies and by tting lockAtLeastFor we make sure it’s not executed more than once in fifteen minutes. Plea note that if the task takes longer than 15 minutes, it will be executed again.
个⼈理解,拿JDBCTemplate进⾏说明,就是当第⼀个微服务执⾏定时任务的时候,会将此定时任务进⾏锁操作,然后其他的定时任务就不会再执⾏,锁操作有⼀定的时长,超过这个时长以后,再⼀次,
所有的定时任务进⾏争抢下⼀个定时任务的执⾏权利,如此循环。其中两个配置lockAtMostFor和lockAtLeastFor,保证了在⼀个定时任务的区间内只有⼀个定时任务在执⾏,同时也保证了即便是其中的⼀个定时任务挂掉了,到⼀定的时间以后,锁也会释放,其他的定时任务依旧会进⾏执⾏权的争夺,执⾏定时任务。
使⽤步骤
1、环境⽀持
Java 8 、slf4j-api、Spring Framework(可选)
2、依赖引⼊
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>0.18.2</version>
</dependency>
3、定时任务的写法
import net.SchedulerLock;
...
@Scheduled(...)
@SchedulerLock(name = "scheduledTaskName")
public void scheduledTask() {
// do something
}
The @SchedulerLock annotation has veral purpos. First of all, only annotated methods are locked, the library ignores all other scheduled tasks. You also have to specify the name for the lock. Only one tasks with the same name can be executed at the same time.
You can also t lockAtMostFor attribute which specifies how long the lock should be kept in ca the executing node dies. This is just a fallback, under normal circumstances the lock is relead as soon the tasks finishes.
Lastly, you can t lockAtLeastFor attribute which specifies minimum amount of time for which the lock should be kept. Its main purpo is to prevent execution from multiple nodes in ca of really short tasks and clock difference between the nodes.
⽰例
Let’s say you have a task which you execute every 15 minutes and which usually takes few minutes to run. Moreover, you want to execute it at most once per 15 minutes. In such ca, you can configure it like this
import net.SchedulerLock;
...
private static final int FOURTEEN_MIN = 14 * 60 * 1000;
...
@Scheduled(cron = "0 */15 * * * *")
@SchedulerLock(name = "scheduledTaskName", lockAtMostFor = FOURTEEN_MIN, lockAtLeastFor = FOURTEEN_MIN)
public void scheduledTask() {
// do something
}
By tting lockAtMostFor we make sure that the lock is relead even if the node dies and by tting lockAtLeastFor we make sure it’s not executed more than once in fifteen minutes. Plea note that if the task takes longer than 15 minutes, it will be executed again.
4、配置task
Now we need to integrate the library into Spring. It’s done by wrapping standard Spring task scheduler.
import net.javacrumbs.shedlock.spring.SpringLockableTaskSchedulerFactory;
新东方英语900句
...
@Bean
public ScheduledLockConfiguration taskScheduler(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}
Or if you already have an instance of ScheduledExecutorService天生皮肤黑怎么快速美白
@Bean
public TaskScheduler taskScheduler(ScheduledExecutorService executorService, LockProvider lockProvider) {
wLockableTaskScheduler(executorService, lockProvider, Duration.of(10, MINUTES));
}
5、配置锁
锁的配置有多种⽅式的,如下的。
a、Mongo
Import the project
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-mongo</artifactId>
<version>0.18.2</version>
</dependency>
Configure:
import net.javacrumbs.MongoLockProvider;
...
@Bean
public LockProvider lockProvider(MongoClient mongo) {
hesitated
成人高考英语词汇return new MongoLockProvider(mongo, "databaName");
}
Plea note that MongoDB integration requires Mongo >= 2.4 and mongo-java-driver >= 3.4.0 b、JdbcTemplate
Create the table
CREATE TABLE shedlock(
name VARCHAR(64),
lock_until TIMESTAMP(3) NULL,
locked_at TIMESTAMP(3) NULL,
locked_by  VARCHAR(255),
PRIMARY KEY (name)
)
Add dependency
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>0.18.2</version>
</dependency>
Configure:
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
...
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource);
}
Tested with oracle
c、Plain JDBC
For tho who do not want to u jdbc-template, there is plain JDBC lock provider. Just import
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc</artifactId>
<version>0.18.2</version>
</dependency>
团子大家族罗马音
and configure
import net.javacrumbs.shedlock.provider.jdbc.JdbcLockProvider;
...
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcLockProvider(dataSource);
}
the rest is the same as with JdbcTemplate lock provider.
Warning
Do not manually delete lock row or document from DB table or Mongo collection. ShedLock has an in-memory cache of existing locks so the row will NOT be automatically recreated until application restart. If you need to, you can edit the
row/document, risking only that multiple locks will be held. Since 0.18.2 you can clean the cache by calling clearCache() on LockProvider.
d、ZooKeeper (using Curator)
Import
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-zookeeper-curator</artifactId>
<version>0.18.2</version>
</dependency>
configure
import net.javacrumbs.keeper.curator.ZookeeperCuratorLockProvider;
...
@Bean
public LockProvider lockProvider(org.apache.curator.framework.CuratorFramework client) {
initiativereturn new ZookeeperCuratorLockProvider(client);
}
By default, ephemeral nodes for locks will be created under /shedlock node.
e、Redis (using Spring RedisConnectionFactory)
Import
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-spring</artifactId>
<version>0.18.2</version>
橄榄球英文
billie jean歌词翻译</dependency>
and configure
import net.javacrumbs.dis.spring.RedisLockProvider;
...
@Bean
public LockProvider lockProvider(JedisPool jedisPool) {
return new RedisLockProvider(connectionFactory, ENV);
}
f、Redis (using Jedis)
Import
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-jedis</artifactId>
<version>0.18.0</version>
</dependency>
and configure
import net.javacrumbs.dis.jedis.JedisLockProvider;
...
@Bean
public LockProvider lockProvider(JedisPool jedisPool) {
return new JedisLockProvider(jedisPool, ENV);
}
g、Spring XML configuration
If you are using Spring XML config, u this configuration
<!-- lock provider of your choice (jdbc/zookeeper/mongo/whatever) -->
<bean id="lockProvider" class="net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockPr
男风ovider">    <constructor-arg ref="dataSource"/>
</bean>
<bean id="scheduler" class="net.javacrumbs.shedlock.spring.SpringLockableTaskSchedulerFactoryBean">    <constructor-arg>
<task:scheduler id="sch" pool-size="10"/>
</constructor-arg>
<constructor-arg ref="lockProvider"/>
<constructor-arg name="defaultLockAtMostFor">
<bean class="java.time.Duration" factory-method="ofMinutes">
<constructor-arg value="10"/>
</bean>
</constructor-arg>
</bean>
<!-- Your task(s) without change (or annotated with @Scheduled)-->
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="task" method="run" fixed-delay="1" fixed-rate="1"/>
</task:scheduled-tasks>
Annotate scheduler method(s)
@SchedulerLock(name = "taskName")
public void run() {
}
Running without Spring
It is possible to u ShedLock without Spring
LockingTaskExecutor executor = new DefaultLockingTaskExecutor(lockProvider);
...
Instant lockAtMostUntil = w().plusSeconds(600);

本文发布于:2023-07-12 18:31:50,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/175331.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:任务   业务   逻辑   队列   注解   皮肤   负载
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图