欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

集群环境定时器更新数据库,只有一台应用执行

程序员文章站 2022-04-01 23:44:23
...
批处理任务通过quartz控制执行的时候,如果有多个部署,就要避免部署的不同应用上的定时任务同时执行而导致的错误。

通过oracle的行锁,控制quartz的执行。

使用spring+quartz+ibatis
ibatis配置文件中里面的查询,如果发现存在对应的行被锁,直接抛出异常返回,知道当前任务正在执行
  <select id="abatorgenerated_selectByExampleForUpdate"  resultMap="abatorgenerated_SysRunParamResult" parameterClass="com.huateng.system.entity.SysRunParamExample" >
    select id, type, systemId, key, value, createId, createTime, oprId, oprTime, RESERVER1,
      RESERVER2, RESERVER3
    from HT_SYSRUNPARAM
    <isParameterPresent >
      <include refid="HT_SYSRUNPARAM.abatorgenerated_Example_Where_Clause" />
      <isNotNull property="orderByClause" >
        order by $orderByClause$
      </isNotNull>
    </isParameterPresent>
      for update nowait
  </select>



提供互斥控制的service层方法
/**
	 * key对应到定时任务的className全称
	 * 配置事务
	 * @param key   --用className作为key
	 * @param interval --获取quartz的执行间隔,单位为毫秒
	 * @param multiNum --异常情况下,多少次执行后,重新执行
	 * @return
	 */
	public boolean localQuartzServiceIsRunning(String key,Long interval,int  multiNum){
	    SysRunParam cur;
            try {
                cur = sysRunParamDAO.getSysRunParamForUpdate(key);
                System.out.println(cur);
            } catch (DataAccessException e) {
                System.out.println("执行过程冲突,DataAccessException+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
                return Boolean.TRUE; //访问报错,说明已经有执行
            } catch (ResultListEmptyException e) { //没有数据就初始化数据
                System.out.println("ResultListEmptyException");
                SysRunParam newParam=new SysRunParam();
                newParam.setId("1");
                newParam.setKey(key);
                newParam.setOprid("system");
                newParam.setOprtime(Calendar.getInstance().getTime());
                newParam.setType("quartz");
                newParam.setValue("ture");
                newParam.setCreatetime(Calendar.getInstance().getTime());
                newParam.setSystemid("2");
                sysRunParamDAO.insert(newParam);
                return Boolean.FALSE;//更新后执行
            }catch(Exception e){
                System.out.println("Exception");
                return Boolean.FALSE;
            }
	    String statu=cur.getValue();
	    Date lastUpdateTime=cur.getOprtime();//上一次执行时间
	    long executeInterval=System.currentTimeMillis()-lastUpdateTime.getTime();
	    if(Boolean.parseBoolean(statu)){
	        //如果长时间没有执行,也该修为执行,避免宕机导致的错误.
	        if(executeInterval>interval*multiNum){
	            System.out.println("executeInterval>interval*multiNum");
	            cur.setValue(Boolean.TRUE+"");
	            cur.setOprtime(Calendar.getInstance().getTime());
	            sysRunParamDAO.updateRecord(cur);
	            return Boolean.FALSE;
	        }else{
	            return Boolean.TRUE;
	        }
	    }else{                                                //如果没有执行,先更新状态
	        cur.setValue(Boolean.TRUE+"");
	        cur.setOprtime(Calendar.getInstance().getTime());
	        sysRunParamDAO.updateRecord(cur);
	        return Boolean.FALSE;
	    }
	}
	
	/**
	 *定时任务完成以后更新运行状态
	 * @param key
	 */
	public void updateLocalQuartzLock(String key){
	    SysRunParam cur;
        try {
            cur = sysRunParamDAO.getSysRunParamForUpdate(key);
            cur.setValue("false");
            cur.setOprtime(Calendar.getInstance().getTime());
            sysRunParamDAO.updateRecord(cur);
        } catch (DataAccessException e) {
            e.printStackTrace();
        } catch (ResultListEmptyException e) {
            e.printStackTrace();
        }
	}


定时器类
public class ActivityEffectJob  {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private SysRunParamService sysRunParamService;
	/**上一次执行的时间*/
	private static long lastExecuteTime=System.currentTimeMillis();
	private static final int multiNum=10;

	public void start() {
	    long lastExecuteTimetemp=lastExecuteTime;
	    lastExecuteTime=System.currentTimeMillis();
		if(sysRunParamService.localQuartzServiceIsRunning(MY_CLASS_NAME,System.currentTimeMillis()-lastExecuteTimetemp, multiNum)){
		    System.out.println(MY_CLASS_NAME+"'s job is running");
		    return;
		}
		try {
		    //works
		    Thread.sleep(1000);
		} catch (Exception e) {
        }finally{
            sysRunParamService.updateLocalQuartzLock(MY_CLASS_NAME);
            lastExecuteTime=System.currentTimeMillis();
            System.out.println("finally:"+MY_CLASS_NAME+"'s job is finnished");
        }

	}

	/**
	 * 当前类名
	 */
   private static final  String MY_CLASS_NAME;
    static{
        MY_CLASS_NAME = new Object() {  
            public String getClassName() {  
                String clazzName = this.getClass().getName();  
                return clazzName.substring(0, clazzName.lastIndexOf('$'));  
            }  
        }.getClassName();  
    }
    public SysRunParamService getSysRunParamService() {
        return sysRunParamService;
    }
    public void setSysRunParamService(SysRunParamService sysRunParamService) {
        this.sysRunParamService = sysRunParamService;
    }
    
    
}

建表脚本
create table HT_SYSRUNPARAM
(
  ID         VARCHAR2(30),
  TYPE       VARCHAR2(30),
  PARENTTYPE VARCHAR2(30),
  SYSTEMID   VARCHAR2(30),
  KEY        VARCHAR2(200),
  VALUE      VARCHAR2(200),
  DSC        VARCHAR2(500),
  CREATEID   VARCHAR2(30),
  CREATETIME TIMESTAMP(6),
  OPRID      VARCHAR2(30),
  OPRTIME    TIMESTAMP(6),
  RESERVER1  VARCHAR2(100),
  RESERVER2  VARCHAR2(100),
  RESERVER3  VARCHAR2(100)
)
;