Redis的四大难点,缓存穿透、缓存击穿、缓存雪崩、分布式锁

1、缓存的概念

2、缓存雪崩

3、缓存穿透

4、缓存击穿

5、分布式锁


1、缓存的概念

广义的缓存
就是在第一次加载某些可能会复用数据的时候,在加载数据的同时,将数据放到一个指定的地点做保 存。再下次加载的时候,从这个指定地点去取数据。这里加缓存是有一个前提的,就是从这个地方取数据,比从数 据源取数据要快的多。
狭义的缓存(java)
1. 虚拟机缓存(ehcache JBoss Cache
2. 分布式缓存(redis memcache
3. 数据库缓存

2、缓存雪崩

缓存雪崩产生的原因
缓存雪崩通俗简单的理解就是:由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间所有原本应该访问缓存的请求都去查询数据库了,而对数据库 CPU 和内存造成巨大压力, 严重的会造成数据库宕机,造成系统的崩溃。
解决方案
1 :在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。
比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。虽然能够在一定的程度上缓解了数据库的压力但是与此同时又降低了系统的吞吐量。
注意 : 加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间 key 是锁着的,这是过来 1000 个请求 999 个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法。

2: 分析用户的行为,不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

3、缓存穿透

缓存穿透
是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找 不到,每次都要去数据库再查询一遍,然后返回空。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中 率问题。
解决方案
1. 如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴。
2. 把空结果,也给缓存起来,这样下次同样的请求就可以直接返回空了,既可以避免当查询的值为空时引起的缓存穿透。同时也可以单独设置个缓存区域存储空值,对要查询的 key 进行预先校验,然后再放行给后面的正常缓存处理逻辑。
注意:再给对应的 ip 存放真值的时候,需要先清除对应的之前的空缓存。

4、缓存击穿

对于一些设置了过期时间的 key ,如果这些 key 可能会在某些时间点被超高并发地访问,是一种非常 热点 的数据。这个时候,需要考虑一个问题:缓存被 击穿 的问题,这个和缓存雪崩的区别在于这里针对某一 key 缓存,前者则是 很多 key
热点key
某个 key 访问非常频繁,当 key 失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃。
解决办法
(1)使用锁,单机用 synchronized,lock 等,分布式用分布式锁。
(2)缓存过期时间不设置,而是设置在 key 对应的 value 里。如果检测到存的时间超过过期时间则异步更新缓存。

5、分布式锁

使用分布式锁要满足的几个条件:
1. 系统是一个分布式系统
2. 共享资源(各个系统访问同一个资源,资源的载体可能是传统关系型数据库或者 NoSQL
3. 同步访问(即有很多个进程同时访问同一个共享资源)
分布式锁
当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
1线程锁
主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码 段。线程锁只在同一 JVM 中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如 synchronized 是共享对象头,显示锁 Lock 是共享某个变量(
state )。
进程锁
为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程 的资源,因此无法通过 synchronized 等线程锁实现进程锁。
应用的场景
线程间并发问题和进程间并发问题都是可以通过分布式锁解决的,但是强烈不建议这样做!因为采用分布式锁解决这些小问题是非常消耗资源的!分布式锁应该用来解决分布式情况下的多进程并发问题才是最合适的。
举例
如果是单机情况下(单 JVM ),线程之间共享内存,只要使用线程锁就可以解决并发问题。
如果是分布式情况下(多 JVM ),线程 A 和线程 B 很可能不是在同一 JVM 中,这样线程锁就无法起到作用了,这时候就要用到分布式锁来解决。
使用 redis setNX 命令实现分布式锁
Redis 为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对 Redis 的连接并不存在竞争关系。 redis SETNX 命令可以方便的实现分布式锁。

猜你喜欢

转载自blog.csdn.net/qinluyu111/article/details/123698394