Redis 集群
本文目录
- Redis 集群
- 1. 主从复制
- 1.1 主从复制简介
- 1.2 高可用集群方案
- 1.3 主从复制工作流程
- 1.3.1 建立连接
- 1.3.2 数据同步
- 1.3.3 命令传播阶段
- 1.4 心跳机制
- 1.5 主从复制的常见问题
- 2. 哨兵模式
- 2.1 哨兵简介
- 2.2 启用哨兵
- 2.3 哨兵工作原理
- 2.3.1 监控阶段
- 2.3.2 通知阶段
- 2.3.3 故障转移阶段
- 3. 集群
- 3.1 集群结构设计
- 3.2 集群搭建
- 3.3 设置与获取数据
- 3.4 主从下线和主从切换
- 3.4.1 slave下线
- 3.4.2 master下线
1. 主从复制
1.1 主从复制简介
单机Redis的问题:
-
机器故障:可能丢数据。
-
容量瓶颈:存不下,硬件有瓶颈。
结论:多台服务器互相复制,实现冗余。
需要解决的问题:如何数据同步。
由主服务器往从服务器复制数据,就叫主从同步。
主服务器
|
|
--------------|--------------
| | |
| | |
slave1 slave2 slave3
master:
- 只写不读。
- 写操作后数据自动同步到slave。
slave:
- 只读不写
1.2 高可用集群方案
- 如果master故障,推选出一台slave当做master。
- 如果master压力过大,可在一个slave下继续接slave,把这个slave当做master。
- 引入哨兵机制,做一个master集群。
好处:
- 读写分离。提高读写能力。
- 负载均衡。
- 故障恢复。
- 数据冗余。实现数据的热备份,是AOF和RDB之外的一个手段。
- 高可用的基石。
1.3 主从复制工作流程
- 建立连接
- 数据同步
- 命令传播
1.3.1 建立连接
-
slave到master的连接。
slaveof ip port
- 如果连通,master会回复masterhost和masterport。
- slave将信息保存下来。
-
建立socket。
- 根据保存的信息连接master的socket。
-
slave通过定时任务发送ping命令。
- master回复pong,证明连接没断。
-
身份验证。
auth password
- Redis不对外提供服务,基本上不需要密码。
-
发送slave端口信息。
replcof listening-port <port-number>
- slave将自己的端口号发给master,master保存下来。
连接方式:
-
方式一:客户端发送命令
slaveof masterIP masterPort
-
方式二: 启动服务器时加上参数
redis-server --slaveof masterIP masterPort
-
方式三: 配置文件中配置master节点信息
slaveof masterIP masterPort
断开方式:
-
从客户端发送命令
slaveof no one
授权访问:
master:
-
master配置文件设置密码
requirepass 密码
-
master客户端发送命令设置密码
config set requirepass 密码
设置密码config get requirepass
获取密码
slave:
-
slave 客户端发送命令设置密码
auto 密码
-
slave配置文件设置密码
masterauth 密码
-
启动客户端时输入密码(访问自己服务端的密码)
redis-cli -a 密码
1.3.2 数据同步
-
请求同步数据
- 刚建立连接时,slave请求把master的所有数据都复制到本机。
psync2
-
master创建rdb同步数据
- master执行
bgsave
。 - master创建了一个复制缓冲区,将新来的数据放进缓冲区。
- master执行
-
slave恢复RDB同步数据(全量复制)
- slave接收rdb文件,并清空自己的数据,执行rdb恢复过程。
- slave发送命令告诉master恢复完成。
-
请求并恢复部分同步数据(增量复制)
- master复制缓冲区信息。
- slave接收信息,执行bgrewriteaof,恢复数据。
数据同步注意事项
-
如果master数据量过大,数据同步阶段应该避开流量高峰期。
-
如果复制缓冲区大小设置的不合理,就会导致数据溢出。如果部分复制发生溢出,那么必须进行第二次全量复制。
repl-backlog-size 1mb
缓冲区默认是1M。 -
master单机内存占用主机内存的比例不应过大,建议50%-70%,剩下的内存用于执行bgsave和创建复制换冲区。
-
为避免slave进行复制时服务器阻塞,建议关闭此时的对外服务。
slave-serve-stale-data yes|no
-
多个slave同时请求数据同步,会占用大量带宽,注意错峰。
-
树状节点时,数据一致性比较差,应该谨慎选择。
1.3.3 命令传播阶段
命令传播阶段会部分复制
- 如果出现了长时间断网:全量复制
- 短时间网络中断:部分中断
服务器运行ID: 识别每一次服务运行时的身份识别码,40位的16进制字符。用来在服务器间发送命令时校验身份。
复制缓冲区: 每次传播命令,master都会将传播的命令记录下来,存储在缓冲区。
- 复制缓冲区是用字符来存储的,拆成AOF那种形式。
- 仅保存影响数据变更的指令,比如set、select等。
偏移量offset: 使用偏移量来确认发送到了哪一个字节。
- master和slave都会记录offset,用来对比复制差异。
- master会保存多个offset,每个slave对应一个。
- slave只保存自己的。
1.4 心跳机制
在命令传播阶段,master与slave间需要进行信息交换,使用心跳机制保持双方在线。
-
master心跳:
- 指令:PING
- 周期: 由
repl-ping-slave-period
决定,默认是10秒。 - 作用:判断slave是否在线。
- 查询:INFO replication 获取slave最后一次连接时间间隔。
-
slave心跳:
- 指令 REPLCONF ACK offset
- 周期 一秒
- 向master汇报自己的复制偏移量,并且判断master是否在线。
注意:
-
当slave多次掉线或者延迟过高,就会被master踢了。
-
min-slaves-to-write 2
最少只剩下2个slave了,就停止写了。
-
min-slaves-max-lag 8
延迟过高,也不写了。
-
-
slave数量和延迟由slave发送REPLCONF ACK命令来确认。
1.5 主从复制的常见问题
- 频繁的全量复制
一旦master重启,runid发生变化,会导致slave全部全量复制。
Redis内部优化方案:
- 会生成一个repl-id和offset。
- 在master关闭时进行RDB持久化,将repl-id和offset保存进RDB文件。
- 重启后将这两个东西恢复回来,使slave以为还是原来的master。
- 断网后slave的offset 越界,触发全量复制。
- 最优的复制缓冲区空间
-
测算master到slave的重连平均时长
-
空间 =
2*second*master每秒钟产生写命令数据总量
-
-
slave收到了慢查询,比如keys *这种命令,导致slave无法响应master,master不停地尝试连接slave,占用了大量资源。
- 合理地设置超时时间,将slave断开。
repl-timeout 60
- 默认60秒
-
master的ping频率低,超时时间短,ping万一丢包了,master就会踢掉slave。
repl-ping-slave-period
- 超时时间至少是ping频率的5-10倍。
-
多个slave数据不同步,网络信息不同步,数据发送有延迟。
- 优化主从机器的网络环境,尽量放在同一个机房。
- 如果延迟非常大,建议暂时关闭slave的对外服务。
slave-serve-stale-data yes|no
- 打开后slave仅响应info,slaveof等少数命令。
- 慎用。
2. 哨兵模式
2.1 哨兵简介
如果master宕机,需要下线master,再选出来一个slave当做master,再通知所有slave。
哨兵是一个分布式系统,用于对主从结构的每台服务器进行监控,当出现问题时通过投票机制来选取新的master。
作用:
- 监控
- 通知
- 自动故障转移
哨兵一般是奇数,3个起。
哨兵也是Redis服务器,只不过不提供数据服务。
2.2 启用哨兵
-
配置文件
sentinel.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
- mymaster是给master起的名字。
- 2的意思是如果有两个哨兵觉得master宕机,那就真的宕机了。一般是所有哨兵的一半+1。
sentinel down-after-milliseconds mymaster 30000
- 主机多少秒没联系就认为宕机
sentinel parallel-syncs mymaster 1
- 挂了之后一次有多少台机器来和新master同步。
sentinel failover-timeout mymaster 180000
- 同步时多久同步完成是有效的。默认180秒同步超时。
-
启动哨兵
redis-sentinel sentinel_port.conf
-
启动顺序
- 启动master。
- 启动slave。
- 启动sentinel。
注意:
- 哨兵启动后,配置文件内会被追加一些自己id和其他哨兵ID和slave的信息。
- 每个哨兵启动后都能互相被其他已经启动的哨兵识别到。
2.3 哨兵工作原理
2.3.1 监控阶段
用于同步各个节点的状态信息。
- 获取各个sentinel的信息。
- 获取master的信息。
- master属性:
- runid
- role
- 各个slave的信息
- master属性:
- 获取所有的slave状态。
- slave属性
- runid
- role
- port
- offset等等。
- slave属性
2.3.2 通知阶段
2.3.3 故障转移阶段
-
如果一个哨兵发现master联不通,就会将其标记为sdown。
-
其他哨兵收到第一个哨兵的通知后,也会去访问master,如果超过配置文件中那个数量的哨兵都确认master宕机,就会将其标记为odown。
-
哨兵们会选举出来一个带头人,内部会有一个投票机制,选定一个哨兵去处理故障转移。
-
选master原则:
- slave在线。
- 响应慢的淘汰。
- 与master断开时间久的踢掉。
- 优先级。
- 优先级
- 偏移量(偏移量小的说明同步的快)
- runid(选id小的)
-
现在就选到了新的master。向新的slave发送slaveof no one。
-
向其他的slave发送slaveof masterIP masterPort。
-
如果原来的master恢复上线后,作为slave连接。
3. 集群
将若干台机器连接在一起,统一对外服务。
3.1 集群结构设计
-
数据存储设计
先对Key进行计算CRC16(key),再对16384取余,得到一个数字,然后存到对应的机器。这个数字,官方叫做槽。增删节点,就是移动槽的位置。
-
集群内部通讯设计
内部节点会互相通讯,了解每个节点有哪些槽。一次命中,直接返回。不命中就查表。所以最多两次就能找到槽。
3.2 集群搭建
配置文件里添加cluster相关配置。
cluster-enabled yes|on
cluster-config-file nodes-端口.conf
cluster-node-timeout 超时下线时间
src文件夹有个命令 redis-trib.rb
,是个ruby脚本。
redis-trib.rb create --replicas 1 master1IP:Port master2IP:Port.....
- 1代表一个master拖一个slave。
- 后面的ip和端口,前面是master,后面是slave。
3.3 设置与获取数据
redis-cli -c
这是集群专用的客户端。一定要加上-c
命令。
3.4 主从下线和主从切换
3.4.1 slave下线
slave对应的master会将slave标记为下线。同时将slave下线的消息发送给集群其他的节点。
slave再次上线后,会与master建立同步,集群其他节点会清除slave的下线状态。
3.4.2 master下线
slave会重连10次,一秒连接一次。
slave会经历一串转变升级为master。
master再次上线后,就会变成slave,去找刚才升级为master的slave同步信息。