SpringCloud架构系统中如何保证集环境下定时任务同时只有
⼀个实例运⾏⼯作?
问题
⾸先说下情况,我们平常开发SpringCloud微服务的时候,若要确保⾼可⽤,同⼀服务都会部署多台实例,然后注册到Eureka上。
⼀般我们会把所有定时任务写到⼀个服务⾥,那平常单实例的时候,都可以正常执⾏。如果该定时任务服务部署多个实例,如何确保只在⼀个服务实例⾥执⾏任务呢?
个⼈总结了下,可以有以下解决思路。
解决
1. 如果原有的task代码同时执⾏⼀次或多次的结果都是正确的,那么可以就不做任何处理,只不过会造成资源浪费,当然这种⽅式不推荐。
⽐如图⾥的taskA是每隔五分钟更新下已完成的⼯单的记录为归档,那其实本质就是执⾏⼀个update的sql,即使是同时执⾏mysql数据库也有锁机制,所以数据不会出错。那多实例下也可以不做处理,不过再说⼀遍,虽然结果不会出错,但是不推荐这样做,还是要处理⼀下的。
2. 使⽤分布式锁
借助分布式锁,确保多个实例⾥的task只有竞争到锁的实例任务才执⾏。⽐如,redis的分不式锁。这种⽅式不好的地⽅是需要修改逻辑代码,增加了对redis的依赖。
3. 使⽤任务调度框架的集功能
之前我使⽤的是Quartz,Quartz是⼀个完全由Java编写的开源作业调度框架,Quartz的集功能通过故障转移和负载平衡功能为您的调度程序带来⾼可⽤性和可扩展性。这种⽅式也有不好的地⽅,那就是要
实现Quartz的集功能,需要修改Quartz的配置,⽽且是要额外增加Quartz集需要的数据库表,如果⼀开始开发没有考虑集,后⾯再加⼊改动会有点⼤。
4. 最⼩ip执⾏
这应该算是⼀个思路,我也是在⽹上看到的,具体实现是。
①先在代码⾥获取获取到当前实例的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⼀样。
springcloud实例总结
如果你的系统架构刚开始,那就可以把任务的分布式集情况考虑进去,使⽤集框架实现,如果你的系统已经完成或趋于稳定,则不建议⼤改,可以考虑⽅法2的分布式锁或者⽅法3。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论