先说一下我们的系统,

在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. 【一天一道LeetCode】#263. Ugly Number

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Write a ...

  2. 最近很多人问我:saiku下载不下来

    saiku的前段团队 在UI设计方面很专业.但是兼容性差到让人无语.不知道为什么,是不是不给钱,人家故意黑它. 一直忙别的工作,现在整理一些saiku相关网站,百度不到的,google又要FQ.看个合 ...

  3. Cocos2D:塔防游戏制作之旅(三)

    整合炮塔资源 为了快速开始,我们为你创建了开始的项目.它包括了一个空白的Cocos2D项目以及大多数你将在教程中使用到的资源. 所以首先下载该 开始项目 并且解压缩到你指定的位置中去. 注意:该项目的 ...

  4. C算法分解质因数与分解因子

    ) ) printf("%d ",i); } }

  5. Java 8新特性探究(四)深入解析日期和时间-JSR310

    众所周知,日期是商业逻辑计算一个关键的部分,任何企业应用程序都需要处理时间问题.应用程序需要知道当前的时间点和下一个时间点,有时它们还必须计算这两个时间点之间的路径.但java之前的日期做法太令人恶心 ...

  6. Leetcode_119_Pascal's Triangle II

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41851069 Given an index k, retu ...

  7. C++对象模型(二):The Semantics of Copy Constructors(拷贝构造函数之编译背后的行为)

    本文是 Inside The C++ Object Model's Chapter 2  的部分读书笔记. 有三种情况,需要拷贝构造函数: 1)object直接为另外一个object的初始值 2)ob ...

  8. 友善之臂tiny4412-1306开发板安卓系统烧写

    折腾了很久,终于烧写成功.不废话,咱们说说流程吧. 首先,我们需要有一个基于tiny4412的kernel,从友善之臂官网获取. 然后解压: 1.tar -xvf  linux-3.5 .... 然后 ...

  9. 【62】Spring总结之bean(3)

    Spring核心机制:依赖注入 Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因此,我们说这些对象间存在依赖关系.加入 ...

  10. LIRe 源代码分析 7:算法类[以颜色布局为例]

    ===================================================== LIRe源代码分析系列文章列表: LIRe 源代码分析 1:整体结构 LIRe 源代码分析 ...