缓存穿透
查询根本不存在的数据,使得请求直达存储层,导致其负载过大,甚至宕机
解决方案:
-
缓存空对象
存储层未命中后,仍然将空值存入缓存层
再次访问该数据时,缓存层会直接返回空值。
-
布隆过滤器
将所有存在的key提前存入布隆过滤器,在访问缓存层之前,先通过过滤器拦截,若请求的是不存在的key,则直接返回空值。
缓存击穿
某一个热点数据,访问量非常大。在器缓存失效瞬间大量请求直达存储层,导致服务崩溃。
解决方案
-
加互斥锁
对数据的访问加互斥锁,当一个线程访问该数据时,其他线程只能等待。
这个线程访问过后,缓存中的数据将被重建,届时其他线程就可以直接从缓存中取值。
-
永不过期
不设置过期时间,所以不会出现上述问题,这是“物理”上的不过期。
为每个value设置逻辑过期时间,当发现该逻辑过期时,使用单独的线程重建缓存。
缓存雪崩
由于某些原因,缓存曾不能提供服务(或者有几个key同时失效),导致所有请求直达存储层,造成存储层宕机。
解决方案:
-
避免同时过期
- 设置过期时间时,附加一个随机数,避免大量key同时过期
-
构建高可用的Redis缓存
部署多个Redis实例,个别节点宕机,依然可以保持服务器的整体可用。
-
构建多级缓存
增加本地缓存,在存储层前面多加一级屏障,降低请求直达存储层的几率。
-
启用限流和降级措施
对存储层增加限流措施,当请求超出限制时,对其提供降级服务。
主从复制
一个服务器想要复制另一个服务器,那么这个主动复制的服务器为从服务器,被复制的服务器为主服务器
使用salveof命令
旧版的复制功能分为两步:同步和命令传播两个操作。
同步是将从服务器的数据库状态更新至主服务器的数据库状态。
- 首先从服务器执行同步操作,即向主服务器发送sync命令
- 收到sync命令的主服务器执行bgsave命令,生成一个RDB文件,并用一个缓冲区记录从现在开始的所有写命令。
- bgsave命令执行完毕后,将生成的RDB文件发送给从服务器,从服务器载入这个RDB文件,将数据库的状态更新为主服务器的数据库状态。
- 之后主服务器在将记录在缓冲区中的所有写命令发送给从服务器,从服务器在执行这些命令,实现数据库的同步。
因为执行bgsave命令的过程中也就是生成RDB文件的过程中,是由子进程执行的,而主进程仍然可以继续执行写入命令,所以需要这个缓冲区来存储。
同步执行完之后就到了命令传播阶段,每当主服务器执行写入命令的时候,就会将该命令发送给从服务器,从服务器执行了相同的命令后,主从服务器数据库就有回到了相同的状态。
但是旧版复制功能有缺陷:
从服务器的复制有两种状态:
- 初次复制,从服务器以前没有复制过任何主服务器,或者当前复制的服务器和之前复制的主服务器不同。
- 断线后的重复制:在命令传播阶段从服务器断线,从服务器后通过重连重新连接到了主服务器,继续复制主服务器。
而缺陷就在于对于断线后的重复制,断线重连后的复制主服务器会把包含所有命令的RDB文件发送给从服务器,但实际上,从服务器的数据库状态与主服务器的数据库状态不同的只是断线后主服务器执行的命令,没有必要同步之前所有的命令。
因此就有了新版的复制功能
为了解决部分重同步所出现的问题,Redis2.8之后出现了psync命令来替代sync命令
psync有两个模式:完整重同步和部分重同步:
- 完整重同步用于处理初次复制的情况。
- 部分重同步用于处理断线重连后的同步情况。断线重连后主服务器只向从服务器发送断线后执行的写命令。
部分重同步原理:
部分重同步有三部分组成:主服务器的复制偏移量和从服务器的复制偏移量、主服务器的复制积压缓冲区、服务器的ID。
复制偏移量:
- 主服务器和从服务器在执行复制的过程中都维护一个自己的复制偏移量,每次主服务器向从服务器发送n个字节的数据时,就将复制偏移量加n,从服务器收到后也将自己的复制偏移量加n。通过复制偏移量,就可以判断出主从服务器是否处于同步的状态。
复制积压缓冲区:
- 是由主服务器维护的一个固定长度的FIFO队列,默认大小为1MB。主服务器接收到写命令后不仅会将命令发送给从服务器,还会将命令放入到复制积压缓冲区中。所以该缓冲区中会保存了最近执行的写命令,并且在赋值积压缓冲区中还对应存储着每个字节对应的复制偏移量。
- 从服务器断线重连后,通过psync命令将自己的复制偏移量发送给主服务器。然后主服务器来判断执行那种同步操作。
- 如果从服务器的复制偏移量offset+1的数据不在复制积压缓冲区中,那么就执行完整重同步
- 如果offset+1的数据在缓冲区中,就执行部分重同步。
服务器id:
- 如果从服务器重连后的和第一次复制时主服务器发送的服务器id不一致,那就说明断线前连接的的主服务器并不是现在连接的,因此要执行完整重同步。否则执行部分重同步。