ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

分布式锁

2021-11-28 21:34:36  阅读:165  来源: 互联网

标签:redisson return park Redisson door public 分布式


1、加锁解决缓存击穿问题

1)本地锁: 使用同步代码块

public Map<String,List<Catalog2Vo>> getCatalogJsonFromDb() {
    //只要是同一把锁,就能锁住使用这个锁的所有线程
    //synchronized (this)  SpringBoot项目中所有组件在容器中都是单例的
    synchronized (this){
        //得到锁之后,需要去缓存中查询一次,如果没有,才继续查询数据库
        String result = redisTemplate.opsForValue().get("xxxx");
        if(StringUtils.isNotBlank(result )){
            return result;
        }
       //查询数据库,返回结果
       return getResuleFromDb();
    }
}

 

2)本地锁在分部式情况下出现的问题

每个本地锁只能锁住当前项目请求过来的10000个请求,多个项目的情况下,依旧会查询多次数据库

0

 

2、分布式锁的原理和使用

1)分布式锁出现的问题

死锁:setnx占好了位,业务代码异常或者程序在页面过程中宕机,没有执行删除逻辑,这就造成了死锁问题

解决:设置锁的自动过期,即使没有删除也会自动删除

 

3、Redisson的使用

整合Redisson作为分布式锁

1)引入依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.12.0</version>
</dependency>

 

2)配置

/**
 * @author houChen
 * @date 2021/10/31 9:37
 * @Description: Redisson的配置类
 */
@Configuration
public class MyRedissonConfig {
    /**
     *  所有对Redisson的使用都是通过RedissonClient对象
     */
    @Bean
    public RedissonClient redisson(){
        //1、创建配置
        Config config = new Config();
        config.useSingleServer().setAddress("121.40.182.123:6379");
        //2、创建RedissonClient
        return Redisson.create(config);
    }
}

 

3)测试

mylock.lock() 是阻塞式的,若某个请求没有获取到锁,则一直阻塞在该处。

@ResponseBody
@GetMapping("/hello")
public String hello(){
    //1、获取一把锁,只要锁名一样,就是同一把锁
    RLock mylock = redisson.getLock("mylock");
    //2、加锁
    mylock.lock();
    try{
        System.out.println("加锁成功,正在执行业务......"+ Thread.currentThread().getId());
        Thread.sleep(30000);
    }catch (Exception e){

    }finally {
        System.out.println("释放锁" + Thread.currentThread().getId());
        mylock.unlock();
    }
    return  "hello";
}

0

 

4)一些问题

当加锁后,程序闪退了,没有执行解锁代码,会不会造成死锁?

不会,因为当锁没有续期时,超过30秒回自动删除

1)锁的自动续期,如果业务超长,运行期间会自动给锁续上30秒。不用担心业务时间长,锁自动过期被删除

2)加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30秒后自动删除

mylock.lock(10, TimeUnit.SECONDS); 10秒后会自动解锁,但是不会续期,所以解锁的时间一定要大于业务执行的时间

1、如果我们传递了锁的超时时间,就发送指令给redis脚本,进行占锁,默认超时就是我们指定的时间

2、如果我们未指定锁的超时时间,就使用30*1000 【LockWatchOutTimeOut看门狗的默认时间】

只要占领成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10秒自动 续期

 

4、Redisson 读写锁

 

5、Redisson 闭锁

/**
 *  闭锁演示
 *
 *  5个班的人都走完了,才能锁大门
 */
@GetMapping("/lockDoor")
@ResponseBody
public String lockDoor() throws InterruptedException {
    RCountDownLatch door = redisson.getCountDownLatch("door");
    door.trySetCount(5);
    door.await(); //等待闭锁都完成
    return  "放假了";
}

@GetMapping
@ResponseBody
public String gogogo(@PathVariable("id") Long id){
    RCountDownLatch door = redisson.getCountDownLatch("door");
    door.countDown(); // 计数减1
    return id + "班的人走了";
}

0

 

6、Redisson 分布式信号量

/**
 * 分布式信号量测试
 * 车位停车   3车位
   当车位为0时,停车操作将会阻塞
 *
 * 可以用来做分布式限流
 */
@GetMapping("/park")
@ResponseBody
public String park() throws InterruptedException {
    RSemaphore park = redisson.getSemaphore("park");
    park.acquire();  //获取一个信号(占一个车位)
    return "ok";
}

@GetMapping("/go")
@ResponseBody
public String go() throws InterruptedException {
    RSemaphore park = redisson.getSemaphore("park");
    park.release();  //获取一个信号
    return "go 车开走啦....";
}

标签:redisson,return,park,Redisson,door,public,分布式
来源: https://www.cnblogs.com/houchen/p/15616649.html

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

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

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

ICode9版权所有