文章目录加载中

Redis集群:数据复制原理和策略

# 介绍

为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。

复制概念中,数据库分为主数据(master)和从数据库(slave)。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。

# 图结构

在 redis 中,从数据库也可以有从数据库。从而组成一个网状结构。

# 启用复制

只需要在从数据库的配置文件中加入slaveof 主数据库地址 主数据库端口即可,主数据库无需进行任何配置。

例如:redis-server --port 6380 --slaveof 127.0.0.1 6379

默认情况下,从数据库不可写,可以通过将slave-read-only 设置为 no 来使从数据库可写。注意:向从数据库写数据不会同步到主数据库,主数据库的数据修改会覆盖从数据库的修改

在 redis 交互式命令行中:

# 设置从数据库
SLAVEOF 127.0.0.1 6379
# 将当前从数据库升级为主数据库
SLAVEOF NO ONE

# 复制的原理

主从数据库复制利用了 RDB 和 AOF 的原理。复制的过程分为 2 部分:复制初始化和同步命令。

复制初始化的过程如下:

  1. slave 启动,向 master 发送 SYNC 命令
  2. master 接受到 SYNC 命令后,保存 RDB 快照文件。在制作快照期间的命令,会被 master 缓存下来
  3. master 将 RDB 快照文件和缓存的命令发送给 slave
  4. slave 加载 RDB 文件,以及缓存的相关命令

完成复制初始化之后,就是同步命令。master 会将写数据相关的命令都发送给 slave(读命令不会同步,因为不会修改数据)。

# 复制的策略

# 增量复制

Redis 2.6 以及之前的版本会重新进行复制初始化(即主数据库重新保存快照并传送给从数据库),Redis 2.8 版的一个重要改进就是断线重连能够支持有条件的增量数据传输,当从数据库重新连接上主数据库后,主数据库只需要将断线期间执行的命令传送给从数据库,从而大大提高 Redis 复制的实用性。

增量复制实现的基础条件:

  1. 从数据库会存储主数据库的运行 ID(每个 redis 对应唯一一个 ID)
  2. 复制同步时,主数据库每将一个命令传送给从数据库时,会同时把该命令存放到一个积压队列(backlog)中,并记录下当前积压队列中存放的命令的偏移量范围
  3. 从数据库接收到主数据库传来的命令时,会记录下该命令的偏移量。

在 redis 2.8 版本之后,不再发送 SYNC 命令,取而代之的是发送 PSYNC,格式为“PSYNC 主数据库的运行 ID 断开前最新的命令偏移量”。主数据库收到 PSYNC 命令后,会执行以下判断来决定此次重连是否可以执行增量复制:

  1. 首先主数据库会判断从数据库传送来的运行 ID 是否和自己的运行 ID 相同。
  2. 然后判断从数据库最后同步成功的命令偏移量是否在积压队列中,如果在则可以执行增量复制,并将积压队列中相应的命令发送给从数据库。

注意:积压队列是一个固定长度的循环队列,默认情况下积压队列的大小为 1 MB

# 乐观复制(optimistic replication)

乐观复制不要主从数据每时完全一致,只保证最终一致性,从而换取 redis 响应客户端请求以及复制性能的提升。

Redis 在主从数据库之间复制数据的过程本身是异步的,不会等待从数据库接收到该命令后再返回给客户端。这一特性保证了启用复制后主数据库的性能不会受到影响。

本文来自心谭博客:xin-tan.com,经常更新web和算法的文章笔记,前往github查看目录归纳:github.com/dongyuanxin/blog