【redis】整合redisson作为分布式锁等功能框架

本文介绍了如何在Spring Boot中使用Redisson实现可重入锁,看门狗机制,以及在并发场景下保证数据一致性,包括读写锁、信号量和缓存一致性策略。通过实例展示了如何配置RedissonClient并应用在iyatmall一致性解决方案中。
摘要由CSDN通过智能技术生成

1.引入依赖

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

2.配置reids

redis官方文档:https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
写一个配置类,注入RedissonClient

@Configuration
public class MyRedissonConfig {

    /**
     * 所有对Redisson 的使用都是通过RedissonClient对象
     * @return
     * @throws IOException
     */
    @Bean(destroyMethod="shutdown")
    RedissonClient redisson() throws IOException {
        Config config = new Config();
        //集群模式
//        config.useClusterServers()
//                .addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");
        //单节点模式
        config.useSingleServer().setAddress("redis://192.168.56.01:6379");//虚拟机redis地址
        return Redisson.create(config);
    }
}

3.可重入锁

可重入锁简单理解: 例如方法A执行需要①锁,方法B执行也需要①锁,如果是可重入锁,方法A调用方法B,可以直接进行调用,执行完AB方法后释放锁。如果是不可重入锁,执行方法B需要等待方法A执行完释放锁,而方法A调用方法B,没有执行完,不会释放锁,形成死锁。redisson的锁是可重入锁。
redisson锁,测试程序:

    @Autowired
    RedissonClient redisson;
    
    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        //1.获取一把锁,只要锁的名字一样就是同一把锁
        RLock lock = redisson.getLock("my-lock");
        //2.加锁
        //lock.lock();//阻塞式等待,默认加的锁都是30s的时间。
        // 2.1.锁的自动续期,如果业务超长,运行期间自动给锁续上新的30s,不同担心业务时间长,锁自动过期
        // 2.2 加锁的业务只要运行完成就不会给当前锁续期,即使不手动解锁,锁默认再30s以后会自行删除
        //最佳实践
        lock.lock(30,TimeUnit.SECONDS); //省掉整个续期操作,手动解锁
        try{
            System.out.println("加锁成功执行业务..." + Thread.currentThread().getId());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //3.解锁, 加锁加锁代码未执行,
            System.out.println("释放锁..." + Thread.currentThread().getId());
            lock.unlock();
        }
        return "hello";
    }

看门狗机制

lock.lock(); //带自动续期
lock.lock(10,TimeUnit.SECONDS);//不带自动续期

1.如果我们未指定超时时间,就会使用30*1000【LockWatchdogTimeout看门狗的默认事件】,只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10s都会自动续期一次【看门狗时间 / 3】

读写锁

并发读,互不影响,并发读写,先写完才读
保证一定能读到最新数据,修改期间,写锁是一个排他锁(互斥锁)。读锁是一个共享锁
读 + 读 : 相当于无锁
读 + 写 :有读锁,写需要等待
写 + 读: 等待写锁释放
写 + 写:阻塞方式
有写的存在,都必须等待

信号量

可以用作分布式限流
获取信号量,获取一个值,信号量-1,可以阻塞式,也可以直接try,获取不到返回false
释放一个车位,信号量+1

闭锁

放假锁门
5个班全部走完可以锁大门
等待其他全部完成【计数减完】,才能执行自己要干的事

数据缓存一致性

双写模式

数据更新,写数据库,然后写缓存
读到的数据和最新的数据有延迟:最终一致性
在这里插入图片描述
由于卡顿等原因,导致写缓存2在最前,写缓存1在后面,就出现了不一致

脏数据问题:
这是暂时性的脏数据问题,在数据稳定后,缓存过期后,又能得到正确的数据

失效模式

数据更新,删除缓存
在这里插入图片描述
这也有脏数据问题
延迟双删可以降低脏数据几率

解决方案

  1. 如果是用户维度数据(订单数据、用户数据),这种并发几率非常小,不用考虑这个问题,缓存数据加上过期时间,每隔一段时间触发读的主动更新即可
  2. 如果是菜单,商品介绍,等基础数据,也可以使用canal订阅binlog的方式
  3. 通过加锁保证并发读写,写写的时候排好队,读读无所谓。适合使用读写锁

总结:实时性、一致性高的不用缓存

iyatmall系统的一致性解决方案:

  1. 缓存的所有数据都有过期时间,数据过期下一次查询触发主动更新
  2. 读写数据的时候,加上分布式的读写锁

最终实现: 整合SpringCache简化开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甲 烷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值