Redis原理之缓存

发布于:2025-07-23 ⋅ 阅读:(18) ⋅ 点赞:(0)

上篇文章:

Redis原理之集群https://blog.csdn.net/sniper_fandc/article/details/149141342?fromshare=blogdetail&sharetype=blogdetail&sharerId=149141342&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link

目录

1 Redis作为MySQL缓存

2 缓存更新策略

2.1 定期生成

2.2 实时生成

3 缓存预热(Cache preheating)

4 缓存穿透(Cache penetration)

5 缓存雪崩(Cache avalanche)

6 缓存击穿(Cache breakdown)


        由于Redis基于内存,比基于磁盘的数据库查询效率(读请求)快的多,因此Redis常用于作为MySQL数据库的缓存。而内存成本高,因此通常只往内存存储少量的热点数据。

1 Redis作为MySQL缓存

        关系型数据库比如MySQL查询效率一般比较慢,有如下原因:

        1.基于磁盘,磁盘IO速度慢。

        2.如果查询不能命中索引,就需要遍历表,增加磁盘IO次数。

        3.关系型数据库会对执行的SQL进行一些解析、校验、优化等工作,进一步增加耗时。

        4.如果是复杂查询,比如涉及到多表联查,笛卡尔积的时间复杂度O(M*N),效率就更低了。

        因此在高并发的环境下,只使用MySQL很容易宕机。为了优化系统性能,提高系统并发量,有两种方式:1.增加MySQL集群,但是成本很高。2.使用Redis作为缓存。方式2就是业界常用的方式:

        注意:这种方式只是加快了读请求的查询效率,而写请求缓存并不能加快效率,还是需要写到MySQL中。

2 缓存更新策略

2.1 定期生成

        定期对访问的数据进行频次统计(通常基于日志分析),选取频次最高的那部分数据作为热点数据存入缓存中。

        优点:实现简单,过程可控,方便排查问题。

        缺点:数据实时性不够。

2.2 实时生成

        实时生成就是当Redis查询未命中时,服务器就会去MySQL数据库查询,并将查询的数据写入到Redis缓存中。

        优点:数据具有实时性。

        缺点:缓存容易很快就写满。

        正因为这样的缺点,就需要合适的内存淘汰策略来更新:

        FIFO:先进先出,缓存时间最久的数据先淘汰。

        LRU:淘汰最久未使用,每个数据设置最近访问时间,优先淘汰最近访问时间最久的数据。

        LFU:淘汰最少使用的,每个数据设置最近一段时间访问次数,优先淘汰访问次数最少的数据。

        Random:随机淘汰。

        而Redis内部也用到了这些策略思想,并按照key是否设置过期时间对这些策略进行了细化:

        volatile-lru:针对设置了过期时间的key(只要设置了过期时间,即使还没过期,如果内存满了又有新数据写入就会淘汰),按照LRU思想淘汰。

        allkeys-lru:针对所有的key,按照LRU思想淘汰。

        volatile-lfu:针对设置了过期时间的key,按照LFU思想淘汰。

        allkeys-lfu:针对所有的key,按照LFU思想淘汰。

        volatile-random:针对设置了过期时间的key,随机淘汰。

        allkeys-random:针对所有的key,随机淘汰。

        volatile-ttl:按照ttl(生存时间,也就是设置了过期时间的key),越早过期越优先淘汰(局限于设置了过期时间key的FIFO)。

        noeviction:默认策略,内存满了再写入就报错。

3 缓存预热(Cache preheating)

        当Redis刚启动或大批key同时过期,此时Redis中没有数据,查询就无法命中缓存,从而去查MySQL,给数据库带来大量查询压力。

        解决办法:通过缓存预热,即提前给缓存中存入一些数据(不一定完全是热点数据),来帮助MySQL减轻大量请求的压力。可以采用定期生成的策略来离线为Redis提前存入一些热点数据,随着时间推移,缓存中的数据最终变为真正的热点数据。

4 缓存穿透(Cache penetration)

        查询的key在Redis和MySQL数据库中都不存在,这样的key不会被实时缓存到Redis中,后续如果这类key频繁访问,依然会对MySQL造成较大压力。

        问题产生原因:1.业务未进行合理的参数校验,导致非法的key被查询。2.数据库部分数据被误删。3.黑客攻击。

        解决办法:1.业务设计更规范,进行必要的参数校验。2.针对不存在的key,可以在MySQL也未命中后,把该key存入Redis中,value设为非法值(比如””,避免频繁访问数据库。3.使用布隆过滤器(hash+bitmap,能够用较少的空间和时间判断某个数据是否存在)存入所有的key,查询Redis和数据库前先查布隆过滤器是否存在该key。

5 缓存雪崩(Cache avalanche)

        短时间内Redis上的大量的key失效,从而导致大量的查询未命中缓存,给数据库带来较大压力。

        问题产生原因:1.Redis节点宕机。2.在短时间内设置了大量过期时间相同的key。

        解决办法:1.部署Redis集群保证高可用性,并进行安全监控。2.不设置过期时间或设置过期时间时附加随机种子,保证不会同时过期。

6 缓存击穿(Cache breakdown)

        缓存穿透的特殊情况,缓存穿透是针对普遍的key(包括热点和非热点)突然同时失效的问题,而缓存击穿是指热点key突然过期,导致大量查询未命中去查数据库。

        解决办法:1.统计出热点key,并设置永不过期。2.必要时进行服务降级(关掉不必要的服务),比如使用分布式锁限制数据库的访问请求。

下篇文章:


网站公告

今日签到

点亮在社区的每一天
去签到