redis 主从master-slave搭建及测试

一、redis主从的特性

 

  1. redis 使用异步复制。从 redis 2.8 开始,slave 也会周期性的告诉 master 现在的数据量。可能只是个机制,用途应该不大。
  2. 一个 master 可以拥有多个 slave,废话,这也是业界的标配吧。

  3. slave 可以接收来自其他 slave 的连接。意思是不是就是说 slave 在接收其他的slave的连接之后成为 master ?答案是 fou,仍然是slave,并不会升级为master

  4. redis 复制在 master 这一端是非阻塞的,也就是说在和 slave 同步数据的时候,master 仍然可以执行客户端的操作命令而不受其影响。这点都不能保证,要你干嘛?
  5. redis 复制在 slave 这一端也是非阻塞的。在配置文件里面有 slave-serve-stale-data 这一项,如果它为 yes ,slave 在执行同步时,它可以使用老版本的数据来处理查询请求,如果是 no ,slave 将返回一个错误。在完成同步后,slave 需要删除老数据,加载新数据,在这个阶段,slave 会阻止连接进来。
  6. Replication can be used both for scalability, in order to have multiple slaves for read-only queries (for example, heavy SORT operations can be offloaded to slaves), or simply for data redundancy.这句话我也没理解什么意思。

  7. 使用复制可以避免 master 因为需要把全部的数据集写入磁盘而造成的开销,因此可以把 master 中 save 配置项全部注释掉,不让它进行保存,然后配置 slave ,让 slave 保存。虽然有这个特性,但是我们好像一般不这么做。

二、

先打开三个终端,然后起三个实例,分别用三个 client 去连接它们:

zhaoguihuadediannao:src zhaogh$ ./redis-server --port 10000 --daemonize yes

zhaoguihuadediannao:src zhaogh$ 

zhaoguihuadediannao:src zhaogh$ ./redis-cli -p 10000

端口10000的做 master。

slave 01:

zhaoguihuadediannao:src zhaogh$ ./redis-server --port 10001 --daemonize yes

zhaoguihuadediannao:src zhaogh$ 

zhaoguihuadediannao:src zhaogh$ ./redis-cli -p 10001

slave 02:

zhaoguihuadediannao:src zhaogh$ ./redis-server --port 10002 --daemonize yes

zhaoguihuadediannao:src zhaogh$ 

zhaoguihuadediannao:src zhaogh$ ./redis-cli -p 10002

上面只是让它们的实例启动了并用客户端去连接它,并没有设置主从关系。在 slave 01 和 slave 02 上执行下面的命令:

127.0.0.1:10001> slaveof 127.0.0.1 10000

OK

127.0.0.1:10001> 

这样就设置好了主从关系。我们来试试有没有效果。

127.0.0.1:10001> get testkey001

(nil)

127.0.0.1:10001> 

这个时候是没有值的。

master 上执行:

127.0.0.1:10000> set testkey001 testvalue001

OK

127.0.0.1:10000> 

然后看看 slave 上有没有:

127.0.0.1:10001> get testkey001

"testvalue001"

127.0.0.1:10001> 

127.0.0.1:10002> get testkey001

"testvalue001"

127.0.0.1:10002> 

有了,是不是比***点读机还 easy ?已经有了感性的认识,我们来介绍一下它的原理吧。

当你设置了主从关系后,slave 在第一次连接或者重新连接 master 时,slave 都会发送一条同步指令给 master ;

master 接到指令后,开始启动后台保存进程保存数据,接着收集所有的数据修改指令。后台保存完了,master 就把这份数据发送给 slave,slave 先把数据保存到磁盘,然后把它加载到内存中,master 接着就把收集的数据修改指令一行一行的发给 slave,slave 接收到之后重新执行该指令,这样就实现了数据同步。

slave 在与 master 失去联系后,自动的重新连接。如果 master 收到了多个 slave 的同步请求,它会执行单个后台保存来为所有的 slave 服务。

一旦 master 和 slave 在失去联系并重新连接上,总是会重新进行一次完整的同步


三、slave  ---master测试

0. 初始情况下各节点info情况(部分有用信息):

MASTER ->
 'connected_slaves': 1,            #可判断slave存活状况
SLAVE  ->
 'master_host': '127.0.0.1',
 'master_last_io_seconds_ago': 5,
 'master_link_status': 'up',       #可判断master与slave存活状况
 'master_port': 6378

1. 正常读写:

In [32]: r1.set('key', 'value')
Out[32]: True

In [34]: r2.get('key')
Out[34]: 'value'

2. 主备正常连接下, 默认slave(不配置slave-read-only on)

向slave写入后发现报错

In [35]: r2.set('key2', 'value')
ReadOnlyError: You can't write against a read only slave

3. Master闪断:

Crash掉主节点:

'master_host': '127.0.0.1',
'master_last_io_seconds_ago': -1,
'master_link_down_since_seconds': 4,
'master_link_status': 'down',
'master_port': 6378

重启主节点后,slave自动从从新建立连接

'master_host': '127.0.0.1',
'master_last_io_seconds_ago': 9,
'master_link_status': 'up',
'master_port': 6378,

4. Crash掉主节点,slave默认(不配置slave-read-only on 情况)

即使master挂掉,slave写入依然报错

SLAVE ->
    'master_host': '127.0.0.1',
    'master_last_io_seconds_ago': -1,
    'master_link_down_since_seconds': 6,
    'master_link_status': 'down',
    'master_port': 6378
    
In [37]: r2.set('key', 'value')
ReadOnlyError: You can't write against a read only slave.

设置slave为readonly,发现报错

zb@ubuntu:~/codes/test$ redis-cli -h 127.0.0.1 -p 6379 set slave-read-only no
(error) READONLY You can't write against a read only slave.

需要关闭slave的slave特性, 将其升级为主节点

zb@ubuntu:~/codes/test$ redis-cli -h 127.0.0.1 -p 6379 slaveof NO ONE
OK
zb@ubuntu:~/codes/test$ redis-cli -h 127.0.0.1 -p 6379 set slave-read-only no
OK

升级为主节点后,继续向slave写入:

In [38]: r2.set('key', 'value')
Out[38]: True

5. 重启master, 如果将slave升级为master, 此时master与slave已经隔离, 都作为主节点存在(注意此时的主节点是没有数据的)

In [41]: r1.get('key')

In [42]: 

6. 拷贝R2的dump数据到R1后重启:

In [43]: r1.get('key')
Out[43]: 'value'

7. 从新将R2设置为R1的slave(slave默认配置):

向slave写入:

In [45]: r2.set('key2', 'value')
ReadOnlyError: You can't write against a read only slave.

8. 如果将slave-read-only 属性写到配置文件中:

可以向slave写入数据,但是不会同步到master

In [50]: r2.set('key2', 'value')
Out[50]: True

9. Crash掉R1,往R2写数据(关掉slave-read-only):

SLAVE ->
    'master_link_status': 'down'

In [75]: r2.set('key2', 'value')
Out[75]: True

重启Master(此时的master无数据):

In [85]: r2.get('key2')

In [86]: r2.get('key3')

可以看到,重启了Master后,slave同步了master状态,由于master没有数据,slave的数据同时被删除

总结(部分测试未写出来):

  • slave 配置为slave-read-only on需要升级为主节点或者写入配置文件中, 而不能在默认slave情况下直接设置
  • master与slave断开后会检测心跳, 从新建立连接.
  • 可以直接copy DUMP文件从新重启master
  • 在Master为空以后,slave同步数据会抹掉全部数据.




你可能感兴趣的:(redis,测试,集群)