redis_note_06_主从复制及高可用

单机/单节点/单实例存在的问题

单点故障
容量限制
并发压力

AKF

X: 全量, 镜像(节点的备份/主备)
Y: 按功能/业务拆分数据至多个节点/实例
Z: 对单个功能/业务, 按时间范围/ID范围(或优先级别等逻辑)进行逻辑拆分

以一个系统的数据库(鉴权业务/功能1/功能2/报表业务)为例:
X: 相当于整库的备份(主备)
Y: 相当于将"鉴权业务/功能1/功能2/报表业务"这些业务包含的表, 从1个库中, 拆分至4个库(分库/垂直拆分)
Z: 相当于将"鉴权业务"的用户表按ID拆分至多个库(分表/水平拆分)

解决一个问题, 必然带来其他问题: AKF理论处理了单点问题, 带来了数据一致性问题
强一致性: 通过同步/阻塞方式, 所有节点阻塞直到数据全部都一致, 破坏可用性(CP)
弱一致性: CAP, 通过异步方式, 容忍数据丢失一部分(AP)
最终一致性: BASE, 同步阻塞数据至某个中间件(可靠, 集群, 响应速度够快, 如: kafka), 使得数据最终通过中间件达到最终一致性(将数据同步问题转嫁三方)(AP, 最终C)

一致性( C ) : 在分布式系统中的所有数据备份,值在同一时刻是否相同(不存在绝对一致性, 忽略了网络传输耗时(超过一定距离需独自部署集群))
可用性( A ) : 在集群中一部分节点故障后,集群整体是否还能正确响应客户端的读写请求(返回报错不是可用)
分区容忍性( P ) : 是否容忍多台服务器之间发生网络分区故障(选择P表示发生网络分区依然能正确响应请求), 如果能容忍,意味着发生了分区(脑裂)的情况, 集群保证每台服务器返回的数据一致(如zk: 由1/2以上节点选举出主,主负责修改数据)

redis解决单点问题

通过主从集群方式
主的单点问题, 通过对主做HA(高可用), 自动故障转移, 对于客户端(client), 感知的是一个集群( 一个主节点提供读写服务, 从节点提供读服务, 主节点宕机, 某个从节点可以升级为主节点继续提供读写服务 )

主从复制

伪分布式,同服务器上启动三个节点

#查看是否已启动进程
ps -ef|grep redis
#启动多实例, port分别为6379 6380 6381
cd /opt/redis5/bin
./install_server.sh
#拷贝配置文件
cd ~/
mkdir redis
cd redis
ln /etc/redis/6379.conf 6379.conf
ln /etc/redis/6380.conf 6380.conf
ln /etc/redis/6381.conf 6381.conf
ln /var/log/redis_6379.log redis_6379.log
ln /var/log/redis_6380.log redis_6380.log
ln /var/log/redis_6381.log redis_6381.log
#查看进程, 关闭redis
ps -ef|grep redis
ps -ef | grep "redis" | grep -v grep | awk '{print $2}' | xargs kill -9
#重启redis
redis-server ./6379.conf
redis-server ./6380.conf
redis-server ./6381.conf

连接客户端端进行测试

#多个shell终端
redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381

#在6380客户端输入追随6379
replicaof 127.0.0.1 6379

在6380的日志中可以看到如下信息(主要包含:连接检查,清除当前节点数据,开启同步)
6188:S 31 Aug 2020 22:10:31.384 * Connecting to MASTER 127.0.0.1:6379
6188:S 31 Aug 2020 22:10:31.384 * MASTER <-> REPLICA sync started
6188:S 31 Aug 2020 22:10:31.384 * Non blocking connect for SYNC fired the event.
6188:S 31 Aug 2020 22:10:31.384 * Master replied to PING, replication can continue…
6188:S 31 Aug 2020 22:10:31.385 * Trying a partial resynchronization (request 5425318284dba4cda94764740be05f7de4911a56:1).
6188:S 31 Aug 2020 22:10:31.579 * Full resync from master: d4ed2d7b332d97bd673ae353ce87f78fbce1b65a:0
6188:S 31 Aug 2020 22:10:31.579 * Discarding previously cached master state.
6188:S 31 Aug 2020 22:10:31.579 * MASTER <-> REPLICA sync: receiving 176 bytes from master
6188:S 31 Aug 2020 22:10:31.580 * MASTER <-> REPLICA sync: Flushing old data
6188:S 31 Aug 2020 22:10:31.580 * MASTER <-> REPLICA sync: Loading DB in memory
6188:S 31 Aug 2020 22:10:31.581 * MASTER <-> REPLICA sync: Finished with success

同步测试

#在6379里插入数据
set k1 123
#在6380中查询
get k1
#在6380中写入,发现报错(不允许写)
#(error) READONLY You can't write against a read only replica.
set k2 456

重启测试

