ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

分布式锁之Redis实现

2022-02-26 11:30:19  阅读:106  来源: 互联网

标签:初始化 String 实现 Redis value param key 分布式


在Java中,关于锁我想大家都很熟悉。在并发编程中,我们通过锁,来避免由于竞争而造成的数据不一致问题。通常,我们以synchronized 、Lock来使用它。
但是Java中的锁,只能保证在同一个JVM进程内中执行。如果在分布式集群环境下呢?

一、分布式锁

分布式锁,是一种思想,它的实现方式有很多。比如,我们将沙滩当做分布式锁的组件,那么它看起来应该是这样的:

加锁

在沙滩上踩一脚,留下自己的脚印,就对应了加锁操作。其他进程或者线程,看到沙滩上已经有脚印,证明锁已被别人持有,则等待。

解锁

把脚印从沙滩上抹去,就是解锁的过程。

锁超时

为了避免死锁,我们可以设置一阵风,在单位时间后刮起,将脚印自动抹去。

分布式锁的实现有很多,比如基于数据库、memcached、Redis、系统文件、zookeeper等。它们的核心的理念跟上面的过程大致相同。

二、redis

我们先来看如何通过单节点Redis实现一个简单的分布式锁。

背景:在当应用服务启动的时候,需要进行数据初始化,如果部署至多容器节点的时候,节点在启动的时候会概率触发多次初始化逻辑;所以,需要通过锁来限制初始化操作之后执行一次。

RedisLock工具类

@Component
public class RedisLockUtil {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static long DEFALT_TIMEOUT = 1L;

    /**
     * @description 上锁
     * @param  key 锁标识
     * @param  value 线程标识
     * @param  timeout 超时时间,秒
     * @updateTime 2021/9/14
     */
    public boolean lock(String key, String value, long timeout) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * @description 上锁(排队等待)
     * @param  key 锁标识
     * @param  value 线程标识
     * @updateTime 2021/9/14
     */
    public boolean lock(String key, String value) {
        while (true) {
            // 执行set命令
            Boolean absent = stringRedisTemplate.opsForValue().setIfAbsent(key, value, DEFALT_TIMEOUT, TimeUnit.MINUTES);
            // 是否成功获取锁
            if (absent) {
                return true;
            }
        }
    }

    /**
     * @description 解锁
     * @param  key 锁标识
     * @param  value 线程标识
     * @updateTime 2021/9/14
     */
    public boolean unlock(String key, String value) {
        String currentValue = stringRedisTemplate.opsForValue().get(key);
        if(StrUtil.isNotBlank(currentValue) && currentValue.equals(value) ){
            return stringRedisTemplate.opsForValue().getOperations().delete(key);
        }
        return false;
    }
}

代码示例

 @Override
 public void onApplicationEvent(ApplicationStartedEvent event) {
     //上锁
     long time = System.currentTimeMillis();
     boolean result = redisLock.lock(INIT_KEY, String.valueOf(time), TIMEOUT);
     if (log.isInfoEnabled()) {
         log.info("获得锁的结果:" + result + ";获得锁的时间戳:" + String.valueOf(time));
     }
     if(!result){
         throw new IllegalArgumentException("已存在初始化!!!");
     }
     try {
         ...
         初始化逻辑代码
         ...
     } catch (Exception e) {
         log.error("初始化失败!", e);
     } finally {
         //释放锁
         redisLock.unlock(INIT_KEY, String.valueOf(time));
         if (log.isInfoEnabled()) {
             log.info("释放锁的时间戳" + String.valueOf(time));
         }
     }
 }

标签:初始化,String,实现,Redis,value,param,key,分布式
来源: https://blog.csdn.net/qq_38566465/article/details/123146750

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有