思路:让定时任务执行时,随机睡几秒钟,首先执行的服务器更新job开关,执行完毕后关闭开关
一、代码
private static String serverIp = null; static { //获取服务器的IP地址,便于后续追踪 try { InetAddress address = InetAddress.getLocalHost(); serverIp = address.getHostAddress(); } catch (Exception e) { logger.error("获取服务器IP地址有误!!"); e.printStackTrace(); } } /** * 每日凌晨1点执行 */ @Scheduled(cron = "0 0 1 * * ?") public void xxxSchedule(){ logger.info("job start"); String jobName = "xxx"; long startTime = new Date().getTime(); try { if (canExecute(jobName)){ jobMapper.xxxSchedule(); jobMapper.updateJobStatus(jobName,serverIp,"off"); logger.info(jobName+"执行完成,耗时:"+(new Date().getTime()-startTime)+"毫秒!"); } } catch (Exception e) { e.printStackTrace(); } } private Boolean canExecute(String jobName) throws Exception { int max = 10000; int min = (int) Math.round(Math.random()*8000); long sleepTime = Math.round(Math.random()*(max-min)); logger.info(jobName+"睡了:"+ sleepTime + "毫秒"); Thread.sleep(sleepTime); if (jobMapper.getJobOff(jobName) == 1){ jobMapper.updateJobStatus(jobName,serverIp,"on"); return true; } logger.info(jobName+"已被其他服务器执行"); return false; }
二、数据库表
CREATE TABLE `job_manager` ( `job_name` varchar(50) NOT NULL PRIMARY KEY COMMENT '名称', `job_desc` varchar(50) COMMENT 'job描述', `server_ip` varchar(50) NOT NULL COMMENT '服务器ip', `on_off` varchar(10) DEFAULT 'off' COMMENT '开关(on:正在执行,off:执行完毕)', `update_date` datetime NOT NULL COMMENT '更新时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='job管理' ROW_FORMAT=DYNAMIC; INSERT INTO `job_manager` VALUES ('xxx','更新xxx的job','0.0.0.0','off',now());
三、查询或改状态的sql
如下sql中:on_off = 'off' AND update_date < curdate(),是可执行job的标志
<select id="getJobOff" parameterType="string" resultType="int"> SELECT count(1) FROM job_manager WHERE job_name = #{jobName} AND on_off = 'off' AND update_date < curdate() </select> <update id="updateJobStatus" parameterType="map"> UPDATE job_manager SET on_off=#{status},server_ip=#{serverIp},update_date=now() WHERE job_name = #{jobName} </update>