#启动6381
redis-server ./6381.conf --replicaof 127.0.0.1 6379
#6379插入数据
set k2 456
#停止6381
ps -ef|grep 127.0.0.1:6381 | grep -v grep | awk '{print $2}' | xargs kill -9
#6379插入数据
set k3 789
set k4 abc
#重启6381
redis-server ./6381.conf --replicaof 127.0.0.1 6379
redis-cli -p 6381
127.0.0.1:6381> keys *
1) "k2"
2) "k1"
3) "k3"
4) "k4"

主节点宕机

#停掉6379
ps -ef|grep 127.0.0.1:6379 | grep -v grep | awk '{print $2}' | xargs kill -9
#发现从节点只还能读取,不能写入, 且日志报错提示
#6188:S 31 Aug 2020 22:32:49.008 * MASTER <-> REPLICA sync started
#6188:S 31 Aug 2020 22:32:49.008 # Error condition on socket for SYNC: Connection refused
#6188:S 31 Aug 2020 22:32:50.015 * Connecting to MASTER 127.0.0.1:6379
#6380停止追随
redis-cli -p 6380
replicaof no one
#日志停止报错,且可读写

主从配置

#从机在同步时,是否允许从节点被查询(主数据传输过来后,flushdb之前)
replica-serve-stale-data yes
#从节点是否只读
replica-read-only yes
#直接通过网络传输rdb
repl-diskless-sync no
#增量复制的队列大小(与增删改操作数量正相关,可确定宕机后数据恢复速度)
repl-backlog-size 1mb
#最少几次/几秒写成功(重试次数/秒)
min-replicas-to-write 3
min-replicas-max-lag 10

redis高可用(HA),哨兵(sentinel)

哨兵先连接主节点,通过主节点的发布订阅功能(psubscribe * 命令查看到有__sentinel__的通道),获取到从节点的信息,再对集群进行监控

# 关闭所有节点
ps -ef | grep "redis" | grep -v grep | awk '{print $2}' | xargs kill -9
# 新增3个监控配置文件
cd ~/redis/
#监控6379
cat >26379.conf<<EOF
#sentinel端口号
port 26379
#监听逻辑mymaster集群,对应ip,port,投票权重值
sentinel monitor mymaster 127.0.0.1 6379 2
EOF

#监控6380
cat >26380.conf<<EOF
#sentinel端口号
port 26380
#监听逻辑mymaster集群,对应ip,port,投票权重值
sentinel monitor mymaster 127.0.0.1 6379 2
EOF

#监控6381
cat >26381.conf<<EOF
#sentinel端口号
port 26381
#监听逻辑mymaster集群,对应ip,port,投票权重值
#一套sentinel可以监控多套redis集群
sentinel monitor mymaster 127.0.0.1 6379 2
EOF

启动实例

ps -ef|grep redis
# 启动主从节点
redis-server ./6379.conf
redis-server ./6380.conf --replicaof 127.0.0.1 6379
redis-server ./6381.conf --replicaof 127.0.0.1 6379

# 启动哨兵监控(redis-server作为sentinel启动,而不是键值对数据库)
redis-server ./26379.conf --sentinel
#对应日志显示:启动了sentinel,发现主节点有两个从节点6380和6381
#38074:X 31 Aug 2020 23:27:32.542 # +monitor master mymaster 127.0.0.1 6379 quorum 2
#38074:X 31 Aug 2020 23:27:32.543 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
#38074:X 31 Aug 2020 23:27:32.557 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379

#在分别启动另外两个监控节点
redis-server ./26380.conf --sentinel
redis-server ./26381.conf --sentinel

#停止主节点
ps -ef|grep 127.0.0.1:6379 | grep -v grep | awk '{print $2}' | xargs kill -9
ps -ef|grep redis

#发现其中一台监控记录了选举过程
#主节点宕机,需要两票选出新节点
39191:X 31 Aug 2020 23:32:09.592 # +sdown master mymaster 127.0.0.1 6379
39191:X 31 Aug 2020 23:32:09.682 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2
#选举出6381作为新节点
39191:X 31 Aug 2020 23:32:09.831 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
#把6381设置为no one, 代替人为操作
39191:X 31 Aug 2020 23:32:09.831 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
#将监控master从6379切换为6381
39191:X 31 Aug 2020 23:32:11.995 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
#将6380设置为6381的从节点
39191:X 31 Aug 2020 23:32:11.995 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
#重新分配集群信息,后续主上线也是6381的从节点
39191:X 31 Aug 2020 23:32:11.995 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
39191:X 31 Aug 2020 23:32:11.995 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
39191:X 31 Aug 2020 23:32:11.995 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
39191:X 31 Aug 2020 23:32:42.029 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381

测试

redis-cli -p 6381
127.0.0.1:6381> set k1 999
OK

redis-cli -p 6380
127.0.0.1:6380> get k1
"999"

上一篇:c++做出游戏巨坑


下一篇:note学习笔记_2