一、Redis主从复制

info replication
#查看主从复制状态
从节点配置

动态配置

REPLICAOF 192.168.1.1 6379
#配置主节点IP和端口
CONFIG SET masterauth PassWord
#配置主节点密码

配置文件
REPLICATION部分

replicaof 192.168.1.1 6379
masterauth PassWord

配置后重启从节点redis服务。

取消从节点
replicaof no one
#取消从节点

取消后数据还存在,自身的身份变为主节点。

主从复制故障恢复

当slave节点故障时,将redis client指向另一个slave节点。

master_link_status:up
master_last_io_seconds_ago:2
#从节点状态正常

master_link_status:down
master_last_io_seconds_ago:-1
master_link_down_since_seconds:8
#从节点状态错误。

当master节点故障时,需要提升slave为新的master节点。
手动方式
将要提升的从节点断开主从,重新成为主节点;将其他子节点重新指向新提升的主节点。

replicaof no one
#提升从节点

replicaof 192.168.1.1 6379
#从节点重新指向新提升的从节点,密码不变。
级联复制

三级从节点指向二级从节点,二级从节点指向主节点。
二级从节点即是一个从节点,同时也有子节点。
主节点只和一个从节点进行交互,可以降低负载。

主从复制的过程

主从复制分为全量复制和增量复制。
主从同步是非阻塞的,有专门用于注册复制的线程。

  1. 从节点向主节点发送psync指令。
  2. 主节点发送全量同步指令,发送replid号和offset(偏移量)。
  3. 从节点保存 masterinfo (runid和offset)。
  4. 主节点执行bgsave快照并保存。同时如有持续写入数据,将放进buffer中。如果buffer满了就放进RDB文件中。
  5. 发送RDB给从节点。
  6. 发送buffer给从节点。
  7. 从节点清除旧数据。
  8. 从节点加载RDB文件。

从节点断开

  1. 主节点写入buffer区。
  2. 从节点恢复连接,向主节点发送offset和runid。
  3. 主节点向从节点发送增量部分数据。

    如果断开时间过长,buffer存满后会写入RDB中。再次连通则会触发全量复制。
buffer区的大小设置

环形队列

repl-backlog-size 1mb
#buffer区的大小,默认值为1M。
repl-backlog-ttl 3600
#指定时间内若无从节点连接,则backlog size内存空间会被释放,若永不释放则设置为0。

计算公式
repl-backlog-size = 允许从节点断开时长 * 主节点offset每秒写入量
例:master每秒写入量为64MB,最大允许断开60秒,设置buffer空间为3840MB.

避免全量复制
  1. 小主节点即小内存,则全量复制较快。
  2. 节点运行ID不匹配,若主节点重启,runid变化则会触发全量复制。runid变化,从节点认为的新主节点,会清理全部数据,重新全量复制。
  3. 环形队列缓冲区空间不足。
避免复制风暴

单主节点复制风暴
解决方案:级联复制,可减少复制流量。缺点:存在复制延迟。

单机多实例
机器宕机后大量全量复制。
解决方案:主节点分散到多台机器,错开复制。

主从复制优化设置

性能相关配置

repl-diskless-sync no
#是否使用无盘方式同步RDB文件,默认为no。
#RDB文件不保存到磁盘,直接通过网络发送给slave。

repl-diskless-sync-delay 5
#无盘时复制的服务器等待时间

repl-ping-slave-period 10
#slave向master发送ping指令的时间间隔,默认为10秒。

repl-timeout 60
#指定ping连接超时时间,若超过此值,master_link_status变为down,并记录错误日志。

repl-disable-tcp-nodelay no
#是否启用TCP nodelay
#若为yes则redis会将多个小TCP包合并为一个大包再发送,以节约带宽,但会造成延迟。
#若为no则master会立即同步数据。

repl-backlog-size 1mb
#设置环形队列buffer区大小。

repl-backlog-ttl 3600
#超过指定时间无slave连接,则释放buffer内存空间。

slave-priority 100
#slave参选master的优先级,数值越小越高。
#若值为0,则永远不参与选举。

min-reaplicas-to-write 1
#master的可用从节点不能少于此值,否则master将无法执行写入操作。默认为0,生产建议为1。

