1架构模型


         redis进行主从复制的过程中,基本流程如下所示:

redis架构之主从复制_java


         主从复制表示为replication,在设置从服务器的时候,可以有多个redis从服务器,然后本来是从服务器的又可以设置从服务器。

         在进行redis数据复制的过程中,主服务器先生成数据文件dump.rdb,然后将此数据文件发送给多个请求的从服务器,然后从服务器接收到数据文件之后,载入到内存当中,从而使用。此后从服务器一秒向主服务器发送请求,从而来同步主从服务器之中的数据。

         在其中也可以采用读写分离的机制,在程序使用的过程中,master服务器来负责数据的写入操作,而slave服务器来负责读取的操作,从而更大的提高并发性能。

         使用redis主从复制模型,主要的缺点就是主备不能自动进行切换,每次需要人为的手动干预


2设置

         redis的主从复制模型中,设置相当简单,只要设置一个地方即可,如下所示:

[redisuser@RHANCL redis]$ grep slaveof redis.conf 查看redis的主从配置,如下表示主服务器为172.168.1.77,端口为6379,此服务器为从服务器

# Master-Slave replication. Use slaveof to make aRedis instance a copy of

slaveof 172.168.1.77 6379


3测试

         测试的具体步骤如下所示:

[redisuser@RHAN redis]$ /opt/redis/bin/redis-server/opt/redis/redis.conf 启动redis主服务器

[redisuser@RHAN bin]$ ./redis-cli redis主服务中添加数据

127.0.0.1:6379> set name kel

OK

[redisuser@RHANCL redis]$ /opt/redis/bin/redis-server/opt/redis/redis.conf启动redis从服务器

 

[redisuser@RHAN redis]$ tail -f redis.log主服务器日志

[1919] 26 Mar 01:47:59.666 * Slave 172.168.1.78:6379asks for synchronization

[1919] 26 Mar 01:47:59.666 * Full resync requested by slave 172.168.1.78:6379

[1919] 26 Mar 01:47:59.666 * Starting BGSAVE for SYNCwith target: disk

[1919] 26 Mar 01:47:59.668 * Background saving started by pid 1959

[1959] 26 Mar 01:47:59.698 * DB saved on disk

[1959] 26 Mar 01:47:59.699 * RDB: 6 MB of memory used by copy-on-write

[1919] 26 Mar 01:47:59.769 * Background savingterminated with success

[1919] 26 Mar 01:47:59.769 * Synchronization with slave 172.168.1.78:6379 succeeded

[redisuser@RHAN redis]$ pwd

/opt/redis

[redisuser@RHAN redis]$ ls -l dump.rdb 主服务器的数据文件,数据文件是你在启动redis服务的时候启动的位置生成,从而你可以看到可能很多的数据文件分散在文件系统的各个位置

-rw-rw-r--. 1 redisuser redisuser 30 Mar 26 01:47dump.rdb

         redis主服务日志中可以看到,开始redis从节点请求进行数据同步,然后朱富强响应了从服务器的同步请求,并且启动BGSAVE,启动一个后台进程pid1959将数据用写时复制的技术保存在磁盘中,也就是上面的数据文件dump.rdb,然后将数据文件同步给redis从服务器。

 

[redisuser@RHANCL redis]$ tail -f redis.log从服务器日志

[1940] 26 Mar 01:48:13.826 * Connecting to MASTER 172.168.1.77:6379

[1940] 26 Mar 01:48:13.827 * MASTER <-> SLAVE sync started

[1940] 26 Mar 01:48:13.829 * Non blocking connect for SYNC fired the event.

[1940] 26 Mar 01:48:13.830 * Master replied to PING, replication can continue...

[1940] 26 Mar 01:48:13.832 * Partialresynchronization not possible (no cached master)

[1940] 26 Mar 01:48:13.836 * Full resync from master:d628a933ea9043bedebb9619718059ab60e38b00:1

[1940] 26 Mar 01:48:13.936 * MASTER <-> SLAVEsync: receiving 30 bytes from master

[1940] 26 Mar 01:48:13.937 * MASTER <-> SLAVEsync:Flushing old data

[1940] 26 Mar 01:48:13.937 * MASTER <-> SLAVE sync: Loading DB in memory

[1940] 26 Mar 01:48:13.937 * MASTER <-> SLAVE sync: Finished with success

[redisuser@RHANCL redis]$ pwd

/opt/redis

[redisuser@RHANCL redis]$ ls -l dump.rdb 从服务器的数据文件

-rw-r--r--. 1 redisuser redisuser 30 Mar 26 01:48dump.rdb

         redis从服务器日志可以看到,首先连接上redis的主服务器,然后请求进行sync同步,触发无阻塞的同步事件,然后主服务器响应从服务器PING,表示主服务器可以连接,然后开始复制,从服务器接收到主服务器的数据,清空从服务器老数据,然后将数据文件装载进内存中。

        

         当主服务器数据发生改变时,从服务器日志显示如下:

