zoukankan      html  css  js  c++  java
  • Redis解决分布式定时任务重复执行问题

    问题描述: 有一个定时任务是每周一给客户发送邮件的功能, 后台部署了2台服务器,所以客户 收到了2封重复邮件。

    解决思路:

    分布式锁一般有三种实现方式:1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁。

    这里使用一台Redis服务器来解决上面的问题。

    代码部分比较简单:

    加锁 :主要是给多个定时任务给redis加锁(key),如果存在key,则加锁失败,如果不存在,则尝试去加锁,返回加锁结果。 

    解锁: 设置一下过期时间为20秒(可根据任务执行长短调整),过期后自动释放掉。这里就不去代码里面释放锁了。

    private static final String LOCK_SUCCESS = "OK";
        private static final String SET_IF_NOT_EXIST = "NX";
        private static final String SET_WITH_EXPIRE_TIME = "PX";
        private static final Long RELEASE_SUCCESS = 1L;
    
     /**
         * 尝试获取分布式锁
         *
         * @param jedis      Redis客户端
         * @param lockKey    锁
         * @param requestId  请求标识
         * @param expireTime 超期时间
         * @return 是否获取成功
         */
        public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        //这里的jedis自己去实现一下 String result
    = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; }

    测试 (同时启动4个服务,每个服务上面启动三个同样的定时任务)

     //每分钟执行一次
        static final String cron1 = "0 */1 * * * ?";
    
        @Scheduled(cron = cron1)
        public void testRedis1() {
            String msg = doRedis();
            System.out.println("msg1 :" + msg);
        }
        
        @Scheduled(cron = cron1)
        public void testRedis2() {
            String msg = doRedis();
            System.out.println("msg 2:" + msg);
        }
        
        @Scheduled(cron = cron1)
        public void testRedis3() {
            String msg = doRedis();
            System.out.println("msg 3:" + msg);
        }
    
    
        //执行redis
        private String doRedis() {
            boolean flag = RedisTool.tryGetDistributedLock("sendMail_20200101", UUID.randomUUID().toString(), 1000 * 20);
            String msg = null;
            if (flag) {
                msg = "你获取到锁了可以去操作业务!";
            } else {
                msg = "别人获取到锁了,你就不用操作了!!!!";
            }
            return msg;
        }

    测试结果

    观察到每一分钟, 3X4个定时任务中,只有一个能获取到锁,可以去操作业务,其他同样的定时任务失败了 。

    总结:后面会具体总结一下分布式锁相关的内容

  • 相关阅读:
    oracle报ORA-00911:invalid character
    转: ㊣华哥日记㊣ 12.14-如何去了解更多的东西
    App竞品技术分析 (3)减小安装包的体积(转)
    ***apache做301重定向的方法
    .htaccess是什么?.htaccess几个简单应用
    一个网页如何决定是当前页打开还是新窗口打开?
    响应式web设计之CSS3 Media Queries
    ***CSS魔法堂:选择器及其优先级
    Bootstrap3 为何无法显示Glyphicons 图标
    MySQL中tinytext、text、mediumtext和longtext详解
  • 原文地址:https://www.cnblogs.com/coloz/p/12697536.html
Copyright © 2011-2022 走看看