面试问题浓缩总结 面试问题浓缩总结
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • MySQL

  • Redis

    • 数据类型
    • 持久化
    • 原理
    • 常见问题
      • 缓存雪崩
      • 缓存穿透
      • 缓存击穿
      • 双写一致性
        • 先更新数据库,再更新缓存
        • 先删缓存,再更新数据库
      • 脑裂
      • 事务
        • 执行的三个阶段
        • 特点
      • 热key
    • 分布式锁,过期策略,淘汰规则
    • 集群和限流
    • 面试题
  • MongoDB

  • 数据库
  • Redis
小游
2021-03-20

常见问题

# 缓存雪崩

Redis中大批量key在同一时间同时失效导致所有请求都打到了MySQL。而MySQL扛不住导致大面积崩塌

解决方案

  1. 缓存数据的过期时间加上个随机值,防止同一时间大量数据过期现象发生
  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中
  3. 设置热点数据永远不过期
  4. 使用快速失败的熔断策略,减少 DB 瞬间压力;
  5. 使用主从模式和集群模式来尽量保证缓存服务的高可用。

# 缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,比如ID默认>0,黑客一直 请求ID= -12的数据那么就会导致数据库压力过大,严重会击垮数据库。

解决方案

  1. 后端接口层增加 用户鉴权校验,参数做校验等
  2. 单个IP每秒访问次数超过阈值直接拉黑IP
  3. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null 失效时间可以为15秒防止恶意攻击
  4. 用Redis提供的 Bloom Filter 特性

# 缓存击穿

大并发集中对这一个热点key进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库

解决方案:设置热点数据永远不过期或者加上互斥锁

业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

缓存穿透,缓存击穿,缓存雪崩解决方案分析_zeb_perfect的专栏-CSDN博客 (opens new window)

redis缓存穿透,缓存击穿,缓存雪崩原因+解决方案 - 知乎 (zhihu.com) (opens new window)

# 双写一致性

缓存跟数据库均更新数据,如何保证数据一致性?

# 先更新数据库,再更新缓存

  1. 安全问题:线程A更新数据库->线程B更新数据库->线程B更新缓存->线程A更新缓存。导致脏读。
  2. 业务场景:读多写少场景,频繁更新数据库而缓存根本没用。更何况如果缓存是叠加计算后结果更浪费性能。

# 先删缓存,再更新数据库

同样会造成数据不一致的问题:

A 请求写来更新缓存->B 发现缓存不在去数据查询旧值后写入缓存->A 将数据写入数据库,此时缓存跟数据库不一致。

FaceBook的Cache Aside Pattern (opens new window)方案

  1. 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  2. 命中:应用程序从cache中取数据,取到后返回。
  3. 更新:先把数据存到数据库中,成功后,再让缓存失效。

# 脑裂

脑裂是指因为网络原因,导致master节点、slave节点 和 sentinel集群处于不用的网络分区,此时因为sentinel集群无法感知到master的存在,所以将slave节点提升为master节点 此时存在两个不同的master节点就像一个大脑分裂成了两个。如果客户端还在基于原来的master节点继续写入数据那么新的master节点将无法同步这些数据,当网络问题解决后sentinel集群将原先的master节点降为slave节点,此时再从新的master中同步数据将造成大量的数据丢失。

解决方法

修改redis的配置文件

min-replicas-to-write 3  表示连接到master的最少slave数量
min-replicas-max-lag 10  表示slave连接到master的最大延迟时间
1
2

当我们上面两个条件都不满足时,那么master就会拒绝写请求,这样就可以减小数据同步后的数据丢失

# 事务

Redis支持事务,通过 MULTI (opens new window) (事务开始)、 DISCARD (opens new window) (事务取消)、 EXEC (opens new window) (执行事务)和 WATCH (opens new window) (监听key,当key被修改时会打断当前事务)四个命令来实现事务功能

# 执行的三个阶段

  1. 开启事务(multi)
  2. 命令入队(业务操作)
  3. 执行事务(exec)或取消事务(discard)

# 特点

  1. redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
  2. Redis事务失败时不支持回滚,而是会继续执行剩下的命令

深入:Redis 事务详解 - SegmentFault 思否 (opens new window)

# 热key

所谓热key问题就是,突然有几十万的请求去访问redis上的某个特定key,那么这样会造成流量过于集中,达到物理网卡上限,从而导致这台redis的服务器宕机引发雪崩。

img

针对热key的解决方案:

  1. 提前把热key打散到不同的服务器,降低压力
  2. 加入二级缓存,提前加载热key数据到内存中,如果redis宕机,走内存查询
编辑 (opens new window)
上次更新: 2021/04/13, 13:33:16
原理
分布式锁,过期策略,淘汰规则

← 原理 分布式锁,过期策略,淘汰规则→

Theme by Vdoing | Copyright © 2021-2021 小游
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式