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

Redisson读写锁和分布式锁的项目实践

解决方案:采用读写锁

什么是读写锁

Redisson读写锁是一种基于Redis实现特殊的机制,用于在分布式系统中协调对共享资源的访问,其继承了Java中的ReentrantReadWriteLock的思想.特别适用于读多写少的场景.其核心是:允许多个线程同时读取共享资源,但写操作必须占用资源.从而保证线程安全的同时提高并发性能

  • 十分适合短链更新时:当某个线程需要更新资源时→需要获取写锁.此时所有的读操作和其他写线程会被阻塞,保证数据的一致性

核心原理

读锁(共享锁):

  • 共享性:允许多个线程同时持有读锁
  • 互斥性:只要存在读锁,该线程就不能获取写锁

写锁(排他锁):

  • 独占性:同一时刻只能占有一个线程持有写锁
  • 互斥性:当一个线程获取了写锁,其他线程就无法同时获取写锁和读锁.写锁占用线程修改共享资源,确保了在修改时没有其他线程访问

基本代码结构如下:

RReadWriteLock configLock = redisson.getReadWriteLock("configLock");
// 读配置
configLock.readLock().lock();
try {return loadConfigFromCache();
} finally {configLock.readLock().unlock();
}
// 写配置
configLock.writeLock().lock();
try {updateConfigInDB();refreshCache();
} finally {configLock.writeLock().unlock();
}

分布式锁Redisson

  • 为防止缓存击穿→大量并发请求同时查询一个失效的缓存,导致数据库压力骤增
  • 通过 Redisson 的 RLock(分布式锁)确保同一时刻只有一个线程执行数据库查询操作

双重检查锁→重建缓存

双重检查流程

  1. 第一次检查-无锁
    • 未在代码中显式体现:通常在实际业务中,外层会先尝试从缓存读取数据。如果缓存命中,直接返回数据,无需加锁。此处代码直接处理未命中场景,可能外层已进行第一次检查。
    • 假设场景:当缓存未命中时,请求进入加锁逻辑。
  2. 加锁后第二次检查-关键
    • 在获取分布式锁后,再次检查缓存-stringRedisTemplate.opsForValue().get
    • 目的:确保在等待锁的过程中,其他线程可能已经更新了缓存,避免重复查询数据库。

缓存穿透和缓存击穿解决方法

  • 流程图如下:

  • 布隆过滤器+缓存空值+redisson锁
  • 缓存空值的操作对布隆过滤器误判操作进行保护→防止穿透
  • redisson锁操作对大量空值同时过期操作进行保护→防止击穿
RLock lock = redissonClient.getLock(String.format(LOCK_SHORT_LINK_GOTO_KEY, fullShortUrl));// 加锁lock.lock();try {// 再次查询缓存String originalUrl = stringRedisTemplate.opsForValue().get(String.format(GOTO_SHORT_LINK_KEY, fullShortUrl));// 如果缓存中不存在,则查询数据库if (StrUtil.isBlank(originalUrl)) {//查询goto表LambdaQueryWrapper<ShortLinkGotoDO> linkGotoQueryWrapperqueryWrapper = Wrappers.lambdaQuery(ShortLinkGotoDO.class).eq(ShortLinkGotoDO::getFullShortUrl, fullShortUrl);ShortLinkGotoDO shortLinkGotoDO = shortLinkGotoMapper.selectOne(linkGotoQueryWrapperqueryWrapper);if (shortLinkGotoDO == null) {//进行风控解决缓存穿透问题->设为空值stringRedisTemplate.opsForValue().set(String.format(SHORT_LINK_IS_NULL_KEY, fullShortUrl), "-", 30, TimeUnit.MINUTES);resp.sendRedirect("/page/notfound");return;}//查询短链接表获取originUrlLambdaQueryWrapper<ShortLinkDO> queryWrapper = Wrappers.lambdaQuery(ShortLinkDO.class).eq(ShortLinkDO::getGid, shortLinkGotoDO.getGid()).eq(ShortLinkDO::getFullShortUrl, fullShortUrl).eq(ShortLinkDO::getEnableStatus, 0);ShortLinkDO shortLinkDO = baseMapper.selectOne(queryWrapper);//数据库中不存在或者短链接已经过期则跳转404页面if (shortLinkDO == null || (shortLinkDO.getValidDate() != null && shortLinkDO.getValidDate().before(new Date()))) {//短链接已经过期stringRedisTemplate.opsForValue().set(String.format(SHORT_LINK_IS_NULL_KEY, fullShortUrl), "-", 30, TimeUnit.MINUTES);resp.sendRedirect("/page/notfound");return;}// 缓存原始链接stringRedisTemplate.opsForValue().set(String.format(GOTO_SHORT_LINK_KEY, fullShortUrl), shortLinkDO.getOriginUrl());//预热缓存stringRedisTemplate.opsForValue().set(String.format(GOTO_SHORT_LINK_KEY, fullShortUrl),shortLinkDO.getOriginUrl(),LinkUtil.getShortLintCacheValidDate(shortLinkDO.getValidDate()),TimeUnit.MILLISECONDS);// 访问统计shortLinkAccessStats(fullShortUrl, shortLinkDO.getGid(), req, resp);// 跳转resp.sendRedirect(shortLinkDO.getOriginUrl());}} finally {lock. Unlock();

 

http://www.lryc.cn/news/2384610.html

相关文章:

  • Https流式输出一次输出一大段,一卡一卡的-解决方案
  • SkyWalking高频采集泄漏线程导致CPU满载排查思路
  • 【HarmonyOS 5】Map Kit 地图服务之应用内地图加载
  • ld: cpu type/subtype in slice (arm64e.old) does not match fat header (arm64e)
  • sentinel核心原理-高频问题
  • 通过vue-pdf和print-js实现PDF和图片在线预览
  • RxJS 核心操作符详细用法示例
  • 视频监控管理平台EasyCVR结合AI分析技术构建高空抛物智能监控系统,筑牢社区安全防护网
  • 2.2.1 05年T1复习
  • Python-11(集合)
  • 钉钉开发之AI消息和卡片交互开发文档收集
  • JMeter 教程:正则表达式提取器提取 JSON 字段数据
  • Opixs: Fluxim推出的全新显示仿真模拟软件
  • [数据集]无人机视角检测分割数据集合集
  • 佰力博与您探讨PVDF薄膜极化特性及其影响因素
  • C++ std::find() 函数全解析
  • 自动获取ip地址安全吗?如何自动获取ip地址
  • STM32:深度解析RS-485总线与SP3485芯片
  • 亚马逊搜索代理: 终极指南
  • QGraphicsView界面的坑(fitInView()函数没反应)
  • 【Python正则表达式终极指南】从零到工程级实战
  • leetcode 算法每日一题 #1
  • 用matlab提取abaqus odb文件中的节点信息
  • Spring Bean 注册到容器的方式
  • 1537. 【中山市第十一届信息学邀请赛决赛】未命名 (noname)
  • 数据库三范式详解与应用建议
  • 信息学奥赛一本通 1539:简单题 | 洛谷 P5057 [CQOI2006] 简单题
  • C++笔记-封装红黑树实现set和map
  • deepseek模拟美团高级java开发工程师面试题
  • 留给王小川的时间不多了