25. Redis集群脑裂该怎么解决呢Redis 脑裂通常发生在主从加哨兵模式下。由于网络分区Sentinel 无法感知到 master误判它下线于是把某个 slave 提升为 new master。但 old master 实际上可能还活着并且部分客户端还在往 old master 写数据。这样就会短时间出现两个 master。网络恢复后old master 会被 Sentinel 降级为 slave并重新同步 new master 的数据这时 old master 在脑裂期间写入的数据就可能丢失。解决方式主要是限制 old master 在异常情况下继续写入。可以配置 min-replicas-to-write 和 min-replicas-max-lag要求 master 至少有指定数量、复制延迟不超过指定时间的 slave才允许处理写请求。这样当 old master 因网络分区无法和 slave 正常同步时就会拒绝写请求。它不能彻底避免脑裂但可以最大限度减少脑裂期间的数据丢失。26. Redis的分片集群有什么作用Redis 分片集群主要解决单机 Redis 的容量瓶颈和吞吐瓶颈。Redis Cluster 会把数据划分为 16384 个 hash slot并分配到多个 master 节点上。每个 master 负责一部分 slot 和对应的数据所以可以把数据分散到多个 master扩展内存容量同时多个 master 也能分摊请求提高整体吞吐量。每个 master 可以配置 slaveslave 主要用于数据备份和故障转移。当 master 宕机时对应的 slave 可以晋升为新的 master提高高可用。集群节点之间通过 Gossip 协议进行通信和心跳检测。客户端可以访问任意节点如果 key 不在当前节点负责的 slot 上会返回 MOVED 重定向引导客户端访问正确节点。27. Redis分片集群中数据是怎么存储和读取的Redis Cluster 通过 hash slot 存储和读取数据。集群一共有 16384 个 hash slot每个 master 负责一部分 slot。写入 key 时会用 CRC16(key) 对 16384 取模算出 key 属于哪个 slot再根据 slot 找到对应的 master 节点进行存储。读取时也是同样的流程。如果客户端请求到了错误节点Redis 会返回 MOVED 重定向告诉客户端正确的 slot 所在节点。客户端会缓存 slot 到节点的映射后续直接访问正确节点。28. Redis是单线程的但是为什么还那么快Redis 快主要有几个原因。第一Redis 基于内存操作读写速度很快。第二Redis 内部使用了高效的数据结构比如哈希表、跳表、SDS 等。第三Redis 命令执行主要是单线程的避免了多线程带来的上下文切换和锁竞争问题。第四Redis 使用 IO 多路复用和非阻塞 IO一个线程可以同时处理大量客户端连接。另外像 BGSAVE 和 AOF 重写这类耗时任务Redis 会通过后台子进程处理尽量减少对主线程的影响。但 fork 和磁盘 IO 在极端情况下仍可能带来短暂阻塞所以不能简单说完全不会阻塞。29. 能解释一下I/O多路复用模型I/O 多路复用是指一个线程可以同时监听多个 Socket当某个 Socket 有可读或者可写事件时操作系统会通知redis去处理对应的事件。这样就避免了一个线程阻塞等待一个连接也不需要为每个连接创建线程可以减少线程切换和资源消耗。常见的 I/O 多路复用模型有 select、poll 和 epoll。在 Linux 下Redis 一般使用 epoll。相比 select 和 poll 每次都要遍历全部 fdepoll 会在内核中维护就绪事件列表redis 调用 epoll_wait 时可以直接拿到已经就绪的事件所以在高并发场景下性能更好。Redis 的网络模型就是 I/O 多路复用加事件驱动。它会把连接建立、命令读取、命令执行、响应写回等操作抽象成不同事件并交给不同的事件处理器处理。Redis 6.0 之后引入了多线程 I/O主要是为了加速网络读写、协议解析和响应写回但命令执行仍然是单线程所以不会破坏 Redis 命令执行的原子性。
Redis拷打第七讲(最终章)
25. Redis集群脑裂该怎么解决呢Redis 脑裂通常发生在主从加哨兵模式下。由于网络分区Sentinel 无法感知到 master误判它下线于是把某个 slave 提升为 new master。但 old master 实际上可能还活着并且部分客户端还在往 old master 写数据。这样就会短时间出现两个 master。网络恢复后old master 会被 Sentinel 降级为 slave并重新同步 new master 的数据这时 old master 在脑裂期间写入的数据就可能丢失。解决方式主要是限制 old master 在异常情况下继续写入。可以配置 min-replicas-to-write 和 min-replicas-max-lag要求 master 至少有指定数量、复制延迟不超过指定时间的 slave才允许处理写请求。这样当 old master 因网络分区无法和 slave 正常同步时就会拒绝写请求。它不能彻底避免脑裂但可以最大限度减少脑裂期间的数据丢失。26. Redis的分片集群有什么作用Redis 分片集群主要解决单机 Redis 的容量瓶颈和吞吐瓶颈。Redis Cluster 会把数据划分为 16384 个 hash slot并分配到多个 master 节点上。每个 master 负责一部分 slot 和对应的数据所以可以把数据分散到多个 master扩展内存容量同时多个 master 也能分摊请求提高整体吞吐量。每个 master 可以配置 slaveslave 主要用于数据备份和故障转移。当 master 宕机时对应的 slave 可以晋升为新的 master提高高可用。集群节点之间通过 Gossip 协议进行通信和心跳检测。客户端可以访问任意节点如果 key 不在当前节点负责的 slot 上会返回 MOVED 重定向引导客户端访问正确节点。27. Redis分片集群中数据是怎么存储和读取的Redis Cluster 通过 hash slot 存储和读取数据。集群一共有 16384 个 hash slot每个 master 负责一部分 slot。写入 key 时会用 CRC16(key) 对 16384 取模算出 key 属于哪个 slot再根据 slot 找到对应的 master 节点进行存储。读取时也是同样的流程。如果客户端请求到了错误节点Redis 会返回 MOVED 重定向告诉客户端正确的 slot 所在节点。客户端会缓存 slot 到节点的映射后续直接访问正确节点。28. Redis是单线程的但是为什么还那么快Redis 快主要有几个原因。第一Redis 基于内存操作读写速度很快。第二Redis 内部使用了高效的数据结构比如哈希表、跳表、SDS 等。第三Redis 命令执行主要是单线程的避免了多线程带来的上下文切换和锁竞争问题。第四Redis 使用 IO 多路复用和非阻塞 IO一个线程可以同时处理大量客户端连接。另外像 BGSAVE 和 AOF 重写这类耗时任务Redis 会通过后台子进程处理尽量减少对主线程的影响。但 fork 和磁盘 IO 在极端情况下仍可能带来短暂阻塞所以不能简单说完全不会阻塞。29. 能解释一下I/O多路复用模型I/O 多路复用是指一个线程可以同时监听多个 Socket当某个 Socket 有可读或者可写事件时操作系统会通知redis去处理对应的事件。这样就避免了一个线程阻塞等待一个连接也不需要为每个连接创建线程可以减少线程切换和资源消耗。常见的 I/O 多路复用模型有 select、poll 和 epoll。在 Linux 下Redis 一般使用 epoll。相比 select 和 poll 每次都要遍历全部 fdepoll 会在内核中维护就绪事件列表redis 调用 epoll_wait 时可以直接拿到已经就绪的事件所以在高并发场景下性能更好。Redis 的网络模型就是 I/O 多路复用加事件驱动。它会把连接建立、命令读取、命令执行、响应写回等操作抽象成不同事件并交给不同的事件处理器处理。Redis 6.0 之后引入了多线程 I/O主要是为了加速网络读写、协议解析和响应写回但命令执行仍然是单线程所以不会破坏 Redis 命令执行的原子性。