min-slave-max-log 20
#slave延迟大于此值时,则主节点不能执行写入操作(配合min-reaplicas-to-write配置使用)。
常见主从复制故障

主从配置不同

  1. 主节点内存比从节点大,导致从节点数据溢出。
  2. rename-command命令不一致。例如主节点命令可用,但从节点命令禁用,导致无法同步。提示:未知命令。
  3. master错误:密码错误。
  4. redis版本不一致,4与5差别较大。至少大版本一致。
  5. 安全模式下。redis在保护模式下:既没有设置密码也没有绑定端口(在配置文件中注释掉),则会无法连接。

二、sentinel-哨兵模式

sentinel解决故障转移,同时监控多组主从复制。
sentinel本身也需要多个节点,大于等于3个且正好为奇数。
可以同时监控多组redis组从节点。

故障转移流程

客户端不再直接连接redis,先连接sentinel,再连接sentinel返回的redis节点。

  1. 多个sentinel发现并确认master存在问题。
  2. 选举出一个sentinel作为领导。
  3. 选出一个slave作为master
  4. 通知其余slave成为新matser的slave。
  5. 通知客户端主从变化。
  6. 等待老的master复活成为新master的slave
实现原理

Sentinel是一个分布式系统,运行在多个节点上。Sentinel进程通过流言协议(Gossip protocols)接收关于Master是否下线的状态信息。并使用投票协议(Agreement Protocols)来决定是否执行自动故障转移,并选择合适的Slave作为新的Master。

每个Sentinel进程定时向其他Sentinel、Master、Slave节点发送消息,确认对方是否存活。若发现某个节点在指定时间内未响应,则会认为此节点已离线,即为主观宕机(Subjective Down),简称SDOWN。

如果哨兵集群中的多数Sentinel节点进程认为Master存在SDOWN,共同利用is-master-down-by-addr命令互相沟通后,则认为客观宕机(Objectively Down),简称ODOWN。

接下来利用投票算法,从所有Slave节点中,选一台合适的Slave将之提升为Master节点,然后自动修改其他Slave相关配置,指向新的Master,最终实现故障转移Fallover。

定时任务
  1. 每10秒每个sentinel对master和slave执行info

    • 发现slave节点
    • 确认主从关系。
  2. 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)

    • 通过sentinel_:hello频道交互
    • 交互对节点的看法和自身信息
  3. 每1秒每个sentinel对其他sentinel和redis执行ping
部署哨兵架构

sentinel使用redis相同的程序,使用不同的配置文件,默认监听端口26379。

sentinel配置项

bind 0.0.0.0
port 26379
daemonize yes
pidfile /usr/local/redis/run/redis-sentinel.pid
logfile /usr/local/redis/log/redis-sentinel.log

sentinel monitor mymaster 192.168.1.1 6379
sentinel auth-pass mymaster password

sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
注册systemctl
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target

验证

redis-cli -p 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=192.168.3.60:6379,slaves=2,sentinels=3
手动下线主节点

修改优先级(如果需要)

slave-priority 100

再手动下线主节点

sentinel failover mymaster集群名

切换当前的集群主节点。

应用程序连接sentinel

程序编写时不是直接连接redis,而是使用专门的库连接sentinel。
客户端先连接到sentinel的集合,查询masterName。
sentinel返回master节点,客户端会再次确认返回的redis节点的role。
确定role是master,进行连接。
客户端会订阅节点频道,获取新的主节点变化。

三、redis cluster 集群

分布式集群
数据分布在多个redis主机,同时对外提供服务,提高性能。

早期的解决方案数据分区
客户端分区:人为分区,客户端将数据分别写入。
代理服务:第三方代理实现。

redis3.0后的版本
无中心架构redis cluster,支持多节点并行写入和故障自动转移功能。
用户写入数据,每个master负责不同的槽位区间。

hash slot
16384个槽位
0-16383之间
节点M1 0-5460
节点M2 5461-10922
节点M3 10923-16383

分布方式 顺序分布 哈希分布
数据分散度 分布倾斜 分布散列
顺序访问 支持 不支持

CRC16(key) --> 获得值 --> 值%16384(取模) --> 数值区间

