Redis-主从同步及哨兵模式

1、Redis 主从同步

Redis主从复制,当用户往Master端写入数据时,通过Redis Sync机制将数据文件发送至Slave,Slave 也会执行相同的操作确保数据一致。同时slave上还可以开启二级slave、三级slave从库,和MySQL的主从类似。 Redis主从配置非常简单,只需要在Redis从库配置中指定slaveof ip port 即可,IP表示指定主库的ip,port表示redis监听端口。

准备机器两台

master:10.0.0.147
slave:10.0.0.149

1.1 配置主从同步

1.1.1 主库配置

# 修改配置文件
bind 0.0.0.0
#以守护进程在后台运行
daemonize yes 
#可选设置认证密码,从库需要指定master的密码才能完成同步
requirepass "123456" 

1.1.2 从库配置

# 修改配置文件设置
bind 0.0.0.0 
# 指定主库 
slaveof 10.0.0.147 6379 
或者 
REPLICAOF 10.0.0.147 6379 
#指定master的认证密码(如果远程服务器设置了密码,则需要认证密码) 
masterauth "123456"

也可在命令行设置,设置完直接生效但重启服务则失效

# 指定主库
slaveof 10.0.0.147 6379 
或者 
REPLICAOF 10.0.0.147 6379 
# 设置master的认证密码 
CONFIG set masterauth 123456 
# 取消主从关系,恢复master身份
SLAVEOF no one

1.1.3 从库查看状态

127.0.0.1:6379> info replication
# Replication
#角色
role:slave
master_host:10.0.0.147
master_port:6379
#主库连接状态必须为up,表示成功
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:1960
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:1eba7a05ef5159b5b2ba02a58571810be5b32230
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1960
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1079
repl_backlog_histlen:882

1.1.4 从库查看状态

10.0.0.147:6379> info replication
# Replication
#角色
role:master
#当前有一个从库连接
connected_slaves:1
#从库信息
slave0:ip=10.0.0.149,port=6379,state=online,offset=2086,lag=0
master_replid:1eba7a05ef5159b5b2ba02a58571810be5b32230
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2086
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2086

1.1.5 从库同步过程日志分析

#连接主库
6190:S 08 Jan 2020 14:44:25.483 * Connecting to MASTER 10.0.0.147:6379
6190:S 08 Jan 2020 14:44:25.483 * MASTER <-> REPLICA sync started
#开始非阻塞同步
6190:S 08 Jan 2020 14:44:25.483 * Non blocking connect for SYNC fired the event.
6190:S 08 Jan 2020 14:44:25.484 * Master replied to PING, replication can continue...
6190:S 08 Jan 2020 14:44:25.485 * Partial resynchronization not possible (no cached master)
#全量同步
6190:S 08 Jan 2020 14:44:25.486 * Full resync from master: 1eba7a05ef5159b5b2ba02a58571810be5b32230:1078
#接收数据
6190:S 08 Jan 2020 14:44:25.526 * MASTER <-> REPLICA sync: receiving 5687 bytes from master
#清空以前缓存的数据
6190:S 08 Jan 2020 14:44:25.526 * MASTER <-> REPLICA sync: Flushing old data
#加载数据库到内存中
6190:S 08 Jan 2020 14:44:25.526 * MASTER <-> REPLICA sync: Loading DB in memory
#同步完成
6190:S 08 Jan 2020 14:44:25.527 * MASTER <-> REPLICA sync: Finished with success

1.1.6 主从同步相关配置解析

扫描二维码关注公众号,回复: 8512145 查看本文章
# 指定主库IP和端口 
replicaof  10.0.0.147  6379 
# 指定主库的认证密码 
masterauth 123456 
# 从库正在复制时,从库可以响应用户读请求,如果设置为no,则返回报错信息 
replica-serve-stale-data yes 
# 设置从库为只读 
replica-read-only yes 
# 启动socket方式复制数据库,master生成rdb文件,不在是先保存到磁盘,然后发给从库。而是直接把 rdb发送给从库,减少了磁盘IO 
repl-diskless-sync yes 
# 配置延时时间,让更多slave加入传输队列,如果复制已经开始,则5秒内,不接受新的slave同步请求 
repl-diskless-sync-delay 5 
# 指定从库定期检查主库状态,默认10秒 
repl-ping-replica-period 10 
# 同步超时时间 repl-timeout 60 
# 是否禁用tcp-nodelay,yes表示禁用,redis会在写缓存积累到一定量之后一起发送,节省带宽,但是会导致master和slave数据延迟,no表示启用,redis会立即发送数据包,即使是很小数据,数据同步会比较快,但是消耗更多带宽 
repl-disable-tcp-nodelay no 
# 设置在同步过程中,写缓冲区的大小,需要考虑到同步的时间和数据的写入速度 
repl-backlog-size 1mb 
# 设置从库的优先级,在主库宕机后,根据优先级选择slave,值越小,则优先级越高,0,表示不参与竞选, 故永远不会被选中
replica-priority 100

