先说一下我们的系统,

在65和66上分别部署有weblogic节点,共计四个,在项目中我们的定时器会隔一段时间就从其它的五个系统中取数据,这时就出现了问题,本来取一次数据就可以的,现在重复执行了三次,同时还造成了对方服务器的压力。

现在说一下我们项目怎么解决的这个问题:

1、首先想到的是在定时执行任务这个文件中添加ip地址,固定成某一台能执行,但我们一台服务器上有两个节点,方案不可行。

2、后来想到使用redis来保存一个状态位,是1表示可以执行,0表示不可以执行,但要是一个节点get到的是1,在它设置此status为0的时候,另一个节点提前一点点get到的也是1,这个时候这两个节点就都会执行,随后想到可不可以使用redis的事务加watch关键字,细想之后redis的事务是一组命名打包执行,中间不再执行其它操作,也实现不了。

3、既然redis的事务不可以,那数据库的应该可以吧。从而最终找到了现在的解决方案。

能解决的问题:

1、多个节点只有一个节点执行任务

2、即使某个正在执行的节点挂掉了,没有来的及修改状态位,也不影响定时器的执行。

下面是数据库表的设计:

这个表是用来表示当前查询的任务是否可以执行,通过type字段可以将多个不同类型的定时器进行区分,从而实现表的共用。

此表中的status字段表示是否可以执行定时任务。

Datetime字段用来记录当前任务的执行时间。

Intervallen这个字段是我们规定一段时间间隔。

代码示例如下:

------------------------------------------

这个是具体的查询是否可以执行任务的逻辑。

下面是具体的sql

这里的for update很重要。

下面针对上面的步骤说明一下:

1、当定时器执行的时候会执行running = sysScheduleStatusService.getAndSetScheduleStatus(parameter);

这个方法,running表示是否可以执行,true表示可以执行。

2、在这个方法中,会先执行SysScheduleStatus scheduleStatus = sysScheduleStatusDao.getScheduleStatus(parameter);这个方法,此方法会调用id为getScheduleStatus的sql语句,这个语句中的for update 关键字会对查询出来的记录加锁。即:

对这一条记录加锁(type为1表示某个类型的定时器)。
然后根据取出来的数据判断status是否为1,为1表示可以执行此定时器,随即调用update方法,将数据库的此字段改为0(不可以执行),提交事务,返回true。由于for update的存在,当某个线程执行这个查询语句的时候,已经对此条记录加锁,别的线程再去查询的时候就会处于等待状态,直到这个线程的事务提交,然后才可以查询,此时查询到的status为0,不可以执行,返回false。
在定时器方法的最后我们要更新表的status为1,以便下一次能顺利执行。这个update的方法我们一定要放到finally中,否则出现异常就有可能这个状态位一直为0了(其实为0也可以解决的);
我们通过status是否为1来判断是否可以执行,但要是节点在执行定时器的时候突然宕机或者其它原因,没有及时的将status设置成1,这个时候我们的定时器就永远走不了了。在这里就使用到了datetime字段和intervallen字段了。
逻辑:当status为0时,我们继续向下走,获取当前时间,当当前时间大于datetime+intervallen时我们就认为某个执行定时器的节点不是宕机就是出现其它异常导致未能及时的将status字段设置成1。这时我们照样返回true,同时更新一下对应type的status和datetime字段。这样即使节点挂掉,也不影响下一次定时任务的执行(由其它节点执行)。
在我这个代码里面我是直接在数据库里面进行了判断,isovertime表示是否超时,为1表示超时我们返回true,执行任务。(这样考虑是因为我们用sysdate来和datetime比较是比较好的,如果我们拿到java代码里面的话,有可能java运行的服务器的时间和数据库的时间不同步)
 
优化:由于我们的定时任务执行的时间比较长,其实还可以将查询出来的list分成三四个list,然后让spring的线程池threadPoolTaskExecutor来执行,从而减少执行时间。
 

要说明一点:

Service 中的这个getAndSetScheduleStatus()方法一定要开启事务。我在做这个的时候发现我们项目中的事务配置的不太对,从而这个方法没有开启事务,当多个节点执行时就出现因为for update而一直等待的情况。下图是事务的配置:


https://zhidao.baidu.com/question/510837808.html
 
 