cluster集群部署
bind 0.0.0.0
masterauth password
requirepass password

cluster-enabled yes
#开启集群,开启后进程会有cluster标识。

cluster-config-file nodes-6379.conf
#集群状态文件,记录主从关系即solt范围信息。由reids cluster集群自动创建和维护。

cluster-require-full-coverage no
#设置为no,若cluster的一组节点宕机,剩余的节点继续提供服务。默认为yes,默认情况下整个cluster将不可用。
ps axu|grep redis

redis-server 0.0.0.0:6379 [cluster]
#已启用集群会有cluster标志
建立集群
redis-cli -a password --cluster create 192.168.3.60:6379 192.168.3.61:6379 192.168.3.62:6379 192.168.3.63:6379 192.168.3.64:6379 192.168.3.65:6379 --cluster-replicas 1

执行命令后查看各节点的角色,确认正确后输入yes继续。(在本例子中是3个M节点,3个S节点)

查看cluster信息

cat redis/data/nodes-6379.conf
扩容集群

添加新的主节点

redis-cli -a password --cluster add-node 新节点的ip:端口 现有任一节点ip:端口


redis-cli -a password --cluster add-node 192.168.3.66:6379 192.168.3.60:6379

添加从节点进集群,并同时指定主节点。

redis-cli -a password --cluster add-node 新节点的ip:端口 现有任一节点ip:端口 --cluster-slave --cluster-master-id 欲指定的主节点ID


redis-cli -a password --cluster add-node 192.168.3.67:6379 192.168.3.60:6379 --cluster-slave --cluster-master-id dd6acd798baf8cca87c5c664c8a854a0c04d6b91
重新组织槽位
redis-cli -a password --cluster reshard 192.168.3.60:6379

提问需要移动多少个槽位
4906

提问接收槽位的节点ID
dd6acd798baf8cca87c5c664c8a854a0c04d6b91

提问槽位来源:
all 平均自动转移槽位

或者>>
输入源节点ID

程序列出槽位转移的计划提问是否执行?
执行yes
缩容集群

缩容前转移槽位,需要手动移动多次,平衡地移动到其他主节点上去。

redis-cli -a password --cluster reshard 192.168.3.60:6379

提问需要移动多少个槽位
4906

提问接收槽位的节点ID
dd6acd798baf8cca87c5c664c8a854a0c04d6b91

提问槽位来源:
输入源节点ID

程序列出槽位转移的计划提问是否执行?
执行yes

删除节点

redis-cli -a password --cluster del-node 现有任一节点ip:端口 欲删除节点的ID 


redis-cli -a password --cluster del-node 192.168.3.60:6379 dd6acd798baf8cca87c5c664c8a854a0c04d6b91 

从cluster中删除一个有从节点的主节点后,从节点会重新匹配主节点,形成多从。

导入数据到新cluster集群中

redis-cluster import
1.关闭redis密码

关闭相关全部redis的密码,包括集群和集群外源主机。
redis-cli -h 192.168.0.60 -p 6379 -a password --no-auth-warning CONFIG SET requirepass ""

2.执行导入命令

redis-cli --cluster import <集群服务器IP:PORT> --cluster-from <外部redisIP:PORT>  --cluster-copy --cluster-replace

执行这个导入命令时,如果节点有密码,因为不是交互式的,所以无法验证。需要事先删除密码。

集群偏移

槽位是均匀的,但是数据不一定均匀,因此存在偏移。

redis-cli cluster countkeysinslot <槽位值>
#获取指定槽位的key数量

自动均匀

redis-cli -a password --cluster rebalance 192.168.3.60:6379

列出big key

redis-cli -a password --bigkeys
cluster局限性

1.从节点不能读写。尝试连接从节点时也会被重定向。
2.读写分离复杂,需要手动维护对应关系。
3.不建议在集群模式下构建读写分离,通过增加节点来解决需求。
4.客户端过多性能会降低,因为可能会重定向。
5.部分命令不支持。mget、keys、scan、flush、sinter等
6.不支持多库
7.复制只支持一层
8.key和Lua支持有限,操作的key必须在一个节点上,Lua和事务无法跨节点使用。

标签: Database, Redis

添加新评论