复制
概述
- 创建具有相同数据库的拷贝服务器
- 快速入门示例
复制的工作原理
- 部分复制
- 注意事项
- 处理服务器下线
概述
持久化功能,可以保证服务器在重启的情况下也不会损失(或少量损失)数据。但是如果发生硬件问题,比如硬盘故障等,数据也可能丢失,而且会影响正常服务。
复制功能可以自动实现数据同步;把主服务器上的数据同步到从服务器。可以解决单点故障,确保正常提供服务。
创建具有相同数据库的拷贝服务器
Redis的复制(replication)功能允许用户根据一个 Redis 服务器来创建 任意多个该服务器的复制品
,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。
主从服务器两者拥有相同的数据库数据:只要主从服务器之间的网络连接正常,主服务器就会一直将发生在自己身上的数据更新同步给从服务器,从而一直保证主从服务器的数据相同。
Redis允许从服务器执行客户端发送的读命令,比如 GET 、LRANGE、SMEMBERS、HGET、ZRANGE 等等。
因为主从服务器拥有相同的数据库数据,所以从服务器在执行客户端发送的读命令时,获得的结果与主服务器执行相同的读命令所获得的结果是一样的。因此,用户可以将原本由主服务器负责处理的一部分(甚至全部)读命令请求转交给从服务器处理,从而降低主服务器在处理读命令请求方面的负载,并扩展整个系统处理读命令请求的能力。通过添加从服务器可以线性地扩展整个系统处理读命令请求的能力。
从服务器的创建与使用
Redis提供了多种方法来为某个主服务器创建从服务器:
使用 SLAVEOF
命令 比如向一个服务器发送 SLAVEOF 127.0.0.1 6379 ,可以让接收到该命令的服务器变为 127.0.0.1:6379 的从服务器。
在将一个服务器设置成从服务器之后,可以通过向它发送 SLAVEOF no one 来让它变回一个主服务器(数据库已有的数据会被保留)。在启动服务器时,通过设置 slaveof
配置选项来让服务器成为指定服务器的从服务器 redis-server /path/redis.6377.conf –slaveof 127.0.0.1 6379
在配置文件中添加配置,指定配置文件启动
slaveof
快速入门示例
- 在主服务器模拟数据写入
[root@localhost config]# redis-cli
127.0.0.1:6379> KEYS *
(empty array)
127.0.0.1:6379>
127.0.0.1:6379> set user1 zs
OK
- 从服务器同步主服务器
[root@localhost config]# redis-cli -p 6377
127.0.0.1:6377> get user1
(nil)
127.0.0.1:6377> SLAVEOF localhost 6379 # 开启 从主服务器同步
OK
127.0.0.1:6377> get user1
'zs'
复制的工作原理
当一个从机启动后,会向主机发送SYNC命令,主机接收到SYNC命令后会开始在后台保存快照(RDB持久化过程),并将保存期间接收到的命令缓存起来,当快照完成后,Redis会将快照文件和所有缓存的命令发送给从机。
从机收到后,会载入快照文件并执行收到的缓存的命令,当主从断开重连后会重新执行上述操作。
- Slave无论是第一次连接还是重连到Master,它都会发出一个SYNC命令
- 当Master收到SYNC命令之后,会做两件事:
- Master执行BGSAVE,即在后台保存数据到磁盘(rdb快照文件)
- Master同时将新收到的写入和修改数据集的命令存入缓冲区(非查询类)
- Master在后台把数据保存到快照文件完成之后,Master会把这个快照文件传送给Slave,而Slave则把内存清空后,加载该文件到内存中
- Master把此前收集到缓冲区中的命令,通过Reids命令协议形式转发给Slave,Slave执行这些命令,实现和Master的同步
- Master/Slave此后会不断通过异步方式进行命令的同步,达到最终数据的同步一致
- 需要注意的是Master和Slave之间一旦发生重连都会引发全量同步操作。但在2.8之后版本,也可能是部分同步操作。
部分复制
2.8版本开始,当Master和Slave之间的连接断开之后,他们之间可以采用持续复制处理方式代替采用全量同步。Master端为复制流维护一个内存缓冲区(in-memory
backlog),记录最近发送的复制流命令;同时,Master和Slave之间都维护一个复制偏移量(replication offset)和当前Master服务器ID(Master
run id)。
当网络断开,Slave尝试重连时:
- 如果MasterID相同(即仍是断网前的Master服务器),并且从断开时到当前时刻的历史命令依然在Master的内存缓冲区中存在,则Master会将缺失的这段时间的所有命令发送给Slave执行,然后复制工作就可以继续执行了;
- 否则,依然需要全量复制操作;
Redis 2.8 版本的这个部分重同步特性会用到一个新增的 PSYNC 内部命令, 而 Redis 2.8 以前的旧版本只有 SYNC 命令, 不过,只要从服务器是
Redis 2.8 或以上的版本, 它就会根据主服务器的版本来决定到底是使用 PSYNC 还是 SYNC。
- 如果主服务器是 Redis 2.8 或以上版本,那么从服务器使用 PSYNC 命令来进行同步。
- 如果主服务器是 Redis 2.8 之前的版本,那么从服务器使用 SYNC 命令来进行同步。
注意事项
- 一个Master可以有多个Slave,从服务器也可以有自己的从服务器, 多个从服务器之间可以构成一个图状结构;
- Redis使用异步复制。从2.8版本开始,Slave会周期性(每秒一次)发起一个Ack确认复制流(replication stream)被处理进度;
- 复制是非阻塞模式的,这意味着即便是多个Slave执行首次同步时,Master依然可以提供查询服务;如果你在Slave
redis.conf做了设置,Slave在执行首次同步的时候仍可以使用旧数据集提供查询;你也可以配置为当Master与Slave失去联系时,让Slave返回客户端一个错误提示; - 当Slave要删掉旧的数据集,并重新加载新版数据时,Slave会阻塞连接请求(一般发生在与Master断开重连后的恢复阶段);
- 复制功能可以单纯地用于数据冗余(data redundancy),也可以通过让多个从服务器处理只读命令请求来提升扩展性(scalability):
比如说, 繁重的 SORT 命令可以交给附属节点去运行。 - 可以通过修改Master端的redis.conf来避免在Master端执行持久化操作(Save),由Slave端来执行持久化。
- 快照无论在主还是从数据库都起了很大的作用,只要执行复制就会进行快照,无论我们是否开启RDB持久化,无论是否启用RDB,Redis在启动时都会尝试读取dir和dbfilename两个参数指定的rdb文件来恢复数据库。
处理服务器下线
在一个由主服务器和从服务器组成的系统中,主服务器或者从服务器都有可能会下线,但是不同服务器下线带来的影响并不相同:
如果下线的是从服务器,那么整个系统处理读请求的性能将有所下降,但整个系统仍然可以继续处理写请求和读请求,所以这种下线不会导致系统停机;
如果下线的是主服务器,那么整个系统将只能处理读请求而无法处理写请求,导致系统停机。因为在整个系统里面,只有主服务器一个能够处理写请求;
为了让系统能够回到正常上线状态(也即是,让系统中的服务器既能够处理读请求,又能够处理写请求),用户需要向系统中的某一个从服务器发送
SLAVEOF no one 命令,让它变为新的主服务器,并向其他从服务器发送 SLAVEOF 命令,让它们去复制新的从服务器。
现在系统有了新的主服务器,以及一个从服务器,客户端可以继续使用这个系统来处理读请求和写请求了。
因为有一台服务器下线了的缘故,所以重新上线的系统在性能方面可能比不上原有的系统,但这种恢复操作可以避免整个系统停机。(如果不想系统恢复之后的性能被影响,可以添加额外的从服务器,用作冗余服务器。)
虽然上面介绍的方法可以让系统重新上线,但手动来执行这些操作实在太麻烦了,为此,Redis 提供了 Sentinel 程序,用户可以使用Sentinel
来自动检测主从服务器的状态,并在主服务器下线时,自动执行故障转移操作(failover),让系统重新上线。
Comments | NOTHING
该文章已经关闭评论