Redis主从复制

| 标签 Redis 

1. 是什么

主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制, Master以写为主,Slave以读为主

2. 能干嘛

  • 读写分离,性能扩展
  • 容灾快速恢复

image.png

3. 怎么玩:主从复制

  • 拷贝多个redis.conf文件include(写绝对路径)
  • 开启daemonize yes
  • Pid文件名字pidfile
  • 指定端口port
  • Log文件名字
  • dump.rdb名字dbfilename
  • Appendonly 关掉或者换名字

    3.1 新建myredis目录,放redis.conf 文件

    [root@AliyunServer ~]# mkdir myredis
    [root@AliyunServer ~]# cd myredis/
    [root@AliyunServer myredis]# cp /etc/redis.conf redis.conf
    [root@AliyunServer myredis]# ls
    redis.conf
    

    3.2 配置一主二仆

    新建redis6379.conf,填写以下内容

    include /myredis/redis.conf
    pidfile /var/run/redis_6379.pid
    port 6379
    dbfilename dump6379.rdb
    

    新建redis6380.conf,填写以下内容

    include /myredis/redis.conf
    pidfile /var/run/redis_6380.pid
    port 6380
    dbfilename dump6380.rdb
    

    新建redis6381.conf,填写以下内容

    include /myredis/redis.conf
    pidfile /var/run/redis_6381.pid
    port 6381
    dbfilename dump6381.rdb
    

    3.3 启动三台redis服务器

    [root@AliyunServer myredis]# redis-server redis6379.conf 
    [root@AliyunServer myredis]# redis-server redis6380.conf 
    [root@AliyunServer myredis]# redis-server redis6381.conf 
    [root@AliyunServer myredis]# ps -ef | grep redis
    root     15948     1  0 18:53 ?        00:00:00 redis-server *:6379
    root     15954     1  0 18:53 ?        00:00:00 redis-server *:6380
    root     15960     1  0 18:53 ?        00:00:00 redis-server *:6381
    root     15966  1432  0 18:53 pts/0    00:00:00 grep --color=auto redis
    

    3.4 查看三台主机运行情况

    info replication 打印主从复制的相关信息

redis6379

[root@AliyunServer myredis]# redis-cli -p 6379
127.0.0.1:6379> info replication
NOAUTH Authentication required.
127.0.0.1:6379> auth 000000
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:1eb5a5251577afa5d4fcf0e24c1e2a006cbaa4ac
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

redis6380

[root@AliyunServer myredis]# redis-cli -p 6380
127.0.0.1:6380> auth 000000
OK
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:7c9792344fb2be59f7c3a4568fb09c0dd5c2b435
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

redis6381

[root@AliyunServer myredis]# redis-cli -p 6381
127.0.0.1:6381> auth 000000
OK
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:35147df3af3e81f16b0eda772fb7795004e989a0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

3.5 配从(库)不配主(库)

slaveof 成为某个实例的从服务器 1、在6380和6381上执行: slaveof 127.0.0.1 6379

redis6380

127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:84
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:7130e8de096108e729930b8f2f403ac55194e3f3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:84
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:84

redis6381

127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:112
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:7130e8de096108e729930b8f2f403ac55194e3f3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:112
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:98

redis6379

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=14,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=14,lag=0
master_failover_state:no-failover
master_replid:7130e8de096108e729930b8f2f403ac55194e3f3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14

2、在主机上写,在从机上可以读取数据 在从机上写数据报错

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"

127.0.0.1:6380> get k1
"v1"

127.0.0.1:6381> get k1
"v1"

127.0.0.1:6381> set k2 v2
(error) READONLY You can't write against a read only replica.

3、主机挂掉,重启就行,一切如初

4、:从机重启需重设:slaveof 127.0.0.1 6379 可以将配置增加到文件中。永久生效。

4. 常用3招

4.1 一主二仆

切入点问题: slave1、slave2是从头开始复制还是从切入点开始复制?比如从k4进来,那之前的k1,k2,k3是否也可以复制? 从机是否可以写?set可否? 主机shutdown后情况如何?从机是上位还是原地待命? 主机又回来了后,主机新增记录,从机还能否顺利复制? 其中一台从机down后情况如何?依照原有它能跟上大部队吗? image.png

演示1:

shutdown掉slave2(6381)

