缓存:分布式锁-Redission,看门狗机制


 分布式锁可不是之前的一个锁,而是各种锁的总称。读写锁,闭锁,信号量等等、。

导入redisson的原生核心依赖  , redisson和之前的jedis  letters一样, 都是客户端:

        
            org.redisson
            redisson
            3.16.8
        

之前用的redistemplate  操作 list hash string等都是当前进程做的,但是redisson 则是把这些对象放在redis上,由redis来操作。

 

配置:

package com.atguigu.gulimall.product.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyRedisConfig {


    /**
     * 所有对 redis 的操作,都是通过 RedissonClient对象
     *
     * @return
     */
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() {
        //创建配置
        Config config = new Config();
        // 这里是说使用单节点模式,而不是集群的redis模式。
        config.useSingleServer().setAddress("redis://" + "192.168.155.3:6379");

        //根据config对象创建 RedissonClient 实例
        return Redisson.create(config);
    }
}

 

===========================================

@Controller
public class IndexController {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedissonClient redissonClient;


    @ResponseBody
    @RequestMapping("/index/hello")
    public String hello() {
        RLock lock = redissonClient.getLock("my-lock");
        // 加锁,这个是阻塞式等待,没加到锁就一直在这里等着。
        lock.lock();
        try {
            System.out.println("加锁成功,执行业务,当前锁的线程ID:" + Thread.currentThread().getId());
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("释放锁,当前锁的线程ID:" + Thread.currentThread().getId());
            lock.unlock();//解锁
        }
        return "hello";
    }

redis中的key也包含了线程ID  95 :

 

 30s后业务执行完释放锁打印:

===================================

假设,解锁代码没有执行,执行业务的时候程序闪断了,服务宕机了,解锁代码没执行,redisson会出现死锁吗?

答案是 不会死锁。

 在redis中可以发现,这个锁有个TTL 的值。

redisson的强大之处:

  • 锁的自动续期,如果业务时间很长,他会自动续期,不用担心锁会被自动删掉,加锁的时候不指定,默认加30s的时间,续期也是30s
  • 加锁的业务运行完成,就不会续期了,即使不手动解锁,也会自动在30s 的时间出自动解锁。

=================================================

 加锁的时候,如果指定时间,不会自动续期。

* 如果我们传递了锁的超时时间,就会给redis发送超时脚本来进行占锁  默认超时时间就是我们指定的
* 如果我们未指定,就使用 30 * 1000 [LockWatchdogTimeout] 看门狗默认时间
* 只要占锁成功 就会启动一个定时任务 任务就是重新给锁设置过期时间 这个时间还是 [LockWatchdogTimeout] 的时间 1/3 看门狗的时间续期一次 续成满时间。

定时任务,每隔十秒就续期,续成满时间30s

 业务如果30s都没做完,那就是业务的问题了。实战用的多的还是指定过期时间。