前言
  和关系型数据库一样,Redis也有自己的高可用属性,主从复制,相比而言 redis的主从复制的搭建过程更为简单。
一 redis 主从复制的特点
1 同一个master可以拥有多个slaves。
2 master下的Slave还可以接受同一架构中其它slave的链接与同步请求,实现数据的级联复制,即master->slave->Sslave模式;
3 master以非阻塞的方式同步数据至slave,这将意味着master会继续处理一个或多个slave的读写请求;
4 slave端同步数据也可以修改为非阻塞是的方式,当slave在执行新的同步时,它仍可以用旧的数据信息来提供查询;否则,当slave与master失去联系时,slave会返回一个错误给客户端;
5 redis的主从复制具有可扩展性,即多个slave专门提供只读查询与数据的冗余,master端专门提供写操作,实现读写分离,负载均衡;
6通过配置禁用Master数据持久化机制,将其数据持久化操作交给Slaves完成,避免在Master中要有独立的进程来完成此操作。

二 redis 复制的原理以及注意事项
 我们可以从slave redis 的log中查看redis 复制的主要过程

  1. [3308] 24 May 23:09:44.133 * Connecting to MASTER 10.0.2.8:6379
  2. [3308] 24 May 23:09:44.134 * MASTER <-> SLAVE sync started
  3. [3308] 24 May 23:09:44.134 * Non blocking connect for SYNC fired the event.
  4. [3308] 24 May 23:09:44.136 * Master replied to PING, replication can continue...
  5. [3308] 24 May 23:09:44.137 * Partial resynchronization not possible (no cached master)
  6. [3308] 24 May 23:09:44.137 * Full resync from master: 295a0c0dbf70e9b372ebdf6d14b0cae90072ac89:1
  7. [3308] 24 May 23:09:44.143 * MASTER <-> SLAVE sync: receiving 40 bytes from master
  8. [3308] 24 May 23:09:44.144 * MASTER <-> SLAVE sync: Flushing old data
  9. [3308] 24 May 23:09:44.144 * MASTER <-> SLAVE sync: Loading DB in memory
  10. [3308] 24 May 23:09:44.144 * MASTER <-> SLAVE sync: Finished with success
  11. [3308] 24 May 23:24:44.033 * 1 changes in 900 seconds. Saving...
  12. [3308] 24 May 23:24:44.034 * Background saving started by pid 3385
  13. [3385] 24 May 23:24:44.037 * DB saved on disk
  14. [3385] 24 May 23:24:44.038 * RDB: 0 MB of memory used by copy-on-write
  15. [3308] 24 May 23:24:44.134 *

结合redis 主从同步的日志和官方文档,我们总结一下redis的同步过程原理:


1 当一个redis 实例加上slaveof master_ip port 方式启动时,无论是第一次连接还是重连,它会主向master发送一个SYNC command,请求同步连接。


2 当master 收到SYNC 命令之后,发送一个PING 命令给slave ,且在后台执行bgsave命令,将数据快照保存到数据文件中,同时会记录所有修改数据的命令并缓存在数据文件。


3 master后台进程把数据持久化到磁盘之后,就发送数据库文件给slave。


4 slave端将数据文件保存到硬盘上,然后将其在加载到内存中,完成第一次全量同步操作。


5 master会将之前收集到的修改数据的操作和新的修改数据的操作发送给Slave端。


6 slave 收到这些命令之后会在本地执行,类似于MySQL的sql_thread操作。从而达到主从数据最终一致。


7 如果master和slave之间的链接出现断连,slave可以自动重连master。根据版本的不同,断连后同步的方式也不同:


    2.8之前:重连成功之后,一次全量同步操作将被自动执行.


    2.8之后:重连成功之后,进行部分同步操作.


Master持久化功能关闭时Replication的安全性


当我们部署redis主从复制的时候,一般都会强烈建议把master的持久化开关打开。即使为了避免持久化带来的延迟影响,不把持久化开关打开,那么也应该把master配置为不会自动启动的。因为master异常crash后再重启是非常危险的,会导致slave中的数据会被清空。


假设我们有一个redis节点A,设置为master,并且关闭持久化功能,另外两个节点B和C是它的slave,并从A复制数据。


如果A节点崩溃了导致所有的数据都丢失了,它会有重启系统来重启进程。但是由于持久化功能被关闭了,所以即使它重启了,它的数据集是空的。


而B和C依然会通过replication机制从A复制数据,所以B和C会从A那里复制到一份空的数据集,并用这份空的数据集将自己本身的非空的数据集替换掉。于是就相当于丢失了所有的数据。


即使使用一些HA工具,比如说sentinel来监控master-slaves集群,也会发生上述的情形,因为master可能崩溃后迅速恢复。速度太快而导致sentinel无法察觉到一个failure的发生。


部分同步(partial resynchronization ) 这个特殊将会使用PSYNC 命令,注意该命令在2.8之后才支持PSYNC如果一个salve使用的是老的版本仅支持SYNC命令,那么将会用SYNC来同步


无磁盘的复制


通常一个同步需要在磁盘上创建一个RDB文件,然后再重新加载这个文件来进行与slave数据同步


由于磁盘的读写是非常慢的,这对于redis master是一个非常有压力的操作,在2.8.18之后的第一个版来尝试使用无磁盘的复制,在这个设置里了进程直接把RDB 发送到slaves,而不需要使用磁盘来做中间的存储。


需要注意的是 不过这个功能目前处于实验阶段,还未正式发布。


三  部署主从复制


环境 :


rac4 主库 10.0.2.8:6379


rac3 从库 10.0.2.6:6379


1 在两台机器上或者同一台机器起不同的端口,具体步骤请参考《redis 初探》


2 修改rac3 的redis.cnf 添加配置 ,指向rac4


  slaveof 10.0.2.8 6379 


  也可以在rac3上启动redis之后执行


  slaveof 10.0.2.8 6379 


  不过一旦slave重启之后 主从关系就消失了。建议在redis.cnf 配置


3 启动主库和从库


  /usr/local/bin/redis-server /etc/redis/redis.conf


至此 搭建一个以rac4为主库 ,rac3为从库的redis 复制系统。


四 应用案例
主库


  1. root@rac4:~# >redis-cli
  2. .0.0.1:6379> select 0
  3. OK
  4. .0.0.1:6379> set name yangyi
  5. OK
  6. .0.0.1:6379> get name
  7. "yangyi"
  8. .0.0.1:6379>

从库


  1. root@rac3:~# >redis-cli
  2. .0.0.1:6379> select 0
  3. OK
  4. .0.0.1:6379> get name
  5. "yangyi"
  6. .0.0.1:6379>