前言
前面几篇博客对Redis的讲解不可谓不详细,从单节点到主从,到sentinel哨兵,到Redis Cluster都一一搭配使用给大家做了讲解,但在使用Redis的过程中我们还是要注意一些比较常见的问题,比如穿透、击穿等等,所以本篇博客主要就是给大家做这方面的扫盲,希望对一些初学者可以有些帮助。
导读
在开始讲解之前,Redis相关的博客地址我先给大家做一个推荐:
Java开发 - Redis初体验
Java开发 - 让你少走弯路的Redis的主从复制
Java开发 - 让你少走弯路的Redis主从实现单节点哨兵模式
Java开发 - 让你少走弯路的Redis集群搭建
Java开发 - 深入理解Redis哨兵机制原理
Java开发 - 深入理解Redis Cluster的工作原理
以上几篇,希望能给需要的朋友一些帮助,下面,我们来讲解Redis使用中常见的一些问题。
缓存穿透
出现的场景
当我们查询一个数据的时候,数据在Redis缓存中不存在,就会查询到数据库中,如果数据库中也没有这条数据,那就相当于没有查到任何东西。这看似很正常,可是当数以万计的查询同时进行时,缓存都没有数据,这些查询将直接访问数据库,这就带给数据库极大的压力,缓存也就失去了存在的意义。这种情况,我们称之为缓存穿透,即穿透了缓存,直达数据库,这个前提条件是大量的穿透。
解决办法
对于缓存穿透,解决的办法博主说两种:
第一种:这是业内比较常见的处理办法:保存空值。即数据库也查不到数据时,在Redis保存一个空值,并返回给请求方,下次再查询的时候就能查到空值直接返回。同时设置一个过期时间,万一这个值后面又存进去了。不过,一般在存进去的时候会把值同步到Redis,所以也不用担心数据库实际有数据,Redis仍为空的情况。
第二种:利用布隆过滤器,布隆过滤器都听过吧?没听过不要紧,最下面会说。首先将数据同步到布隆过滤器,接着再查询时判断数据不在布隆过滤器(布隆过滤器只能判断不存在),如果不存在就直接返回空数据,否则就去缓存中查找数据。看下图:
缓存击穿
出现的场景
当一个访问频繁的热点数据在Redis中突然失效时,大量的请求就会绕过Redis,直接访问数据库,相当于凿穿了Redis,这个情况其实和缓存穿透很类似,只是击穿是在缓存突然失效的时候无法找到缓存,直接访问了数据库。这种现象我们叫做缓存击穿。
解决办法
缓存击穿的解决办法也不少,主要分为以下几种:
第一种:设置热点数据为永不过期,这样就不会出现击穿的现象;
第二种:利用分布式锁,在热点数据失效后,保证只有一个线程去访问数据库,访问数据库后就把查询到的数据缓存到Redis,这样,后面的数据就不会出现击穿的情况。如下图:
缓存雪崩
出现的场景
缓存雪崩指在某一段时间内,缓存大量过期,或者Redis服务直接宕机,导致大量的缓存无法命中,越积越多,就像雪花一样,最后引起大范围的崩塌,就好像雪崩了一样。其本质也是直接访问了数据库,只是出现的情况和上面的击穿和穿透不一样。但严重的不是缓存的集中过期,而是Redis服务的宕机,我想,大家应该都能想明白这其中的道理。
解决办法
解决的办法嘛其实也很简单:
第一种:针对集中过期的数据,设置基数+随机数的过期时间,这样就不会出现缓存集中过期的场景,或者设置锁,限制绕过缓存访问数据库的线程数量;
第二种:针对Redis服务宕机的情况,使用Redis主从、集群都是很好的解决方案,但也要根据实际情况和成本出发去考虑问题。
布隆过滤器
关于布隆过滤器的使用,博主在先前的博客中有详细介绍过,传送门:Java开发 - 布隆过滤器初体验
所以,此处不再赘述,你只需要知道的是:布隆过滤器只能判断不存在某个数据,而不能判断存在。
结语
伴随着轻快的下课铃声,额...不是,伴随着博主留下一个个链接之后,本篇博客就要跟大家说再见了,学习使我快乐,不知道这篇博客能不能带给你快乐呢?咱们今天就讲到这里,下一篇讲什么,博主要好好想想,有可能是Kafka,也有可能是RabbitMQ,我再纠结纠结。