一个应用里有利用定时任务统计数据并插入数据库的需求,在单机情况下,不用考虑任何重复执行问题
但在集群下部署多个应用,定时任务就会出现重复执行的问题,为了避免资源浪费和脏数据的问题出现,借助redis分布式锁解决
redis分布式锁原理如下:
基于Redis实现的分布式锁其实很简单,底层就是使用redis的setnx指令来实现的加锁,我们来看看官方对setnx的定义:
SETNX key value
将 key 的值设为 value ,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。
返回值:
设置成功,返回 1 。
设置失败,返回 0 。
以上内容来自于:http://redisdoc.com/string/setnx.html
既然setnx这么强大,那么我们是不是可以高枕无忧直接使用了? 当然了,我们还要考虑一些极端场景。
比如如果一台机器在运行状态中突然宕机没有设置锁的过期时间无法自动释放锁,那么另一台应用会一直认为有机器占用着分布式锁执行任务,此时实际是没有执行的,而导致死锁问题。
死锁问题解决方法:
在这里我们给分布式锁设置一个过期时间,能够在开始执行任务后自动释放分布式锁
原理图如下:
代码如下:
package com.xjb.redis.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {