跳到主要内容

06-10

06 数据同步:主从库如何实现数据一致

  • Redis的高可靠性:
    1. 数据尽量少丢失(AOF、RDB)
    2. 服务尽量少中断(增加副本冗余量,将一份数据同时保存在多个实例上)
  • 主从库读写分离,主、从库均可接收读操作,主库接受写操作,执行后同步给从库
  • 主从库第一次数据同步:
    1. 主从库建立连接、协商同步,为全量复制做准备
    2. 主库同步所有数据到从库,从库收到数据后,在本地完成数据加载,这个过程主要依赖于内存快照生成的RDB文件
  • 主从库全量复制时的主库压力: 全量复制需要生成、传输RDB文件,从库数量大时会导致主库忙于fork子进程生成RDB文件,阻塞主线程处理正常请求,导致主库响应速度下降,传输RDB文件会占用主库网络带宽
  • “主-从-从”模式,主从级联模式分担主库压力: 选择部分从库,用于级联其他从库,以减轻主库压力
  • 主从库完成全量复制后,会维护一个网络连接,这个过程被称为基于长连接的命令传播,可以避免频繁建立连接的开销
  • 主从库网络连接中断: 网络中断后,主库会采用增量复制(Redis 2.8之后)的方式继续同步,只把主从库网络断连期间主库收到的命令同步给从库
  • repl_backlog_buffer: 一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己已经读到的位置,缓冲区写满后,主库继续写入则会覆盖之前写入的操作,可在配置中调整repl_backlog_size参数
  • 主从同步使用RDB而不使用AOF的原因: RDB文件内容是经过压缩的二进制数据(不同数据类型进行针对性优化),文件很小,AOF文件记录了每次写操作的指令,文件体积大,且包括冗余操作(同一个Key的多次操作)
  • 主库还可以根据slave_repl_offset判断是全量复制,还是增量复制

07 哨兵机制: 主库挂了,如何不间断服务

  • 哨兵: 本质上是一个运行在特定模式下的redis实例,不服务请求操作,只完成监控、选主、通知的任务
  • 切换主库流程:
    1. 监控: 判断主从库下线
    2. 选主: 选出新主库
    3. 通知: 让从库执行replicaof,与新主库同步,通知客户端,与新主库连接
  • 主观下线: 哨兵进程使用PING命令检测自己与主、从库的网络连接情况,用于判断实例状态
  • 客观下线: 哨兵集群中大多数实例判断主库已经“客观下线”时,主库才会被标记为“客观下线”,当有N个哨兵实例时,最好要有N/2+1个实例判断主库为“主观下线”,最终才能判断主库为“客观下线”
  • 选定新主库:
    1. 筛选: 检查从库当前在线状态,并且判断它之前的网络连接状态
    2. 根据从库优先级、从库复制进度、从库ID号三个规则给从库打分,得分最高者为新主库

08 哨兵集群: 哨兵挂了,主从库还能切换吗

  • 哨兵集群组成: 基于Redis提供的pub/sub机制,哨兵与主库建立连接,发布自身连接信息(IP、端口),并从主库上订阅信息,获取其他哨兵发布的连接信息
  • 哨兵处理彼此之间建立连接形成集群外,还需要跟从库建立连接,因为在哨兵的监控任务中,需要对主从库进行心跳判断,主从库切换完成后,还需要通知从库与新主库进行同步
  • 由哪个哨兵执行主从切换: 通过投票机制(Leader选举),与哨兵集群判断“客观下线”过程相似
  • 要保证所有哨兵实例配置一致,尤其是主观下线的判断之down-after-milliseconds,此值不一致可能导致哨兵集群无法对主库故障形成共识
  • 哨兵对主从库进行的在线状态判断等操作属于时间时间,通过定时器完成,每个哨兵的定时器执行周期都会添加一个随机时间偏移,避免哨兵同时判定主库下线,同时进行leader选举

09 切片集群: 数据增多了,该加内存还是加实例

  • 切片集群(分片集群): 指启动多个Redis实例组成一个集群,然后按照一定的规则,把收到的数据划分成多分,每一份用一个实例来保存
  • 扩展方案:
    1. 纵向扩展: 升级单个Redis实例资源配置, 实施简单、直接,但是会受到硬件和成本的限制
    2. 横向扩展: 横向增加当前Redis实例的个数
  • Redis Cluster: 无中心化,采用哈希槽(Hash Slot)处理数据和实例之间的映射关系,每个键值对会根据它的Key被映射到一个哈希槽中
  • 可根据不同实例配置,手动分配哈希槽,需要把所有槽分配完毕,否则Redis集群无法工作
  • 客户端定位数据: 客户端与集群实例建立连接后,实例会把哈希槽的分配信息发送给客户端
  • Redis实例会把自己的哈希槽信息发给与它相连接的其他实例,来完成哈希槽分配信息的扩散
  • 重新分配哈希槽:
    1. 在集群中,实例新增或者删除,都会导致Redis需要重新分配哈希槽
    2. 为了负载均衡,Redis需要吧哈希槽在所有实例上重新分配一遍
  • Redis Cluster的重定向机制: 实例接受到客户端请求后,假如实例上并没有这个键值对映射的哈希槽,这个实例会给客户端返回一个包含新实例访问地址的MOVED命令响应结果,客户端接受后则会更新本地缓存的对应关系,并重新发送请求到正确的实例
  • 假如请求时实例数据迁移只完成了部分,旧实例会给客户端返回一条ASK报错信息,客户端接收后向正确的新实例发送ASKING命令,请求新实例允许执行客户端接下来发送的命令,然后再向新实例发送命令读取数据(此过程不更新客户端对应关系缓存)
  • 分片实现采用hash-based而非range-based,能把数据打散,不容易引起数据倾斜,有利于数据分片分布均衡,提高访问性能