1. 是什么
主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制, Master以写为主,Slave以读为主
2. 能干嘛
- 读写分离,性能扩展
- 容灾快速恢复
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
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后情况如何?依照原有它能跟上大部队吗?
演示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
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,一次完全同步(全量复制)将被自动执行