Redis从入门到精通(九、Redis使用中常见的问题)

2019-06-16  本文已影响0人  QuoVadis_k

Redis 在为程序带来性能提高的同时,也会有缺点,这些都是我们需要考虑的,比如: Redis与持久化数据库的数据一致性问题,缓存雪崩问题,缓存穿透问题,缓存击穿问题等,本文就上述几个问题,简单的阐述一下解决思路。

缓存穿透

如果我们的查询数据路线是: App -> Redis -> MySQL(或其它RDBS),正常情况下,我们查询数据都会在Redis命中,Redis未命中的情况下才去查询MySQL,然后将查询到的数据写入到Redis中,这样下次就直接可以在Redis层命中。

那么如果查询一条MySQL中压根儿根本就不存在的数据,也就是缓存和数据库都查询不到这条数据,但是请求每次都会打到数据库上面去。这种查询不存在数据的现象我们称为缓存穿透

解决方案(缓存穿透)

第一种方案比较简单易懂,查询不到数据,将Null值存到Redis中,并设置上过期时间,这样下次请求再过来,可以直接返回Null,不会再落到MySQL。

但是,针对于一些恶意攻击,攻击带过来的大量key 是不存在的,那么我们采用第一种方案就会缓存大量不存在key的数据。此时我们采用第一种方案就不合适了,我们完全可以先对使用第二种方案进行过滤掉这些key。关于 BloomFilter , 下文列出简单的描述,我们可以在应用层加一层 BloomFilter 来解决这个问题。

Bloomfilter: 布隆过滤器, 它是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率。即Bloom Filter报告某一元素存在于某集合中,但是实际上该元素并不在集合中。但是如果某个元素确实没有在该集合中,那么Bloom Filter 是不会报告该元素存在于集合中的,所以不会漏报。

针对key非常多、请求重复率比较低的数据,我们就没有必要进行缓存,使用第二种方案直接过滤掉。而对于空数据的key有限的,重复率比较高的,我们则可以采用第一种方式进行缓存。


缓存击穿

在高并发的系统中,大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去。这种现象我们称为缓存击穿

解决方案(缓存击穿)

第一种方案使用具有局限性,需要结合业务考虑是否可以不设置过期时间。
第二种方案,由于使用了互斥锁,所以性能肯定会差很多。


缓存雪崩

缓存雪崩的情况是说,当某一时刻发生大规模的缓存失效的情况 或者 缓存服务宕机了,会有大量的请求进来直接打到DB上面。称为 缓存雪崩

解决方案(缓存雪崩)

Redis 的集群是必须要做的,保证Redis服务的高可用,在应用种也要处理Redis宕机的情况,比如做出限流或者降级的措施,采用本地缓存等,让查询请求尽可能少的落到数据库上。Redis的集群方案怎么来做,可以参考我之前的文章。

针对一些热点数据集中失效的问题,可以采用设置不同的过期时间的方案,在一个基础时间上左右浮动,例如: 30min + 3s,30min -5s .


Redis与持久层数据一致性的问题

App -> Redis -> MySQL ,App查询请求先请求Redis,如果查询不到再请求MySQL,查询到数据后将数据写入MySQL。

在这样的一条查询链路种,由于数据的写入可能会造成Redis与MySQL数据的不一致。

比如: 数据写入时,先写入Redis再写入MySQL,可能在写入MySQL时出现异常,导致数据不一致,反过来也是如此。

解决方案(数据不一致)


总结

在实际使用过程种还是要结合具体的业务,来从上述几个方面来考虑程序的健壮性。最终的目的都是保护数据库。

上一篇下一篇

猜你喜欢

热点阅读