分布式锁之Redis篇

本文介绍了如何使用Redis实现分布式锁,包括加锁、过期时间设置和自动续期策略。此外,还详细讲解了Redisson分布式锁,包括可重入锁、读写锁、信号量和闭锁的使用,以及如何解决Redis锁查询问题。
摘要由CSDN通过智能技术生成

分布式锁之Redis


1. 前言

在Java并发编程中,我们通常使用到synchronizedLock这两个线程锁,Java中的锁,只能保证对同一个JVM中的线程有效。而在分布式集群环境,这个时候我们就需要使用到分布式锁。

实现分布式锁的方案

  1. 基于数据库实现分布式锁
  2. 基于缓存Redis实现分布式锁
  3. 基于Zookeeper的临时序列化节点实现分布式锁

2. Redis实现分布式锁

场景:在高并发的情况下,可能有大量请求来到数据库查询三级分类数据,而这种数据不会经常改变,可以引入缓存来存储第一次从数据库查询出来的数据,其他线程就可以去缓存中获取数据,来减少数据库的查询压力。

在集群的环境下,就可以使用分布式锁来控制去查询数据库的次数。

2.1 阶段一

在这里插入图片描述

    private  Map<String, List<Catelog2Vo>>  getCatalogJsonDBWithRedisLock() {
   
        // 去Redis中抢占位置
        Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", "1111");
        if (lock){
   
            // 抢到锁了 执行业务
            Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
            // 删除锁
            stringRedisTemplate.delete("lock");
            return dataFromDb;
        }else {
   
            // 自旋获取锁
            // 休眠100ms
            try {
   
                Thread.sleep(100);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
            return getCatalogJsonDBWithRedisLock();
        }
    }

得到锁以后,我们应该再去缓存中确定一次,如果没有才需要继续查询,从数据库查到数据以后,应该先把数据放入缓存中,再将数据返回。

  private Map<String, List<Catelog2Vo>> getDataFromDb() {
   
        // 得到锁以后,我们应该再去缓存中确定一次,如果没有才需要继续查询
        String catalogJson = stringRedisTemplate.opsForValue().get("catalogJson");
        if (!StringUtils.isEmpty(catalogJson)) {
   
            // 反序列化 转换为指定对象
            Map<String, List<Catelog2Vo>> result = JSON.parseObject(catalogJson, new 
            TypeReference<Map<String, List<Catelog2Vo>>>() {
   });
            return result;
        }
        System.out.println("查询数据库了......");
        // 查询所有分类数据在进行刷选
        List<CategoryEntity> categoryEntityList = baseMapper.selectList(null);
        // 查询一级分类
        List<CategoryEntity> leave1Categorys = getParent_cid(categoryEntityList, 0L);
        Map<String, List<Catelog2Vo>> listMap = leave1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), l1 -> {
   
        
            List<CategoryEntity> categoryL2List = getParent_cid(categoryEntityList, l1.getCatId());
            List<Catelog2Vo> catelog2Vos = null;
            if (categoryL2List != null) {
   
                catelog2Vos = categoryL2List.stream().map(l2 -> {
   
                    Catelog2Vo catelog2Vo = new Catelog2Vo(l2.getParentCid().toString(), null, l2.getCatId().toString(), l2.getName());
 
                    List<CategoryEntity> categoryL3List = getParent_cid(categoryEntityList, 
                                                                        l2.getCatId());
                    if (categoryL3List != null) {
   
                        List<Catelog2Vo.Catelog3Vo
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值