文章目
什么是缓存击穿、缓存穿透、缓存雪崩?
缓存雪崩
指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。
- 解决其实很简单:
- 让其到期时间均匀即可。
- 或者设置热点数据永远不过期,有更新操作就更新缓存就好了(比如运维更新了首页商品,那你刷下缓存就完事了,不要设置过期时间),电商首页的数据也可以用这个操作,保险。
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,我们数据库的 id 都是1开始自增上去的,如发起为id值为 -1 的数据或 id 为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大,严重会击垮数据库。
如何解决?
- 如果是非法请求,我们在 API 入口,对参数进行校验,过滤非法值。
- 如果查询数据库为空,我们可以
给缓存设置个空值,或者默认值
。但是如果有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效) - 使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。(利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return)
缓存击穿
指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db
如何解决?
- 使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载 db 数据库数据和设置缓存。否则就去重试获取缓存。
如果redis里的数据为空的话,就请求数据库,就在请求数据库这一步给它上锁,那么这时候就只有一个线程,能获取到这个锁
,所以也就只有一个线程能操作数据库,那么这个时候对数据库的压力就非常小,当查询到这个数据之后,就把缓存重新写到redis中去,其他没有抢到锁的线程,让它先睡几毫秒,然后再重新去redis里面去查询
。分布式锁实现方式:redis 和 zookeeper - “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
Redis 过期策略和内存淘汰策略
怎么实现Redis的高可用?其实就是多点部署
通过三种模式实现:
- 主从模式
- 哨兵模式
- 集群模式
主从模式
主节点负责读写,从节点只负责读操作。主从节点会进行数据同步,机制就是主从同步机制。
主从同步机制有两种:全量复制,增量复制。一般当 slave 第一次启动连接 master,或者认为是第一次连接,就采用全量复制,全量复制流程如下:
这里的 AOF 写命令,就可以等价于 epoll 中的 overlist 。如果后续再发生更新,那就是增量
更新操作。
- replicationFeedSlaves 函数:把用户执行的命令发送到所有的slave节点,让slave节点执行。
- 判断用户执行的命令是否有数据更新
- 判断 slave节点是否为空
哨兵模式
主从模式中,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址。显然,多数业务场景都不能接受这种故障处理方式。Redis 从 2.8开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。
哨兵模式,由一个或多个Sentinel实例组成的Sentinel系统,它可以监视所有的Redis主节点和从节点,并在被监视的主节点进入下线状态时,自动将下线主服务器属下的某个从节点升级为新的主节点。但是呢,一个哨兵进程对Redis节点进行监控,就可能会出现问题(单点问题),因此,可以使用多个哨兵来进行监控Redis节点,并且各个哨兵之间还会进行监控。
哨兵模式的作用
- 发送命令,等待Redis服务器(包括主服务器和从服务器)返回监控其运行状态;
- 哨兵监测到主节点宕机,会自动将从节点切换成主节点,然后通过发布订阅模式通知其他的从节点,修改配置文件,让它们切换主机。
- 哨兵之间还会相互监控,从而达到高可用。
集群模式
哨兵模式基于主从模式,实现读写分离,它还可以自动切换,系统可用性更高。但是它每个节点存储的数据是一样的,浪费内存,并且不好在线扩容。因此,Cluster集群应运而生,它在 Redis3.0 加入的,实现了 Redis 的分布式存储。对数据进行分片,也就是说每台Redis节点上存储不同的内容,来解决在线扩容的问题。并且,它也提供复制和故障转移的功能。
节点之间使用 Gossip 协议通信,交换的信息内容包括节点出现故障、新节点加入、主从节点变更信息、slot信息等等
。常用的Gossip消息分为4种,分别是:ping、pong、meet、fail。
使用:Hash Slot 插槽算法。
Redis 集群的数据分布之分片
MySQL与Redis 如何保证双写一致性
- 缓存延时双删
- 删除缓存重试机制
- 读取biglog异步删除缓存
Redis 的 Hash 冲突怎么办
- 链式解决
- 渐进式 rehash
Redis 与 Memcached 的区别
- Redis 的键数据类型更多
- 速度快
- 可以持久化数据
Gossip 协议详解
Gossip协议是基于六度分隔理论(Six Degrees of Separation)哲学的体现,简单的来说,一个人通过6个中间人可以认识世界任何人。
传播过程
- 种子节点
周期性的散播消息
【假定把周期限定为 1 秒】。 被感染节点随机选择 N 个邻接节点
散播消息【假定fan-out(扇出)设置为6,每次最多往6个节点散播】。- 节点只接收消息不反馈结果。
每次散播消息都选择尚未发送过的节点进行散播
。- 收到消息的节点不再往发送节点散播:A -> B,那么B进行散播的时候,不再发给 A。
消息类型 (Anti-Entropy(反熵传播)和Rumor-Mongering(谣言传播))
反熵传播:传播全量数据
谣言传播:传播增量数据
通信方式
- 推送模式、拉取模式、Push/Pull。
- Push: 节点 A 将数据 (key,value,version) 及对应的版本号推送给 B 节点,B 节点更新 A 中比自己新的数据
- Pull:A 仅将数据 key, version 推送给 B,B 将本地比 A 新的数据(Key, value, version)推送给 A,A 更新本地
- Push/Pull:与 Pull 类似,只是多了一步,A 再将本地比 B 新的数据推送给 B,B 则更新本地
轻松理解CAP理论
CAP 即:
- Consistency(一致性):强调的是
数据正确且最新
。 - Availability(可用性):强调的是
系统返回不出错,但是返回的结果不一定是最新的
- Partition tolerance(分区容忍性):会一直运行,不管我的内部出现何种数据同步问题,强调的是不挂掉。