Redis缓存

“梦会枯,就算夜有尽头。” 


         Redis的主要用途有三个方面:1.存储数据(作为数据库使用) 2.缓存(Redis最常用的场景) 3.消息队列。在计算机种,速度快的设备可以 作为速度慢的设备的缓存。最常见的就是内存作为硬盘的“缓存”。硬盘可以作为网络的缓存,浏览器通过http、https服务获取到的数据(html、css、js、视频、图片)等等,一些少有改变的、体积大的如图标、视频等,在第一次访问网站时,就会被浏览器存储在本地的硬盘上。

        ——前言

使⽤ Redis 作为缓存       

        Redis通常是用来作为Myql数据库的缓存。但诸如Mysql、sqlserver等关系型数据库虽然功能强大,但也有很明显的缺陷:

🎇 数据库把数据存储在硬盘上, 硬盘的 IO 速度并不快. 尤其是随机访问。

🎇 如果查询不能命中索引, 就需要进⾏表的遍历, 这就会⼤⼤增加硬盘 IO 次数。

🎇 关系型数据库对于 SQL 的执⾏会做⼀系列的解析, 校验, 优化⼯作。

🎇 如果是⼀些复杂查询, ⽐如联合查询, 需要进⾏笛卡尔积操作, 效率更是降低很多。

……

        因此,虽然数据库能够支持比较高的并发量,但对于数据库的压力会很大,很容易就会使数据库服务器宕机。

为什么并发量⾼了就会宕机?

        服务器每次处理⼀个请求, 都是需要消耗⼀定的硬件资源的. 所谓的硬件资源包括不限于 CPU, 内存, 硬盘, ⽹络带宽等等。

        ⼀个服务器的硬件资源本⾝是有限的。当后续的请求没有资源可⽤,⾃然就⽆法正确处理。更严重的还会导致服务器程序的代码出现崩溃。

        所以针对如何让数据库能够承担更⼤的并发量的问题,提供了两种不同的解决方法:
💰 开源: 引⼊更多的机器, 部署更多的数据库实例, 构成数据库集群. (主从复制, 分库分表等...)

💰 节流: 引⼊缓存, 存储热点数据,从⽽降低客户端请求直接访问数据库的数量。

        Redis 就是⼀个⽤来作为数据库缓存的常⻅⽅案,就像⼀个 "护盾" ⼀样, 把 MySQL 给罩住了。


Redis缓存更新策略

        现在的问题在于,Redis应该存储哪些数据?前面所说Redis需要存储热点数据,那么哪些是热点数据呢? 有些数据可能在一定时间内是热点的,有很高的访问需求,但一段时间过后就变成了普通的数据了,这又该如何处理呢?

(1) 定期生成        

        所谓定期生成,就是把访问的数据以日志的形式,一一记录下来。对于访问的数据频次进⾏统计. 挑选出访问频次最⾼的前 N% 的数据.

优点:实现过程简单,过程更加可控。能及时排查问题

缺点:实时性不够,对于突发的热点内容无法得到及时更新               

(2) 实时生成

        先给缓存设定容量上限(可以通过 Redis 配置⽂件的 maxmemory 参数设定)。

        接下来把⽤⼾每次查询:

如果在 Redis 查到了, 就直接返回。
如果 Redis 中不存在, 就从数据库查, 把查到的结果同时也写⼊ Redis。
        这样不停地向Redis写入数据,逐渐达到Redis设置的内存上限,就会触发“内存淘汰策略”。

Redis内存淘汰策略:

        Redis内存淘汰策略分为四种:
📍 FIFO (First In First Out) 先进先出

        把缓存中存在时间最久的 (也就是先来的数据) 淘汰掉。

📍 LRU (Least Recently Used) 淘汰最久未使⽤的

        记录每个 key 的最近访问时间. 把最近访问时间最⽼的 key 淘汰掉。

📍 LFU (Least Frequently Used) 淘汰访问次数最少的

        记录每个 key 最近⼀段时间的访问次数. 把访问次数最少的淘汰掉。

📍 Random 随机淘汰

        从所有的 key 中抽取幸运⼉被随机淘汰掉。

        当然 Redis 也提供了内置的淘汰策略, 也可以供我们直接使⽤。

# 当内存不⾜以容纳新写⼊数据时,从设置了过期时间的key中使⽤LRU
volatile-lru -> Evict using approximated LRU among the keys with an expire set.