1.2 同步策略

1.2.1 全量同步

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:

1)从服务器连接主服务器,发送SYNC命令; 
2)主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令; 
3)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令; 
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照; 
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令; 
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

完成上面几个步骤后就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求。

1.2.2 增量同步

Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

1.2.3 Redis主从同步策略

主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,再要求从机进行全量同步。

1.2.4 集群环境注意项

如果多个Slave重启或者master重启,会因为master_replid不一致导致全量同步,当多个同时出现的时候,可能会导致Master IO剧增而宕机。

2、Redis 哨兵模式

Redis主从虽然解决了单点导致的数据丢失问题,但是没有解决无缝的故障转移,也就是说在主库宕机后,从库无法自动切换为主库,需要手工去切换,在这一瞬间会对后端数据库造成极大的负载,可能直接导致后端数据库宕机。

2.1 哨兵主要作用

监控:监控redis主库及从库运行状态;
通知:如果redis发生故障转移,可以通过邮件通知管理员;
自动故障转移:一旦发现主库宕机,则在从库中通过选举新的master进行故障转移。

2.2 工作原理

哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols) 来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。 每个哨兵(sentinel) 会向其它哨兵(sentinel)、master、slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方宕机了,这就是所谓的”主观认为宕机” (Subjective Down,简称sdown)。若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master真正宕机,即“客观上认为宕机”(Objective Down,简称odown),通过一定的vote算法,从剩下的slave节点中,选一台提升为 master,然后自动修改相关配置。

2.3 哨兵模式配置

准备三台机器

master:10.0.0.147
slave1:10.0.0.148
slave2:10.0.0.149

2.3.1 配置redis主从

修改redis配置文件

# 配置master,开启网卡监听,(可选设置密码)
bind 0.0.0.0
# 配置slave1,指定master
bind 0.0.0.0 
replicaof  10.0.0.147 6379
# 配置slave2,指定master
bind 0.0.0.0 
replicaof  10.0.0.147 6379
# 启动master和slave得redis服务
 /etc/init.d/redis_6379 start

2.3.2 master查看主从状态

10.0.0.147:6379> role
1) "master"
2) (integer) 12544
3) 1) 1) "10.0.0.149"
      2) "6379"
      3) "12544"
   2) 1) "10.0.0.148"
      2) "6379"
      3) "12544"
10.0.0.147:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.0.0.149,port=6379,state=online,offset=12558,lag=1
slave1:ip=10.0.0.148,port=6379,state=online,offset=12558,lag=0
master_replid:1eba7a05ef5159b5b2ba02a58571810be5b32230
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:12558
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:12558

2.3.3 配置哨兵

master端配置哨兵

#从源码包复制出哨兵配置文件
[root@localhost ~]# cp /usr/src/redis-5.0.5/sentinel.conf /usr/local/redis/
#编辑配置
[root@localhost ~]# vim /usr/local/redis/sentinel.conf 

# 绑定监听IP 
bind 0.0.0.0 
# 监听端口 
port 26379 
# 后台运行 
daemonize yes 
pidfile /var/run/redis-sentinel.pid 
# 哨兵的日志文件 
logfile "sentinel.log" 
# 日志文件存放路径 
dir /usr/local/redis/ 
# 设置初始master以及法定认为下线人数 
sentinel monitor mymaster 10.0.0.147 6379 2 
# master主观下线时间,默认30秒,30秒内没有回复pong,则认为下线了 
sentinel down-after-milliseconds mymaster 30000 
# 指定在故障转移期间,多少个slave向新的master同步的数量,如果slave提供查询服务,则应该设置小一点更好
sentinel parallel-syncs mymaster 1 
# 指定故障转移超时时间,默认为3分钟 
sentinel failover-timeout mymaster 180000 
# 设置通知脚本,发生故障转移可以向管理员发送通知(可选) 
#sentinel notification-script mymaster /usr/local/redis/notify.sh 
# 禁止修改脚本,避免脚本重置 sentinel deny-scripts-reconfig yes 

