redis主从复制
1.redis主从复制的作用
redis的定位是一个高可用的数据服务器,可是在实际生产环境下,单机的redis服务器是无法满足真正意义上的高可用性的。
第一,单机的redis服务器很容易发生单点故障,即使redis提供了各种持久化的方法来避免数据的丢失,但是物理上的故障(硬盘损毁等)还是无法完全避免的。
第二,如果对单台机器的性能进行纵向拓展,无论是CPU,内存还是磁盘容量都很容易达到瓶颈,无法满足实际需求。
针对这些问题,redis提供了复制(replication)的功能,通过"主从(一主多从)"和"集群(多主多从)"的方式对redis的服务进行水平扩展,用多台redis服务器共同构建一个高可用的redis服务系统。
在这里,我们主要介绍redis的主从复制功能。
2.redis主从复制介绍
在redis的复制概念模型中,分为"主(master)"和"从(slave)"两种角色类型的服务器,从服务器"服从"主服务器。主服务器既可以读也可以写,而从服务器原则上只允许读操作(通过修改配置,从服务器也可以执行写入操作),同时负责接收和同步主服务器上的数据。主服务器和从服务器是一对多的关系,从服务器也可以拥有从服务器,以此类推。
可以看到主从结构下的redis服务器集群节点的拓扑结构是一棵树。
使用了主从结构的redis系统,一般是读写分离的:"主库负责写入,在写入的同时和从库进行数据的同步;而从库负责读取操作。"
一主多从的结构下,不会出现单点故障,同时可用性也得到了保障。由于负责读取的从库相对较多,因此很适合读多写少(例如:电商)的场景。
使用redis的主从复制功能比较简单,只需要在从服务器启动的配置文件中添加slaveof "IP" "PORT"配置即可,同时redis也允许其它的方式来实现这一目的(启动时命令行参数、redis命令等)。可以通过info replication来查看当前redis服务器在主从复制中的状态。
6381端口 从库状态
6379端口 主库状态
3.redis主从复制原理
1.从服务器初始化
当从服务器启动时,会向主服务器发送SYNC命令,请求同步数据。主服务器接收到消息之后,进行RDB持久化,并生成一个快照文件;与此同时,主服务器会将生成快照期间新执行的命令缓存起来。在快照文件生成完毕之后,主服务器将RDB快照文件和缓存下来的命令一并发送给从服务器,从服务器首先载入接收到的RDB快照文件,接着执行被缓存下来的新命令,完成主从数据的初始化同步操作。
2.从服务器保持同步
从服务器在同步完成之后,主服务器接收到的所有命令都会异步的发送给从服务器用来保持主从数据的一致性。
3.从服务器故障后处理
当从服务器崩溃之后,重启之后进行初始化,会自动的同步主服务器的数据。在redis的2.8版本之后,redis采用了"增量复制"的方式优化了从服务器的初始化同步数据的过程。
4.主服务器故障后处理
当主服务器崩溃之后,首先需要手动的选择一个从服务器升级为主服务器(需要手动调整所有相关的从服务器),然后启动之前已经崩溃的主服务器作为从服务器回到系统中。
可以看到,redis在主服务器崩溃之后需要繁琐的人工干预来恢复服务,特别是在主数据库禁止了持久化之后,上述步骤不能错乱,否则会导致主数据库重启后恢复了错误数据,进而导致从数据库也同步错误数据这一灾难性后果。为此,redis提供了哨兵机制,用于自动化的监控和维持分布式redis系统的良好运转。
4.redis哨兵
1.哨兵的介绍
redis的设计者为了让redis能够在主从模式下实现故障恢复的自动化,为此提供了redis的哨兵功能。哨兵是一个独立于数据服务器的进程,用于监控redis数据服务器的状态,当主从模式下最关键的主服务器出现故障时,能够被哨兵自动的察觉。同时哨兵会在剩余的从服务器中"选举"出新的主服务器,达到自动化恢复系统服务的目的。
2.哨兵的使用
redis提供了redis-sentinel脚本用于部署哨兵,启动时通过指定的哨兵配置文件来对哨兵的行为进行灵活的控制。哨兵的配置文件中至少需要包含被哨兵监控的主服务器IP、端口、投票决定数目,当然也可以配置诸如down-after-milliseconds(发送ping命令的时间间隔,用于监听)等选项。
sentinel monitor "master_name" "IP" "PORT"
down-after-milliseconds "milliseconds" ("milliseconds"大于1000时,默认为1000)
3.哨兵的工作方式
哨兵启动时会与主服务器建立连接,并且间接的获得所属从服务器信息,完成哨兵的初始化。哨兵初始化完成之后,会周期性的和主从服务器、其它哨兵节点(通过消息频道的订阅/发布)进行通信。
哨兵每10秒会向所有服务器发送一次INFO命令,获得相关redis服务器的当前状态以便决定是否需要故障恢复。
当一个哨兵在down-after-milliseconds规定时间内未收到主服务器的响应,则当前哨兵"主观"认为主服务器下线,同时和监视当前系统的其它哨兵进行投票决定,当超过当前哨兵配置中投票决定的数目时,则当前哨兵"客观"认为主服务器下线,哨兵集群会选举出领导哨兵来进行主从服务器集群主从状态的切换(使用Raft算法)。
5.redis主从复制总结
1.乐观复制策略
redis的主从复制采用的是乐观复制的策略,在一定的时间内允许主从服务器的数据不完全一致,但是保持主从数据库数据的最终一致性(按照CAP定理,放弃了C(强一致性))。
这意味着redis主从服务器之间的数据复制操作时异步的,主服务器不等待从服务器返回复制的结果,可以立即处理新的写入命令。这一策略使得主服务器的性能在复制时不会受到太大影响,但是从服务器会出现短时间内数据不一致的情况。redis允许用户配置主库的min-slaves-to-write(代表至少N台从服务器完成复制,才允许主服务器写入)和min-slaves-max-lag(允许从服务器断开连接的时间)这两个配置项来控制分区中数据不一致的影响。
2.和集群的区别
redis的主从复制特性为redis带来了很高的读取可用性,但是对于海量数据的持久化存储是力不从心的。因为主从复制结构下,任意的节点都保存了100%的存储数据,所以能够存储的数据规模还是受限于单例服务器存储容量的大小。
为此,在单主多从结构的基础上,redis还提供了集群特性。通过将存储数据合理的分片存储在不同的redis节点上,通过集群水平扩容之后的redis集群拥有了极高的读写可用性和分区容错性。为了理解更强大、复杂的集群特性其基础之一就是redis的主从复制原理。