SpringCloud架构系统中如何保证集群环境下定时任务同时只有一个实例运行工作?

Easter79
• 阅读 442

问题

首先说下情况,我们平常开发SpringCloud微服务的时候,若要确保高可用,同一服务都会部署多台实例,然后注册到Eureka上。

一般我们会把所有定时任务写到一个服务里,那平常单实例的时候,都可以正常执行。如果该定时任务服务部署多个实例,如何确保只在一个服务实例里执行任务呢?

SpringCloud架构系统中如何保证集群环境下定时任务同时只有一个实例运行工作?

个人总结了下,可以有以下解决思路。

解决

1. 如果原有的task代码同时执行一次或多次的结果都是正确的,那么可以就不做任何处理,只不过会造成资源浪费,当然这种方式不推荐。

比如图里的taskA是每隔五分钟更新下已完成的工单的记录为归档,那其实本质就是执行一个update的sql,即使是同时执行mysql数据库也有锁机制,所以数据不会出错。那多实例下也可以不做处理,不过再说一遍,虽然结果不会出错,但是不推荐这样做,还是要处理一下的。

2. 使用分布式锁

借助分布式锁,确保多个实例里的task只有竞争到锁的实例任务才执行。比如,redis的分不式锁。这种方式不好的地方是需要修改逻辑代码,增加了对redis的依赖。

3. 使用任务调度框架的集群功能

之前我使用的是Quartz,Quartz是一个完全由Java编写的开源作业调度框架,Quartz的集群功能通过故障转移和负载平衡功能为您的调度程序带来高可用性和可扩展性。这种方式也有不好的地方,那就是要实现Quartz的集群功能,需要修改Quartz的配置,而且是要额外增加Quartz集群需要的数据库表,如果一开始开发没有考虑集群,后面再加入改动会有点大。

4. 最小ip执行

这应该算是一个思路,我也是在网上看到的,具体实现是。

SpringCloud架构系统中如何保证集群环境下定时任务同时只有一个实例运行工作?

①先在代码里获取获取到当前实例的ip,通过一定算法规则转成一个Long型。
②从Eureka里根据实例名,图里的Taks-Server获取到对应的集群ip集合,也就是192.168.2.10、192.168.2.11、192.168.2.12,也分别把它们转成对应的Long型。
③拿第一步里的Long和第二步获取的Long的List做对比,如果判断到它是集合里最小的,那就在该实例里执行task,否则就retur掉。

这样就能确保永远只有一个实例执行定时任务了。

5. elastic-job

elastic-job 是由当当网基于quartz 二次开发之后的分布式调度解决方案,所以本质和方法3一样。

总结

如果你的系统架构刚开始,那就可以把任务的分布式集群情况考虑进去,使用集群框架实现,如果你的系统已经完成或趋于稳定,则不建议大改,可以考虑方法2的分布式锁或者方法3。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Spring Cloud Eureka源代码解析(1)Eureka启动,原生启动与SpringCloudEureka启动异同
Eureka作为服务注册中心对整个微服务架构起着最核心的整合作用,因此对Eureka还是有很大的必要进行深入研究。Eureka1.x版本是纯基于servlet的应用。为了与springcloud结合使用,除了本身eureka代码,还有个粘合模块springcloudnetflixeurekaserver。在我们启动EurekaServer实例
Wesley13 Wesley13
3年前
RAC环境单实例启动数据库收到ORA
     在RAC环境中,如果你在没有启动节点的集群服务的情况下单实例启动数据库,将收到类似如下的报错:\oracle@rhel1u01\$sqlSQL\Plus:Release10.2.0.5.0ProductiononTueApr215:00:272013Copyright(
Stella981 Stella981
3年前
Spring Cloud Eureka 服务关闭但是未从注册中心删除 自我保护机制
自我保护背景首先对Eureka注册中心需要了解的是Eureka各个节点都是平等的,没有ZK中角色的概念,即使N1个节点挂掉也不会影响其他节点的正常运行。默认情况下,如果EurekaServer在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,EurekaServer将会移除该实例。但是当网络分区故障发生时,微服务与EurekaSer
Wesley13 Wesley13
3年前
C#中依赖注入
由于客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户只定义一个注入点。在程序运行过程中,客户类部直接实例化具体服务类实例,而是客户类的运行上下文环境或者专门组建负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。依赖注入的方法大致分为3中:接口注入、构造方法注入、setter注入;1、setter注入setter注入是指
记一次SpringBoot服务生产环境内存占用过高的排查
缘起生产环境服务A部署在K8s上,某天运维告诉我这个服务经常会重启,客户没有报告是因为我们是滚动发布更新,先启动这个服务的一个新实例,然后将旧实例Kill掉,这样前端是无感知的,但重启是实实在在存在的,生产问题不可马虎,于是开启了定位问题之旅。过程定位问题
Java服务总在半夜挂,背后的真相竟然是... | 京东云技术团队
最近有用户反馈测试环境Java服务总在凌晨00:00左右挂掉,用户反馈Java服务没有定时任务,也没有流量突增的情况,Jvm配置也合理,莫名其妙就挂了
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k