最近项目中新增的一个功能是定时解绑未登录超过30天的用户。
由于生产环境下是4台服务器,为防止集群服务器定时任务多次执行和提高执行成功率,设计如下功能的实现。
一、设计思路和实现方案:
思路:数据库新建一张表,以当天日期(yyyyMMdd)作为主键。定时任务入口会新增到此表一条数据,新增成功,则执行接下来的定时任务;若新增失败被catch到异常,则return,不执行接下来的定时任务。
定时任务主表:
主键:id
解绑数量:unbind_num
执行服务器ip:execute_ip
创建时间:create_time
定时任务详情记录表:
主键:id
解绑数据的主要信息字段(此处不再记录详细字段,根据自己的需求记录即可)
解绑方式:unbind_type(可区分是定时任务解绑还是用户主动解绑)
执行服务器ip:execute_ip
创建时间:create_time
说明:主表的解绑数量和执行ip都是在定时任务执行完成后,根据主键进行的更新。(定时任务一开始就insert到主表一个主键 ,主要是获取执行权,防止有多个服务器同时获取执行权,最后解绑却出现问题)
定时任务程序入口:
MesQuartzJob mesQuartzJob = new MesQuartzJob();
mesQuartzJob.setQuId(timeYMD);
mesQuartzJob.setCreateTime(date);
String serIp ="";
try {
int insertSelective = mesQuartzJobMapper.insertSelective(mesQuartzJob);
serIp = GetIpUtils.getSerIp();
} catch (Exception e) {
log.error(
"method:RemoveBindQuartzJob:removeBindOutTime|mesQuartzJobMapper.insertSelective;inParam:执行服务器={};mesQuartzJob={};执行定时任务;异常:",
serIp,mesQuartzJob.toString(), e);
return;
}
##在之后的代码为解绑的执行逻辑,省略
##解绑完成后统计解绑数量并更新到主表
定时任务我们使用的quartz:
以下配置我们放在了spring的配置文件中,需保证RemoveBindQuartzJob实体被扫描到:
<!-- 全部定义到内部bean中,可以添加多个任务 -->
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!-- 解除绑定超过30天的操作员,注意:admin需特殊处理 -->
<bean class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail">
<bean
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 执行类 -->
<property name="targetObject">
<ref bean="removeBindQuartzJob" />
</property>
<!-- 类中要定时执行的方法 -->
<property name="targetMethod">
<value>removeBindOutTime</value>
</property>
</bean>
</property>
<property name="cronExpression" value=" 0 0 2 * * ? *" />
</bean>
</list>
</property>
</bean>
<!-- 配置任务所在的类 -->
<bean id="removeBindQuartzJob" class="com.xxx.xxx.quartz.RemoveBindQuartzJob" />