Loading... # 缓存的击穿、穿透、雪崩以及redis分布式锁原理 ## 缓存击穿 某个key超时或被LRU清除之后,有大量请求并发访问该key,导致大量请求抵达数据库。 ### 解决 思路是阻止访问到达数据库,利用redis是单进程单实例的特点: 1. 如果某个请求get key没有请求到数据 2. setnx插入一条数据,设置锁 3. 只有成功插入获得锁的人可以访问数据库,其他人睡眠一会再去redis中取 这样同时只有一个访问到达数据库,取回数据并刷新redis缓存,其它人都就可以从缓存中获取数据了。 ### 问题 1. 死锁,获得锁的进程挂了,导致锁无法释放,数据没有成功取回,其它进程也获取不到锁。 这个问题可以通过设置过期时间解决,setnx的key在几毫秒后过期,就算当前进程挂了,锁过期了,其它进程一样可以获得锁。 2. 获得锁的进程没挂,但是由于某种原因导致请求时间比较长,然后锁超时了(设置了过期时间)。 通过多线程解决,一个线程去数据库取数据,一个线程负责监控数据是否取回来,并定期刷新锁的过期时间。 通过上面两种方式,在service中自己实现分布式协调,很麻烦。 ## 缓存穿透 从业务层接受的查询是系统中根本不存在的数据,数据库中都没有,缓存自然不会有。 ### 解决 - 布隆过滤器 ### 问题 - 布隆过滤器只能添加不能删除,数据库中数据删了,布隆会认为数据还在,依然会访问数据库。 可以通过更换过滤器比如布谷鸟,或者在缓存中为删除的key创建一个null值来解决。 ## 缓存雪崩 大量的key同时失效,间接造成大量访问到达数据库 ### 解决 存在两种情况 1. 时点性无关 这种情况可以通过随机过期时间解决,避免大量key同时过期。 2. 零点过期 到零点新的一天,旧的数据要全部过期,引入新的数据,必须雪崩!不能通过随机过期时间来解决。强依赖击穿方案,通过锁来解决。业务层增加判断,零点延时,每个请求随机延时几毫秒,避免大量并发情况出现。 无论击穿,穿透还是雪崩,前提都是高并发,key过期了没有并发访问,自然不会击穿,穿透和雪崩也是。问题的核心是避免大量请求到达数据库。 ## redis实现分布式锁原理 就是击穿方案中写的:setnx,并设置过期时间,通过守护线程,来延长过期时间,能成功setnx就是得到了锁。 Last modification:December 18th, 2019 at 07:09 pm © 允许规范转载