多台或者集群环境下如何保证spring定时器只执行一个的更多相关文章

  1. Ubuntu14(64位) 集群环境下安装Hadoop2.4

    经过前边的积累,今天最终实现了集群环境下部署Hadoop.并成功执行了官方的样例. 工作例如以下: 两台机器: NameNode:上网小本,3G内存.机器名:YP-X100e,IP:192.168.1 ...

  2. CAS服务器集群和客户端集群环境下的单点登录和单点注销解决方案

    CAS的集群环境,包括CAS的客户应用是集群环境,以及CAS服务本身是集群环境这两种情况.在集群环境下使用CAS,要解决两个问题,一是单点退出(注销)时,CAS如何将退出请求正确转发到用户sessio ...

  3. 分布式集群环境下,如何实现session共享一(应用场景)

    在web应用中,由于http的请求响应式,无状态.要记录用户相关的状态信息,比如电商网站的购物车,比如用户是否登录等,都需要使用session.我们知道session是由servlet容器创建和管理, ...

  4. 分布式集群环境下,如何实现session共享四(部署项目测试)

    这是分布式集群环境下,如何实现session共享系列的第四篇.在上一篇:分布式集群环境下,如何实现session共享三(环境搭建)中,已经准备好了相关的环境:tomcat.nginx.redis.本篇 ...

  5. quartz在集群环境下的最终解决方案

    在集群环境下,大家会碰到一直困扰的问题,即多个 APP 下如何用 quartz 协调处理自动化 JOB . 大家想象一下,现在有 A , B , C3 台机器同时作为集群服务器对外统一提供 SERVI ...

  6. 集群环境下,Session管理的几种手段

    集群环境下,Session管理的几种手段 1.Session复制 缺点:集群服务器间需要大量的通信进行Session复制,占用服务器和网络的大量资源. 由于所有用户的Session信息在每台服务器上都 ...

  7. 集群环境下的Session管理

    1. 集群环境下的管理HTTPSSession所遇到的问题 一台服务器对应这个一个session对象,无法在另外一个服务器互通 解决方法: 1. Session 的 Replication(复制)将当 ...

  8. 在Hadoop1.2.1分布式集群环境下安装hive0.12

    在Hadoop1.2.1分布式集群环境下安装hive0.12 ● 前言: 1. 大家最好通读一遍过后,在理解的基础上再按照步骤搭建. 2. 之前写过两篇<<在VMware下安装Ubuntu ...

  9. 在tomcat集群环境下redis实现分布式锁

    上篇介绍了redis在集群环境下如何解决session共享的问题.今天来讲一下如何解决分布式锁的问题 什么是分布式锁? 分布式锁就是在多个服务器中,都来争夺某一资源.这时候我们肯定需要一把锁是不是 , ...

随机推荐

  1. Java-IO之BufferedReader(字符缓冲输入流)

    BufferedReader是缓冲字符输入流,继承于Reader,BufferedReader的作用是为其他字符输入流添加一些缓冲功能. BufferedReader主要的函数列表: Buffered ...

  2. Andriod的国际化-android学习之旅(五十八)

    android资源国际化

  3. gcov辅助脚本

    gcov辅助脚本(金庆的专栏)代码覆盖测试查看结果时,需要进入代码所在目录,调用gcov,然后vi查看.因为代码目录结构复杂,进出子目录太麻烦,所以用以下脚本直接生成与查看.一般是用TSVN列出有更改 ...

  4. Java进阶(二十四)Java List集合add与set方法原理简介

    Java List集合add与set方法原理简介 add方法 add方法用于向集合列表中添加对象. 语法1 用于在列表的尾部插入指定元素.如果List集合对象由于调用add方法而发生更改,则返回 tr ...

  5. R12 - Error 'Unable to process your transaction. The operating unit is either invalid or it cannot b

    In this Document   Symptoms   Cause   Solution   Still Have Questions?   References APPLIES TO: Orac ...

  6. log4xx/log4j异步日志配置示例

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration S ...

  7. mpi中的广播

    MPI可以实现一对多的集合通信,最常用的是广播:某个进程将数据广播到所有其他进程,最终的结果就是每个进程都有一份广播的数据.MPICH中的广播函数是MPI_Bcast(void* buffer,int ...

  8. VS2008中开发手持终端程序(PDA软件)总结

    VS2008中开发手持终端程序(PDA手机软件)的项目总结 1程序结构 程序中包括四个部分: 1.系统配置 这个部分用来配置系统中的相关参数,参数包括数据库信息和串口的配置信息.这部分的主要技术是XM ...

  9. Leetcode_94_Binary Tree Inorder Traversal

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42876657 Given a binary tree, r ...

  10. iOS实现时间线列表效果(例如订单详情页面的效果)

    之前看到美团的订单详情页面很有特色,于是决定模仿一下这个效果. 其实就是简单的 TableView 技巧,下面我们就来一步一步实现它. 设计 TableViewCell 原型 子类化一个新的 UITa ...