xxl-job如何保证调度的一致性
1:所谓的调度一致性,是指保证一次任务调度只有一个机器来执行,而不会因为其是分布式部署而出现多台机器同时执行某一个job
2:保证调度一次性的方法就是采用分布式锁,常见的分布式锁主要有以下3种方式
-
A): 基于缓存(redis)实现分布式锁
1:获取锁的时候,使用setnx命令来设置锁,同时对锁还增加了过期时间,value作为一个随机字符串,可以用来解锁的时候判断
2:获取锁的时候,增加了获取时间,如果超时,就没有获取锁
3:解锁的时候,通过随机字符串来判断是不是同一把锁。
(本篇文章不是来搞分布式锁的) -
B): 基于Zookeeper实现分布式锁
1:创建一个目录 mylock
2:线程A想获取锁,就在mylock目录下创建临时目录,会返回一个数字。
3:获取mylock目录下的所有子节点,然后获取比自己小的兄弟节点,如果不存在,说明当前线程的序号最小,那么它就获取了当前这把锁
4:线程B获取所有节点,判断自己是不是最小节点,设置监听比自己小一位的节点.(类似排队,只关注前一位)
5:线程A处理完毕后,删除自己节点。线程B监听到了变更事件,判断自己是不是最小的,获取到锁。 -
C): 基于数据库实现分布式锁
1:悲观锁
利用 select where for update。但是如果使用 “where name = XX” 此时name 必须走索引,否则会锁表
有些情况下,比如表数据不大,mysql可能会优化,不走索引,导致锁表问题。
2:乐观锁
通过加递增的版本号来实现乐观锁
3: 在xxl-job中实现分布式锁用的数据库的分布式锁,其中一个表只存储表的名称,通过 for update 来查询锁。
1):conn.setAutoCommit(false); 关闭隐式提交。
2):select * from xxl_job_lock where lock preparedStatement.execute(); 获得显示排他锁,然后开启事务。
3):conn.commit(); 事务完毕后,提交。
4):preparedStatement.close(); 释放悲观锁开启下一次轮回。
代码在:JobScheduleHelper
代码.png