当前位置: 首页 > news >正文

谷粒商城:Redisson

目录

Redisson

整合Redisson

 RLock

RReadWriteLock

RSemaphore

RCountDownLatch

优化三级分类缓存

缓存一致性问题

双写模式

失效模式

脏数据解决


Redisson

提供redis分布式锁(Distributed locks with Redis)的java客户端

整合Redisson

引入

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

程序化配置

@Configuration
public class RedissonConfig {
    @Value("${spring.redis.host}"+":"+"${spring.redis.port}")
    private String singleAddress;
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() throws IOException {
        Config config = new Config();
        /*
          SingleServer() 单节点模式
          redis:// redis 连接协议
         */
        config.useSingleServer()
                .setAddress("redis://"+singleAddress);

        return Redisson.create(config);
    }
}

 RLock

可重入锁(Reentrant Lock)它允许同一个线程多次获取同一把锁而不会产生死锁。

RLock lock = redisson.getLock("myLock");

// 尝试获取锁,最多等待10秒,锁有效期30秒
boolean res = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (res) {
    try {
        // 业务代码
    } finally {
        lock.unlock();
    }
}
  1. 可重入性:同一线程可多次获取同一把锁

  2. 锁续期:内置看门狗机制自动续期

  3. 公平锁:支持公平锁和非公平锁

  4. 锁释放:确保只有锁持有者能释放锁


RReadWriteLock

读写锁,它允许多个读操作同时进行,但写操作是排他的。

RReadWriteLock rwLock = redisson.getReadWriteLock("myReadWriteLock");
RLock readLock = rwLock.readLock();  // 获取读锁
RLock writeLock = rwLock.writeLock(); // 获取写锁
writeLock.lock();  // 先获取写锁
try {
    // 写操作...
    
    // 保持写锁的同时获取读锁(锁降级)
    readLock.lock();
    try {
        // 读操作...
    } finally {
        // 注意:这里不能释放写锁
    }
    
    // 可以继续持有写锁做其他操作
} finally {
    writeLock.unlock();  // 最后释放写锁
    // 此时仍持有读锁
}
  1. 读写分离

    • 多个线程可以同时持有读锁

    • 写锁是排他的,有写锁时不能有读锁或其他写锁

  2. 可重入性

    • 读锁和写锁都支持可重入

    • 同一线程可以多次获取同一把读锁或写锁

  3. 锁降级

    • 支持将写锁降级为读锁

    • 但不支持读锁升级为写锁(会死锁)

  4. 公平性选择

    • 支持公平和非公平两种模式


RSemaphore

 信号量,它允许多个线程/进程在分布式环境中协调对共享资源的访问

// 获取信号量实例(初始许可数为5)
RSemaphore semaphore = redisson.getSemaphore("mySemaphore");
semaphore.trySetPermits(5);  // 初始化许可数量

// 获取1个许可(阻塞直到可用)
semaphore.acquire();

try {
    // 访问受限资源
    accessLimitedResource();
} finally {
    // 释放许可
    semaphore.release();
}

  1. 资源限制:控制同时访问特定资源的线程/进程数量

  2. 分布式支持:跨JVM、跨服务器的协调能力

  3. 公平性选择:支持公平和非公平两种模式

  4. 可重入:支持同一线程多次获取许可

  5. 超时机制:支持尝试获取许可的超时设置

典型应用场景

  1. 限流控制:限制系统并发请求数

  2. 资源池管理:如数据库连接池控制

  3. 任务调度:限制同时执行的任务数量

  4. API访问限制:控制第三方API调用频率


RCountDownLatch

闭锁,它允许一个或多个线程等待其他线程完成操作后再继续执行。

RCountDownLatch latch = redisson.getCountDownLatch("myLatch");

// 初始化计数器为5
latch.trySetCount(5);

// 减少计数器(每个工作线程完成后调用)
latch.countDown();

//获取当前计数
long remaining = latch.getCount();

// 等待计数器归零(阻塞)
latch.await();