notify.sh 脚本

#!/bin/bash 
#####################
TO="******“@qq.com" 
SUBJECT="redis 发生故障转移" 
CONTEXT="redis 发生故障转移" 
echo -e "$CONTEXT"|mailx -s "$SUBJECT" "$TO"

slave端配置哨兵,直接复制master配置文件即可

scp /usr/local/redis/sentinel.conf 10.0.0.148:/usr/local/redis/
scp /usr/local/redis/sentinel.conf 10.0.0.149:/usr/local/redis/

scp /usr/local/redis/notify.sh 10.0.0.148:/usr/local/redis/
scp /usr/local/redis/notify.sh 10.0.0.149:/usr/local/redis/

master和slave端分别添加权限并启动哨兵

[root@localhost ~]# chmod +x /usr/local/redis/notify.sh 
[root@localhost ~]# /usr/local/redis/bin/redis-sentinel /usr/local/redis/sentinel.conf 

访问哨兵

[root@localhost ~]# /usr/local/redis/bin/redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
#状态ok,主库147,从库2个,哨兵3个
master0:name=mymaster,status=ok,address=10.0.0.147:6379,slaves=2,sentinels=3

干掉主库

[root@localhost redis]# ps -ef|grep redis
root     11736     1  0 18:31 ?        00:00:01 /usr/local/redis/bin/redis-server 0.0.0.0:6379
root     11747     1  0 18:35 ?        00:00:00 /usr/local/redis/bin/redis-sentinel 0.0.0.0:26379 [sentinel]
root     11779  6149  0 18:39 pts/0    00:00:00 grep --color=auto redis
[root@localhost redis]# kill -9 11736

分别查看redis日志和哨兵日志

redis日志

#出现异常
11897:S 09 Jan 2020 18:41:05.549 * Connecting to MASTER 10.0.0.147:6379
11897:S 09 Jan 2020 18:41:05.549 * MASTER <-> REPLICA sync started
11897:S 09 Jan 2020 18:41:05.550 # Error condition on socket for SYNC: Connection refused
11897:S 09 Jan 2020 18:41:06.556 * Connecting to MASTER 10.0.0.147:6379
11897:S 09 Jan 2020 18:41:06.556 * MASTER <-> REPLICA sync started
11897:S 09 Jan 2020 18:41:06.556 # Error condition on socket for SYNC: Connection refused
11897:S 09 Jan 2020 18:41:07.561 * Connecting to MASTER 10.0.0.147:6379
11897:S 09 Jan 2020 18:41:07.561 * MASTER <-> REPLICA sync started
11897:S 09 Jan 2020 18:41:07.562 # Error condition on socket for SYNC: Connection refused
#切换新的master
11897:S 09 Jan 2020 18:41:07.629 * REPLICAOF 10.0.0.149:6379 enabled (user request from 'id=7 addr=10.0.0.148:50432 fd=10 name=sentinel-f171f6ad-cmd age=304 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=285 qbuf-free=32483 obl=36 oll=0 omem=0 events=r cmd=exec')
11897:S 09 Jan 2020 18:41:07.631 # CONFIG REWRITE executed with success.
11897:S 09 Jan 2020 18:41:08.570 * Connecting to MASTER 10.0.0.149:6379
11897:S 09 Jan 2020 18:41:08.570 * MASTER <-> REPLICA sync started
11897:S 09 Jan 2020 18:41:08.570 * Non blocking connect for SYNC fired the event.
11897:S 09 Jan 2020 18:41:08.571 * Master replied to PING, replication can continue...
11897:S 09 Jan 2020 18:41:08.571 * Trying a partial resynchronization (request 78626a53d94d95eaff9f58c693bf7fc40d6cc88c:55143).
11897:S 09 Jan 2020 18:41:08.571 * Successful partial resynchronization with master.
11897:S 09 Jan 2020 18:41:08.572 # Master replication ID changed to bd545fd804a6a992631658d317c8c057e75c92e3
11897:S 09 Jan 2020 18:41:08.572 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.

哨兵日志

