Redis高可用

1. 事务机制和IO多路复用

1.1 事务

1.1.1 事务特点

  • 事务提交前,先检查命令语法是否正确
  • 提交后的命令一定会执行
  • 有命令报错,也会执行完
  • 不能回滚

1.1.2 命令

  • multi,告诉Redis服务器开启一个事务。只是开启而不是执行。
  • exec, 告诉Redis开始执行事务
  • discard,告诉Redis取消事务
  • watch,监视某一个键值对,它的作用是在事务执行之前如果监视的键值被修改,事务会被取消

1.2 IO多路复用

redis 是单线程,单线程只能在一个CPU内核上执行,假如是4核的,只会占用一个,其它三个不参与。 worker线程串行 read读->计算->write返回

在Redis6.0加入了io-threads, 主线程worker只进行计算,并行读取

io-threads 4

io-threads-do-reads yes

2. 持久化和过期淘汰策略

2.1 持久化

Redis是存储在内存中的, 服务器重启数据会丢失。持久化方案可以保存数据到磁盘文件,可以恢复到内存中。Redis提供的持久化方案有:

  • rdb:生成某一时刻的快照,保存到二进制文件中
    • 优点:
      • 容灾性好,方便备份
      • 性能最大化,fork出一个子进程来操作,对主进程没有影响
      • 数据较多时,相对于aof启动效率更高
    • 缺点:
      • 会造成数据丢失
  • aof:实时记录每一条写命令,追加到文件中,打开可以看到具体的操作记录
    • 同步策略:appendfsync
      • everysec(默认),每秒同步一次
      • always,每次操作后都要同步一次
      • no,由操作系统调度进行同步
    • 重写策略:
      • 手动触发,执行bgrewiteaof命令
      • 自动触发:auto-rewrite-percentage 100, auto-rewrite-min-size 64mb
    • 优点
      • 数据安全,不会造成数据的丢失
    • 缺点
      • 比rdb重启效率低;运行效率比rdb低
  • 混合模式:上面两种方式的结合

触发方式有两种:

  • 手动触发:
    • save命令,会让Redis处于阻塞的状态,直到rdb持久化完成,线上环境谨慎使用
    • bgsave命令,它会fork出一个子进程(有短暂阻塞),用来执行持久化,主进程继续响应客户端请求
  • 自动触发:
    • 配置文件修改(save n m),在n秒内,有m个key发生变化就会触发,执行命令最总执行的是bgsave

2.2 过期键删除策略

Redis设置key时,都会设置一个过期时间,Redis同时使用了两种过期删除策略,惰性过期和定时过期

  • 惰性过期:只有当这个key被访问时,才会判断是否过期,过期则清理掉。他可以节省CPU的资源,但是会浪费内存的资源。存出现大量过期key没有被访问过,从而不会被清理,导致内存占用越来越大。
  • 定时过期:每间隔一段时间,扫描一定数量的设置了过期时间的key,如果过期了则删除
    • 默认每秒进行10次过期扫描
    • 从过期字典中随机20个key
    • 删除这20个key中已过期的
    • 如果超过25%的key过期,则重复第一步
    • 同时,为了保证业务不受影响,Redis还设置了扫描的时间上限,默认不会超过25ms

2.3 内存淘汰策略

加入内存不足时,Redis会根据设置的淘汰策略,删除一些不常用的数据,保证Redis的正常使用

  • noevication: 当内存使用超过配置的时候会返回错误,不会驱逐任何键
  • allkeys-lru:加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键
  • volatile-lru:加入键的时候如果超限,首先从设置了过期时间的键集合中驱逐最久没用使用的键
  • allkeys-random:加入键的时候如果过限,从过期键的集合中随机驱逐
  • volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐
  • volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键
  • volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少得键
  • allkeys-lfu:从所有键中驱逐使用频率最少得键

3. Redis缓存常见的问题

  • 缓存雪崩:大量Redis key 在同一时间失效,导致请求访问到数据库, 造成数据库瓶颈
    • 过期时间随机设置
    • 定时任务重新设置过期时间
    • 永不过期
  • 缓存穿透:短时间内大量访问不存在的数据,导致穿透Redis直接访问数据库,造成数据库瓶颈
    • 没有值时也保存Redis
    • 封禁对方IP
    • 对参数进行校验
    • 布隆过滤器
  • 缓存击穿:一个热点key失效,导致访问这个热点key的访问直接到数据库。
    • 加锁,分布式锁或互斥锁

4. 布隆过滤器

布隆过滤器主旨是采用一个很长的二进制数组,并通过一些列的hash函数来确定该数据是否存在

  • 优点:二进制组成的数据,占用内存极少,并且插入和查询速度足够快
  • 缺点:随着数组的增加,误判概率增加;还有无法判断数据一定存在;无法删除数据

5. 高并发下数据库和Redis双写不一致问题

  • 不考虑高并发时,使用锁可以彻底解决问题,锁会把并发串行化
  • 先更新数据库,在更新缓存
  • 先更新缓存,再更新数据库
  • 先删除缓存,后更新数据库
  • 先更新数据库,后删除缓存