[1940] 26 Mar 02:15:58.501 *1 changes in 900 seconds. Saving...

[1940] 26 Mar 02:15:58.502 * Background savingstarted by pid 1988

[1988] 26 Mar 02:15:58.533 * DB saved on disk

[1988] 26 Mar 02:15:58.535 * RDB: 6 MB of memory usedby copy-on-write

[1940] 26 Mar 02:15:58.604 * Background savingterminated with success

         可以看到从服务器进行了直接同步,然后在从服务器进行查询数据如下:

[redisuser@RHANCL bin]$ ./redis-cli

127.0.0.1:6379> get name

"kel"

[redisuser@RHAN bin]$ ./redis-cli

127.0.0.1:6379> get name

"kel"

 

127.0.0.1:6379> info (使用info可以查看redis的主从复制,是属于主服务器还是从服务器

# Replication

role:master

connected_slaves:1

slave0:ip=172.168.1.78,port=6379,state=online,offset=2533,lag=1

master_repl_offset:2547

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:2

repl_backlog_histlen:2546

127.0.0.1:6379> info(使用info可以查看redis的主从复制,是属于主服务器还是从服务器

# Replication

role:slave

master_host:172.168.1.77

master_port:6379

master_link_status:up

master_last_io_seconds_ago:4

master_sync_in_progress:0

slave_repl_offset:2701

slave_priority:100

slave_read_only:1

connected_slaves:0

master_repl_offset:0

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

127.0.0.1:6379> set name some从服务器是只读模式,不可写

(error) READONLY You can't write against a read only slave


4crash恢复

         redis发生crash的时候,可能出现mastercrash或者是slave crash,从而分别进行说明。


4.1 master crash 恢复

         手动模拟redismastercrash,如下步骤:

[redisuser@RHAN bin]$ ps -ef|grep redis-server杀死redis master服务

501      1919     1  0 01:45 ?        00:00:00 /opt/redis/bin/redis-server*:6379              

501      2014  1028  0 02:24 pts/1    00:00:00 grep redis-server

[redisuser@RHAN bin]$ kill -9 1919

[redisuser@RHAN bin]$ ps -ef|grep redis-server

501      2016  1028  0 02:24 pts/1    00:00:00 grep redis-server

         此时redis从服务器会出现错误,如下所示:

[redisuser@RHANCL redis]$ tail -3 redis.log slave服务器的错误日志)

[1940] 26 Mar 02:26:05.616 * Connecting to MASTER172.168.1.77:6379

[1940] 26 Mar 02:26:05.617 * MASTER <-> SLAVEsync started

[1940] 26 Mar 02:26:05.617 # Error condition on socket for SYNC: Connection refused

         恢复步骤如下:

[redisuser@RHANCL bin]$ ./redis-cli 取消主从模式,将slave主机变成master主机

127.0.0.1:6379> slaveof no one

OK

         slave主机中日志如下所示,表示slave服务器变成master服务器:

[1940] 26 Mar 02:27:38.783 * Discarding previouslycached master state.

[1940] 26 Mar 02:27:38.783 * MASTER MODE enabled (user request from 'id=4addr=127.0.0.1:29963 fd=6 name= age=19 idle=0 flags=N db=0 sub=0 psub=0multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=slaveof')

        

         master的操作如下:

[redisuser@RHAN redis]$ rm -rf dump.rdb 删除原来的数据文件,其实不删除也行,因为会全部进行重新同步

[redisuser@RHAN redis]$ /opt/redis/bin/redis-server/opt/redis/redis.conf启动redis服务

[redisuser@RHAN redis]$ /opt/redis/bin/redis-cli 进入客户端进行同步数据

127.0.0.1:6379> get name

(nil)

127.0.0.1:6379> slaveof 172.168.1.78 6379 设置从其他redis服务器进行同步数据

OK

127.0.0.1:6379> dbsize确认两者的数据相同

(integer) 2

127.0.0.1:6379> slaveof no one取消主从关系

OK

         slave无武器操作如下:

[redisuser@RHANCL bin]$ ./redis-cli 设置主从关系

127.0.0.1:6379> slaveof 172.168.1.77 6379 将原来的主从关系进行重新设置

OK

127.0.0.1:6379> dbsize

(integer) 2

         谨记不要直接重启redis主服务器,这样会丢失数据,而且slave进行全部重新同步。

 

4.2 slave crash恢复

         slave redis进行恢复的时候,其实没啥好恢复的,因为只要是从服务器启动或者重新启动,都会到master上进行同步,从而不会造成数据丢失,如下所示:

[2038] 26 Mar 02:39:06.667 # Connection with slave 172.168.1.78:6379 lostmaster日志显示丢失slave连接

[redisuser@RHANCL redis]$ /opt/redis/bin/redis-server/opt/redis/redis.conf 启动slave redis服务

[redisuser@RHANCL redis]$ ./bin/redis-cli 检查同步结果

127.0.0.1:6379> dbsize

(integer) 2