Redisson 读写锁和分布式锁的项目实践
问题 1:在修改分组时,有短链接正在访问会出现什么问题?怎么解决
假设:现有线程 A 正在修改短链 a 的分组 gid1 为 gid2(还未修改成功)
同时有一个线程 B 获取了短链 a 分组 gid1,要进行统计 pv,uv,uip 操作时.发现 gid1 已经不存在了,就会发生并发问题
解决方案:采用读写锁
什么是读写锁
Redisson 读写锁是一种基于 Redis 实现特殊的机制,用于在分布式系统中协调对共享资源的访问,其继承了 Java 中的
ReentrantReadWriteLock
的思想.特别适用于读多写少的场景.其核心是:允许多个线程同时读取共享资源,但写操作必须占用资源.从而保证线程安全的同时提高并发性能
十分适合短链更新时:当某个线程需要更新资源时→需要获取写锁.此时所有的读操作和其他写线程会被阻塞,保证数据的一致性
核心原理
读锁(共享锁):
共享性:允许多个线程同时持有读锁
互斥性:只要存在读锁,该线程就不能获取写锁
写锁(排他锁):
独占性:同一时刻只能占有一个线程持有写锁
互斥性:当一个线程获取了写锁,其他线程就无法同时获取写锁和读锁.写锁占用线程修改共享资源,确保了在修改时没有其他线程访问
基本代码结构如下:
分布式锁 Redisson
为防止缓存击穿→大量并发请求同时查询一个失效的缓存,导致数据库压力骤增
通过 Redisson 的
RLock
(分布式锁)确保同一时刻只有一个线程执行数据库查询操作
双重检查锁→重建缓存
双重检查流程
第一次检查-无锁:未在代码中显式体现:通常在实际业务中,外层会先尝试从缓存读取数据。如果缓存命中,直接返回数据,无需加锁。此处代码直接处理未命中场景,可能外层已进行第一次检查。假设场景:当缓存未命中时,请求进入加锁逻辑。
加锁后第二次检查-关键:在获取分布式锁后,再次检查缓存-
stringRedisTemplate.opsForValue().get
。目的:确保在等待锁的过程中,其他线程可能已经更新了缓存,避免重复查询数据库。
缓存穿透和缓存击穿解决方法
流程图如下:

布隆过滤器+缓存空值+redisson 锁
缓存空值的操作对布隆过滤器误判操作进行保护→防止穿透
redisson 锁操作对大量空值同时过期操作进行保护→防止击穿
文章转载自:ihav2carryon
评论