10495:X 09 Jan 2020 18:36:07.439 * Running mode=sentinel, port=26379.
10495:X 09 Jan 2020 18:36:07.439 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
10495:X 09 Jan 2020 18:36:07.439 # Sentinel ID is 1fa72ba23f97e66d0c5a33ff4cd2ca33f825c1dc
10495:X 09 Jan 2020 18:36:07.439 # +monitor master mymaster 10.0.0.147 6379 quorum 2
10495:X 09 Jan 2020 18:36:07.440 * +slave slave 10.0.0.148:6379 10.0.0.148 6379 @ mymaster 10.0.0.147 6379
10495:X 09 Jan 2020 18:36:07.441 * +slave slave 10.0.0.149:6379 10.0.0.149 6379 @ mymaster 10.0.0.147 6379
10495:X 09 Jan 2020 18:36:07.529 * +sentinel sentinel 49813b843f450032a6cab1507ab6c142f3801d68 10.0.0.147 26379 @ mymaster 10.0.0.147 6379
10495:X 09 Jan 2020 18:36:07.782 * +sentinel sentinel f171f6adfeee4113a766628ff996a7370c779054 10.0.0.148 26379 @ mymaster 10.0.0.147 6379
# sdown 10.0.0.147主观宕机
10495:X 09 Jan 2020 18:41:07.283 # +sdown master mymaster 10.0.0.147 6379
10495:X 09 Jan 2020 18:41:07.318 # +new-epoch 1
10495:X 09 Jan 2020 18:41:07.320 # +vote-for-leader f171f6adfeee4113a766628ff996a7370c779054 1
# 客观宕机 达到法定人数 3比2 quorum 3/2
10495:X 09 Jan 2020 18:41:07.346 # +odown master mymaster 10.0.0.147 6379 #quorum 3/2
# 开始故障转移
10495:X 09 Jan 2020 18:41:07.346 # Next failover delay: I will not start a failover before Thu Jan  9 18:47:07 2020
10495:X 09 Jan 2020 18:41:07.634 # +config-update-from sentinel f171f6adfeee4113a766628ff996a7370c779054 10.0.0.148 26379 @ mymaster 10.0.0.147 6379
# 切换主库为10.0.0.149
10495:X 09 Jan 2020 18:41:07.634 # +switch-master mymaster 10.0.0.147 6379 10.0.0.149 6379
# 10.0.0.148成为10.0.0.149从库
10495:X 09 Jan 2020 18:41:07.635 * +slave slave 10.0.0.148:6379 10.0.0.148 6379 @ mymaster 10.0.0.149 6379
# 10.0.0.147成为10.0.0.149从库
10495:X 09 Jan 2020 18:41:07.635 * +slave slave 10.0.0.147:6379 10.0.0.147 6379 @ mymaster 10.0.0.149 6379
10495:X 09 Jan 2020 18:41:37.651 # +sdown slave 10.0.0.147:6379 10.0.0.147 6379 @ mymaster 10.0.0.149 6379

查看10.0.0.149,角色切换为master

[root@localhost redis]# /usr/local/redis/bin/redis-cli 
127.0.0.1:6379> role
1) "master"
2) (integer) 115376
3) 1) 1) "10.0.0.148"
      2) "6379"
      3) "115241"

查看哨兵

[root@localhost redis]# /usr/local/redis/bin/redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=10.0.0.149:6379,slaves=2,sentinels=3

重启10.0.0.147,成为从库

127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=10.0.0.149:6379,slaves=2,sentinels=3

补充:哨兵间通过频道订阅的方式进行消息互通,通知最新的主库、从库等信息

[root@localhost redis]# /usr/local/redis/bin/redis-cli
127.0.0.1:6379> pubsub channels
1) "__sentinel__:hello"
127.0.0.1:6379> subscribe __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "10.0.0.148,26379,f171f6adfeee4113a766628ff996a7370c779054,1,mymaster,10.0.0.149,6379,1"
1) "message"
2) "__sentinel__:hello"
3) "10.0.0.149,26379,1fa72ba23f97e66d0c5a33ff4cd2ca33f825c1dc,1,mymaster,10.0.0.149,6379,1"
1) "message"
2) "__sentinel__:hello"
3) "10.0.0.147,26379,49813b843f450032a6cab1507ab6c142f3801d68,1,mymaster,10.0.0.149,6379,1"
发布了34 篇原创文章 · 获赞 1 · 访问量 506

猜你喜欢

转载自blog.csdn.net/weixin_42440154/article/details/103891210