精华内容
下载资源
问答
  • 背景 在实际项目开发中,当编写一个定时任务时候,不同开发人员在自己机器上跑导致数据重复插入。此时同步锁解决已经无法解决这种...多个定时任务,是多个key,不能set一样的,各管各的定时任务。懂redis的应该都明白 .
    • 背景

    在实际项目开发中,当编写一个定时任务时候,不同开发人员在自己机器上跑导致数据重复插入。此时同步锁解决已经无法解决这种不同集群上的问题了。

    • 引出

    使用redis解决
    利用redis是单线程的特性

    • 核心代码
    if(redisTemplate.opsForValue().setIfAbsent("getsnInfo","11")){ //key的值放什么不重要,重要的是key.所以11或者aa都行。多个定时任务,是多个key,不能set一样的,各管各的定时任务。懂redis的应该都明白
    	try{
    
    	// 业务代码
    
      		}catch(){ 
      			redisTemplate.delete("getsnInfo"); 
      		}
      			redisTemplate.delete("getsnInfo");
    }
    
    • 注意
      异常里和方法结尾,都要加上删除key标识。否则当系统异常退出和正常执行退出时,key还在,未来的定时任务将永远不会被执行。

    • 关于setIfAbsent分析

    相当于redis中
    setnx (set if not exist)(分布式锁中经常会使用)不存在设置,如果存在不会覆盖还是使用之前存在的值。

    案例:
    127.0.0.1:6379> keys *
    1) "key1"
    127.0.0.1:6379> get key1
    "zhangsan"
    127.0.0.1:6379> setnx key1 lisi
    (integer) 0
    127.0.0.1:6379> get key1
    
    展开全文
  • 集群服务器定时任务重复执行的解决方案 服务器采用了负载均衡,有两台服务器,部署的代码一样,所以里面的定时任务在某一时间会被同时执行,这就导致了很其他意外的发生,想要解决的问题基本就三:单点执行,...

    集群服务器定时任务重复执行的解决方案

    96

    服务器采用了负载均衡,有两台服务器,部署的代码一样,所以里面的定时任务在某一时间会被同时执行,这就导致了很多其他意外的发生,想要解决的问题基本就三个:单点执行,故障转移,服务状态。这里对比一下网上找的几种方案,:

    (1)只在一台服务器上部署该定时任务代码。

    优点:解决方法容易理解    缺点:部署麻烦,需要多套代码,且当这台服务器出问题时就没定时任务了。

    (2)在定时任务代码上加上某个特定的ip限制,仅某个ip的服务器能运行该定时任务。

    优点:解决方法容易理解,部署简单,不需要多套代码。  缺点:同上,只能规定一台服务器运行,发送故障时就没办法了。

    (3)利用数据库的共享锁事务管理机制来运行定时任务。

    参考博客:https://blog.csdn.net/u012881584/article/details/70194237

    原理:在数据库中新建一张表定时任务表,存储了上次执行定时任务的ip地址(ip),任务名称(task_name),是否正在执行(execute)。原博客用代码的方式解释了自己的思路,这里我用文字来总结一下:

    集群中的所有服务器都是走以下流程

    第一步:查找数据库的定时任务表。

    第二步:检查是否有机器在运行定时任务。检查方法:update定时任务表的excute字段为1(1为执行中,0为未执行)、ip为自己的ip,如果update失败,则证明有机器在执行该定时任务,该机器的定时任务就不执行了,成功则进行第三步。

    第三步:执行定时任务的具体内容。

    第四步:还原excute字段为0。

    以上是该方案的流程,利用了mysql的共享锁机制判断,通过是否更新成功来判断是否有机器正在执行定时任务,这种方案可以保证任务只执行一次,且只要集群中有一台服务器是好的,就会执行任务。方案挺好,暂时想不到有啥缺点,可能增加了数据库的负担算一个吧....

    (4)利用redis数据库。

    参考:https://www.jianshu.com/p/48c5b11b80cd

    原理:和第三种差不多,只是通过redis的key-value来存储任务名--执行ip。执行定时任务前先查询redis是否有改任务的值,没有就自己 执行,并插入新的key-vale。有的话就查看ip是否是自己,是的话就执行,不是的话就 证明有其他机器在执行,自己就不执行啦。过期时间可以自己设置,方便有机器出故障时候可以转移机器执行任务。

    优点:利用了redis的自动过期机制实现了转移故障机器的问题,比较简单,而且redis的访问速度也很快。

    缺点:这里没有事务管理机制,访问redis的时候,一定会出现高并发的情况,所以得自己实现redis的共享锁机制。

    (5)利用quartz集群分布式(并发)部署解决方案。

    参考:https://www.tuicool.com/articles/B3qeUrB

    quartz有很成熟的分布式并发部署定时任务的解决方案了,但是配置比较复杂,且需要新建恨的数据库表,这里就不详细写了(好吧,我也没认真看....)

    综上所述,我觉得第三种方案适合小型的项目去做,大的项目最好用quartz去做。

    在实现的过程中又发现,同一台服务器上的不同版本之间也会发生cron重复执行的问题,所以不仅考虑不同服务器的问题,还得考虑不同版本之间的问题。

    展开全文
  • 方法:新建一张任务执行表,每次执行定时任务之前先insert该表。 比如:每天执行一次批处理操作。主键可以设置为批处理name+日期(年月日)。集群服务器可能会同时去insert该表,而只有一台服务器能插入成功,则只...

    1、Oracle

    思路:Insert表内容时,主键重复,无法插入

    范围:适用于执行频率低的定时任务

    方法:新建一张任务执行表,每次执行定时任务之前先insert该表。

    比如:每天执行一次批处理操作。主键可以设置为批处理name+日期(年月日)。集群服务器可能会同时去insert该表,而只有一台服务器能插入成功,则只让这一台服务器执行该批处理任务。

     

    2、Redis

    范围:适用于执行频率高的定时任务

    有如下两种思路方法:

    思路1:采用的是redis中list的push和pop操作。因为Redis是单线程,所有命令依次执行,所以不会出现多台服务器同时访问的情况。

    方法:系统初始化时,向Redis中lpush一个list(key,1),作为标识Flag。每台服务器执行批处理之前,先去rpop该list,只有获取到该标识的服务器才能执行批处理任务,执行完毕后再lpush回一个list(key,1)。

    比如:执行任务前先执行rpopRedisFlag,任务完成后执行lpushRedisFlag.

    public class AutoJobActDis extends QuartzJobBean {
        
        @Override
        protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException                         {
            if (rpopRedisFlag("AUTO_JOB_ACTDIS")) {
                this.executeJob(this);
                lpushRedisFlag("AUTO_JOB_ACTDIS");
            }
        }
        /**
         * 从缓存中取得Flag,获取定时任务执行权限
         *
         * @param redisKey
         * @return
         */
        public boolean rpopRedisFlag(String redisKey) {
            String redisValue = redisService.rpopRedisList(redisKey);
            if (StringUtil.isEmpty(redisValue)) {
                return false;
            } else {
                return true;
            }
        }
    
        /**
         * 缓存中增加Flag
         *
         * @param redisKey
         */
        public void lpushRedisFlag(String redisKey) {
            redisService.lpushRedisList(redisKey, "1");
        }
    }
    
    public class RedisService {
        /**
    	 * 存储Redis队列,顺序存储
    	 * @param key redis键名
    	 * @param value 键值
    	 */
    	public void lpushRedisList(String key, String value) {
    		Jedis jedis = null;
    		try {
    			jedis = jedisClient.getClient();
    			jedis.lpush(key, value);
    		} catch (Exception e) {
    			logger.error(e.getMessage(), e);
    		} finally {
    			if (jedis != null) {
    				jedis.close();
    			}
    		}
    	}
    
    	/**
    	 * 移除并获取列表最后一个元素
    	 * @param key
    	 * @return
    	 */
    	public String rpopRedisList(String key) {
    		Jedis jedis = null;
    		try {
    			jedis = jedisClient.getClient();
    			return jedis.rpop(key);
    		} catch (Exception e) {
    			logger.error(e.getMessage(), e);
    		} finally {
    			if (jedis != null) {
    				jedis.close();
    			}
    		}
    		return null;
    	}
    }

    思路2:采用的是redis中String的incr和expire操作。因为Redis是单线程,所有命令依次执行,所以不会出现多台服务器同时访问的情况。

    语法:INCR key  将 key 中储存的数字值增一。

        Redis Incr 命令将 key 中储存的数字值增一。

        如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

        如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

        本操作的值限制在 64 位(bit)有符号数字表示之内。

    EXPIRE key seconds  为给定 key 设置过期时间。

        Redis Expire 命令用于设置 key 的过期时间。key 过期后将不再可用。

    方法:每台服务器执行批处理之前,先去incr一个固定key,只有返回值等于1的服务器才能执行批处理任务,然后将该key值设置过期时间。

    比如:

    			jedis = jedisTool.getJedis();
    			if(jedis.incr(PRE_AGAIN_REDIS+batchId)!=1) {
    				logger.info("其他机器已经重跑");
    				return ;
    			} else {
    				jedis.expire(PRE_AGAIN_REDIS+batchId, 60);//设置60s过期
    			}

     

    展开全文
  • 前面的章节,用户通过绑定手机号的注册为会员,并可以补充完个人信息,比如姓名、生日等信息,拿到用户的生日信息之后,就可以通过会员生日信息进行营销,此处就涉及到定时任务执行营销信息推送的问题。本篇就带你...

    前面的章节,用户通过绑定手机号的注册为会员,并可以补充完个人信息,比如姓名、生日等信息,拿到用户的生日信息之后,就可以通过会员生日信息进行营销,此处就涉及到定时任务执行营销信息推送的问题。本篇就带你走入微服务下的定时任务的构建问题。

    定时任务选型

    常见的定时任务的解决方案有以下几种:

    右半部分基于 Java 或 Spring 框架即可支持定时任务的开发运行,左侧部分需要引入第三方框架支持。针对不同方案,作个简单介绍

    • XXL-JOB 是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。任务调度与任务执行分离,功能很丰富,在多家公司商业产品中已有应用。官方地址:https://www.xuxueli.com/xxl-job/
    • Elastic-Job 是一个分布式调度解决方案,由两个相互独立的子项目 Elastic-Job-Lite 和 Elastic-Job-Cloud 组成。Elastic-Job-Lite 定位为轻量级无中心化解决方案,依赖 Zookeeper ,使用 jar 包的形式提供分布式任务的协调服务,之前是当当网 Java 应用框架 ddframe 框架中的一部分,后分离出来独立发展。
    • Quartz 算是定时任务领域的老牌框架了,出自 OpenSymphony 开源组织,完全由 Java 编写,提供内存作业存储和数据库作业存储两种方式。在分布式任务调度时,数据库作业存储在服务器关闭或重启时,任务信息都不会丢失,在集群环境有很好的可用性。
    展开全文
  • 项目里面提供的时间是半小时或整点去执行Spring定时任务,查询数据库中有哪些Schedule是满足要求的,然后去执行那些符合条件的任务。 一切功能表现正常,但是项目部署在服务器上后,用户反映在同一时间会收到两封...
  • 第二章会动态配置定时任务,cron表达式,定时任务时间,名称等都从前台页面而来,实现定时任务的增删改查(详情请阅读第二章)。 本章配置如下: <bean id="timedtask" class="org.springframework.scheduling...
  • 定时任务重复执行多

    千次阅读 2017-04-28 14:29:58
    定时任务,在本地测试执行正常,但是发布到服务器,发现到执行时间,总会重复执行多次; 解决办法:服务器端的server.xml文件host修改配置:autoDeploy="false" deployOnStartup="false
  • Spring提供了定时任务的功能,但是在多个实例的集群中,会出现定时任务重复执行多次的情况。 使用Qutaz框架自带的分布式定时任务可以很好的解决这个问题,但是讲道理功能有些过于强大,对于需求不高,乃至可以一定...
  • 生产上是两台集群服务器,项目部署上去发现定时任务的模块同时在两台机器上各执行了一遍,这将会导致其他意外的发生。 解决方案----redis分布式锁 使用redis分布式锁,为定时任务唯一指定的key加锁,并设置锁超时...
  • 那么定时任务是否会启用多个线程,叠加执行? 测试: 定时任务配置: <task:scheduled-tasks> <task:scheduled ref="bsMailServiceImpl" method="doAgain" cron="0/5 * * * * ...
  • NULL 博文链接:https://medbricom.iteye.com/blog/1782765
  • 分布式定时任务重复执行记录

    千次阅读 2019-03-07 10:57:37
    背景: 一项目拆分了几可单独运行的模块。 A模块中的定时器每30s去执行一次任务,A模块中的定时器每30s去执行一次任务...技术: 原本是在ssm框架下的定时任务是没有出现重复执行的情况,现在迁移到了spring...
  • 当服务部署在负载均衡下的服务器上时,无法通过在代码里面添加同步阻止比如定时器重复执行,用户重复提交等问题发生,这时可以使用分布式锁 当然,这只是简单的demo,而且没有实现原子性,如果是定时任务,可以获取...
  • 问题描述: 公司项目,每天凌晨1点会执行一条定时任务...生产环境用的是集群环境,一共部署到了4台服务器上,因此同一时间点,同一个定时任务 会被重复执行4次。 解决办法: 锁。 数据库新建一张表。 CREATE TABLE `t_
  • 配置了10个定时任务,但是走的job类是同 一,在启动项目的时候,如何确保这同时跑的10个定时任务,不重复读取一条数据或者重复读取相同的几条数据,防止修改一条数据的时候,别的定时任务已经执行完成,这就造成了...
  • 使用spring的@Scheduler注解可以非常方便的启动一个定时任务,但是当服务部署在服务器上做负载均衡的时候,可能会出现重复执行的情况。现在我们通过代码指定job只在某一台机器执行。首先在系统中配置一执行job...
  • 一、单机指定时间执行定时任务实现方式 Timer运行机制 ScheduledThreadPoolExecutor的运行机制 原理图 Leader/Follower模式正在上传…重新上传取消 Timer和ScheduledThreadPoolExucutor区别 Timer是基于...
  • @Scheduled定时任务重复执行两次

    千次阅读 2020-04-15 10:16:25
    java @Scheduled定时任务重复执行两次问题描述解决方法 问题描述 java Maven项目,使用@Scheduled(cron = “0 0/59 * * * ?”) 对定时方法进行了标注,结果该方法在每59分钟执行完后的若干秒中再次执行了一次。同时...
  • 关于springboot定时任务配置线程池之后任务重复执行问题,踩坑 最近遇到一问题。项目中有一job 的定时任务mytask。里面有七个定时任务。有3秒执行一次的,有五秒的,有十秒的,有两三分钟的,也有把小时的。...
  • 内容包括实现示例及不同服务器存在时间差时的处理方式。...当服务器进行水平扩展,部署多个节点之后,分散在多个节点的定时任务将被重复执行。 对于执行非幂等操作的定时任务,可以基于Redis的分布式锁来避免重复执行
  • 其中有一定时任务的问题,由于是主从两台机器,程序需要用nginx做反向代理,两台服务器都需要部署相同的程序,这样的话,每台服务器都有可能执行定时任务,导致定时任务重复执行,出现错乱的脏数据。研究了好久...
  • 定时任务在本地可以执行,在服务器上无法执行...首先,本地可以执行说明,定时任务代码层面没有问题,,放到服务器上晚12小时才执行,首先考虑的是时区问题,查看服务器时区没有问题,说明服务器时间是正常的,查看no
  • springmvc定时任务重复执行2次的解决

    千次阅读 2018-05-27 23:07:49
    也许是老生常谈的问题了。 我在网上找了好多,虽然讲的是定时任务的那个类被实例化了两次,要注意配置分离。于是我有了下面的操作: ...但是任然重复执行两次定时任务。最后的解决方案是在web.xml中分开加载...
  • 第一种做法不是很好 虽然可以避免数据重复处理的问题,但是存在单点故障的问题...执行定时任务。(如果服务是部署在docker里 就会不太好使了 因为主机名是会变化的) 官方也提供了一些解决方案 在agent.js中继承a...
  • springboot 定时任务部署至linux服务器上后会执行两次问题(以下分为两种原因) springboot定时任务在本地运行时,正常执行且只执行一次,但是在maven打包成war包,部署至linux服务器上之后,定时任务奇怪的执行了...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,509
精华内容 15,003
关键字:

多个服务器重复执行定时任务