# 当内存不⾜以容纳新写⼊数据时,从所有key中使⽤LRU(最近最少使⽤)算法进⾏淘汰.
allkeys-lru -> Evict any key using approximated LRU.

# 当内存不⾜以容纳新写⼊数据时,在过期的key中,使⽤LFU算法进⾏删除key.
volatile-lfu -> Evict using approximated LFU among the keys with an expire set.

# 当内存不⾜以容纳新写⼊数据时,从所有key中使⽤LFU算法进⾏淘汰
allkeys-lfu -> Evict any key using approximated LFU.

# 当内存不⾜以容纳新写⼊数据时,从设置了过期时间的key中,随机淘汰数据.
volatile-random -> Remove a random key among the ones with an expire set.

# 当内存不⾜以容纳新写⼊数据时,从所有key中随机淘汰数据.
allkeys-random -> Remove a random key, any key.

# 在设置了过期时间的key中,根据过期时间进⾏淘汰,越早过期的优先被淘汰.
volatile-ttl -> Remove the key with the nearest expire time (minor TTL)

# 默认策略,当内存不⾜以容纳新写⼊数据时,新写⼊操作会报错
noeviction -> Don't evict anything, just return an error on write operations.

Redis预热\穿透\雪崩\击穿

关于预热:   

        使⽤ Redis 作为 MySQL 的缓存的时候, 当 Redis 刚刚启动, 或者 Redis ⼤批 key 失效之后, 此时由于 Redis ⾃⾝相当于是空着的, 没啥缓存数据, 那么 MySQL 就可能直接被访问到, 从⽽造成较⼤的压⼒。

        因此就需要提前把热点数据准备好, 直接写⼊到 Redis 中. 使 Redis 可以尽快为 MySQL 撑起保护伞。

缓存预热(Cache preheating) :        

        所谓的缓存预热,就是将“定期生成” 和 “实时生成”相结合,先通过离线的方式,先把热点数据导入到redis缓存之中。此时导入的热点数据能够替Mysql分担很大一部分压力,随着时间推移,新的热点数据会替代掉旧的数据。

什么是缓存穿透(Cache penetration):

        访问的 key 在 Redis 和 数据库中都不存在. 此时这样的 key 不会被放到缓存上, 后续如果仍然在访问该 key, 依然会访问到数据库.

造成原因:

🏷  业务设计不合理。比如一些非法的Key因为确实校验,一直未命中。
🏷  开发/运维误操作. 不⼩⼼把部分数据从数据库上误删了。
🏷 ⿊客恶意攻击。

解决方案:        

🏷 针对要查询的参数进⾏严格的合法性校验。比如,如果一个Key值在Myql、redis上都不存在,仍然写入Redis中,并设置一个非法Value值。

🏷 使用布隆过滤器,判断在与不在。每次查询Redis、Mysql时,先判定这个Key是否存在布隆过滤器之中。

什么是缓存雪崩(Cache avalanche)

        短时间内⼤量的 key 在缓存上失效,导致数据库压⼒骤增,甚⾄直接宕机。

造成原因:

🏷 Redis 挂了        

🏷 Redis 上的⼤量的 key 同时过期。当Redis作为缓存时,考虑到时效性,就会给有些Key设置过期时间。       

解决方案:

🏷部署⾼可⽤的 Redis 集群, 并且完善监控报警体系。  

🏷不给 key 设置过期时间 或者 设置过期时间的时候添加随机时间因⼦  

什么是缓存击穿 (Cache breakdown)

        看到这个词,你是否觉得与之前缓存穿透十分相似呢?但其实这两者还是有些差异的。“breakdown”翻译成“瘫痪、崩溃”似乎要好一丢丢。

        相当于缓存雪崩的特殊情况. 针对热点 key , 突然过期了, 导致⼤量的请求直接访问到数据库上, 甚⾄引起数据库宕机。

        所以两者的区别也可以是,穿透是说明缓存压根没起到作用,击穿表示缓存是能起作用,但是对于一些热点Key无法查询。

解决方案:

🏷 基于统计的⽅式发现热点 key, 并设置永不过期。

🏷  进⾏必要的服务降级,例如访问数据库的时候使⽤分布式锁,限制同时请求数据库的并发数。

小结:

① 缓存的基本概念

② Redis缓存策略,内存淘汰策略

③ 缓存预热\穿透\雪崩\击穿


祝你好运,向阳而生 ~


 

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值