// 带超时的等待
boolean reached = latch.await(10, TimeUnit.SECONDS);

  1. 一次性使用:计数器归零后不能重置(与JDK的CountDownLatch一致)

  2. 等待/通知机制:线程可以等待计数器归零

  3. 可视化监控:可通过Redis直接查看当前计数状态

典型应用场景

  1. 分布式任务同步:等待多个分布式任务完成

  2. 系统初始化:等待所有服务初始化完成

  3. 批量处理:等待所有子任务处理完成

  4. 测试协调:分布式测试中的线程协调


优化三级分类缓存

    @Override
    public Map<String, List<Level2CategoryVo>> getLevel2AndLevel3Category() {
        //1.先从缓存中获取 catalogJson
        ValueOperations<String,String> valueOperations = redisTemplate.opsForValue();
        String catalogJson = valueOperations.get("catalogJson");
        Map<String, List<Level2CategoryVo>> res = null;
        if(StringUtils.isEmpty(catalogJson)){
            //缓存中无对应数据,查询数据库
            res = getCatalogJsonFromDBWithRedissonLock();
        }else{
            res = JSON.parseObject(catalogJson,new TypeReference<Map<String, List<Level2CategoryVo>> >(){});
        }
        return res;
    }

    /**
     * 获取 Redisson 分布式锁,查询数据库
     * @return
     */
    private Map<String, List<Level2CategoryVo>> getCatalogJsonFromDBWithRedissonLock(){
        Map<String, List<Level2CategoryVo>> res = null;
        RLock lock = redisson.getLock("CatalogJson-Lock");
        lock.lock();
        //成功获取到锁
        try {
            res = getCatalogJsonFromDB();
        }finally {
            lock.unlock();
        }
        return res;
    }

缓存一致性问题

双写模式

修改数据库,并修改缓存。

    失效模式

    修改数据库后,删除缓存,下一次查询时缓存数据。

    脏数据解决

    俩种模式都会产生暂时的脏数据,解决方案:

    1. 读写锁
    2. 过期时间,保证最终一致性
    3. 一致性要求高的数据,不存入缓存,应直接查询数据库

    http://www.dtcms.com/a/106340.html

    相关文章:

  1. TiDB 可观测性解读(二)丨算子执行信息性能诊断案例分享
  2. Linux网络编程socket服务器端模拟实现
  3. JSP 指令
  4. Python数据类型-dict
  5. 第八届 蓝桥杯 嵌入式 省赛
  6. 【ESP32-IDF 笔记】02-LED PWM 配置
  7. 运维面试题(ORACLE数据库)--20250401
  8. Cesium学习(未完继续)
  9. 题解:AT_arc050_c [ARC050C] LCM 111
  10. Android的安全问题 - 在 Android 源码的 system/sepolicy 目录中,区分 public、private 和 vendor的目的
  11. Kotlin 作用域函数:apply、let、run、with、also
  12. 掩码图像建模 (MIM) 中的对数似然与交叉熵
  13. 品铂科技与宇都通讯UWB技术核心区别对比(2025年)
  14. C++:位图和布隆过滤器
  15. spring-ai-alibaba第三章ollama集成Tool
  16. 【redis】缓存 更新策略(定期、实时生存),缓存预热、穿透、雪崩、击穿详解
  17. ERP管理系统:Java+Vue,含源码及文档,一体化管理资源,优化流程,强化企业运营效率
  18. React.memo()和 useMemo()的用法是什么,有哪些区别
  19. CSS3学习教程,从入门到精通,CSS3 媒体查询实现响应式布局语法指南(21)
  20. Unity插件SuperScrollView详解(基础篇)
  21. Redis安全与配置问题——AOF文件损坏问题及解决方案
  22. 机器人--ros2--IMU
  23. 用jQuery和Canvas打造2D版“我的世界+超级玛丽“游戏
  24. 知名界面控件DevExpress v24.2.6全新可用|发布重要更改
  25. 安卓一些接口使用
  26. dbgpt7.0 docker部署
  27. Unity工具—默认取消Image和RowImage的Raycast Target
  28. Vue3入门
  29. 智谱大模型(ChatGLM3)PyCharm的调试指南
  30. AI大模型从0到1记录学习 day11