127.0.0.1:6381> SHUTDOWN
not connected> exit
[root@AliyunServer ~]# ps -ef | grep redis
root     16056     1  0 Feb18 ?        00:16:10 redis-server *:6379
root     16062     1  0 Feb18 ?        00:12:08 redis-server *:6380
root     24135 24097  0 15:43 pts/1    00:00:00 redis-cli -p 6379
root     24136 24116  0 15:44 pts/2    00:00:00 redis-cli -p 6380

主机添加数据,slave1查看

127.0.0.1:6379> set a1 v1
OK
127.0.0.1:6379> set a2 v2
OK
127.0.0.1:6379> set a3 v3
OK
127.0.0.1:6379> keys *
1) "a3"
2) "a1"
3) "a2"
4) "k1"

127.0.0.1:6380> keys *
1) "a3"
2) "a1"
3) "a2"
4) "k1"

此时再启动slave2,执行slaveof 127.0.0.1 6379加入集群,观察数据有没有同步

[root@AliyunServer myredis]# redis-server redis6381.conf 
[root@AliyunServer myredis]# redis-cli -p 6381
127.0.0.1:6381> auth 000000
OK
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:fad59dcec9f4d44fdce5ab9ddfce6bfcde2763e7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> KEYS *
1) "k1"
2) "a3"
3) "a2"
4) "a1"

发现数据已经同步!

演示2:

shutdown主机,观察从机是上位还是原地待命

127.0.0.1:6379> SHUTDOWN
not connected> exit
[root@AliyunServer ~]# 

观察从机

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down

127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down

重新启动主机

[root@AliyunServer myredis]# redis-server redis6379.conf 
[root@AliyunServer myredis]# redis-cli -p 6379
127.0.0.1:6379> auth 000000
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=14,lag=1
slave1:ip=127.0.0.1,port=6380,state=online,offset=14,lag=1
master_failover_state:no-failover
master_replid:9c7e4c1bb8eacbaddf987859efdb8bbb6f516dc3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14

127.0.0.1:6379> KEYS *
1) "a1"
2) "a3"
3) "k1"
4) "a2"

观察到其仍是主机,数据也都还在 继续插入数据,观察是否同步

127.0.0.1:6379> set s1 v1
OK
127.0.0.1:6379> set s2 v2
OK
127.0.0.1:6379> set s3 v3
OK
127.0.0.1:6379> KEYS *
1) "s2"
2) "a3"
3) "a1"
4) "a2"
5) "k1"
6) "s3"
7) "s1"

127.0.0.1:6380> KEYS *
1) "s3"
2) "s2"
3) "a1"
4) "a3"
5) "k1"
6) "a2"
7) "s1"

127.0.0.1:6381> KEYS *
1) "s3"
2) "a2"
3) "s2"
4) "k1"
5) "s1"
6) "a3"
7) "a1"

发现数据已经同步!

总结:

1 第一次slave1 和slave2切入点,是全量复制,之后是增量复制 2 主机可以写,但是从机不可以写 3 主机shutdowm后从机待机状态,等主机回来后,主机新增记录从机可以顺利复制 4 从机shutdowm后,每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件

4.2 薪火相传

上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险。

用 slaveof

其他特点与一主二仆一样,主服务挂掉从服务器依然还是从服务器不会上位,主服务器启动后依然是主服务器

缺点: 一旦某个slave宕机,后面的slave都没法备份 主机挂了,从机还是从机,无法写数据了

演示:

slave2变成slave1的从机,观察各个机器的信息

127.0.0.1:6381> slaveof 127.0.0.1 6380
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:2406
slave_priority:100
slave_read_only:1
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=2406,lag=1

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=2434,lag=1
master_failover_state:no-failover

image.png

4.3 反客为主

当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改。

用slaveof no one 将从机变为主机。

演示:

shutdown主机

127.0.0.1:6379> SHUTDOWN
not connected> exit

查看slave1信息

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:down

将slave1变成主机

127.0.0.1:6380> SLAVEOF no one
OK
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover

5. 复制原理

  • Slave启动成功连接到master后会发送一个sync命令(数据同步消息)
  • Master接到命令启动后台的存盘进程(把主服务器数据持久化),同时收集所有接收到的用于修改数据集命令, 在后台进程执行完毕之后,master将传送整个数据文件(rdb文件)到slave,slave拿到rdb文件进行读取,以完成一次完全同步
  • 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
  • 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
  • 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

image.png


上一篇     下一篇