redis(五)-集群

参考资料:
redis 4.x cookbook 中文版;
redis官方文档
注: 本文redis的版本为: 5.0.3

redis学习路径

集群:

在互联网应用的系统中,单个redis实例不能提供稳定高效同时具备数据冗余和高可用性能的键值对存储服务;
所以我们通常会对redis进行水平扩展;

  • 哨兵(Sentinel)

由於单个哨兵进程也有可能出现宕机或断连,所以哨兵通常需要存在3个或者更多的进程;当多个哨兵进程检测到主实例的下线,将会通过内部选举,推出一个哨兵进程来将某个从实例进行提升为主实例;

监控与通知:
对redis服务进行监控,以及将故障通知其他程序或管理员;
自动化故障转移:
1.当没有配置哨兵时,在主从复制中,如果主实例挂掉/因意外断连后,需要人工将从实例提升为主实例;
2.配置哨兵后,哨兵会根据各个从实例配置的优先级来进行评选提升;
配置服务提供者:
通过对应的客户端重新配置脚本,可以在每次故障转移后,告诉客户端,新的主机地址;
如何找到监控主实例的从实例:
sentinel会每隔固定时间想主实例发送:info replication命令,获取主实例的从实例详细信息;
如何找到其他sentinel:
所有sentinel在运行后都会每隔固定时间向名为_sentinel_:hello的频道发送sentinel本身信息以及监控的主机信息;因此订阅此频道即可得到所有sentinel的信息;

注意,此处的配置文件不可直接使用;

# 默认情况下,不能从127.0.0.1以外的地方访问redis-sentinel;
# 可以通过bind指定ip;
# 也可以通过 protected-mode no 来禁用保护(意思就是任意地方都可访问)
#
# bind 127.0.0.1 192.168.1.1
#
# protected-mode no

# port <sentinel-port>
# 监听的端口
port 26379

# 是否作为守护进程(如果需要后台运行,选择yes)
daemonize no

# 指定为守护进程后,将在下面指定位置保存pid文件;
pidfile /var/run/redis-sentinel.pid

# 指定哨兵日志的输出文件,如果以空字符串指定,在非守护进程状态时,将进行标准输出(输出到命令行);在守护进程状态运行时,日志将输出到/dev/null中;
logfile ""

# sentinel announce-ip <ip>
# sentinel announce-port <port>
#
# sentinel在进行监控后,会向一个名为 _sentinel_:hello的频道中发送消息,消息的内容包括:哨兵本身的信息,哨兵监控的主实例信息和状态;
# 
# 如果不配置,将会默认发布本地ip和端口;
# 如果只声明ip,那端口会是默认的26379;
# 如果只声明port,那ip会是默认的127.0.0.1;
# 通常情况下配置这里是因为要从外部通过NAT访问,或者是因为docker之类的容器的端口映射导致找不到主从实例或其他哨兵;
# sentinel announce-ip 1.2.3.4

# dir <working-directory>
# 设置工作目录;
dir /tmp

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
#
# 告诉Sentinel监视此主服务器,并仅在至少<quorum>个哨兵同意的情况下,才能将其视为O_DOWN(客观地处于Down)状态.
#
# 判定一个master是否宕机,必须要由仲裁会(所有已知的sentinel)的大部分通过,才能裁定;所以才会需要3个以上的哨兵才能进行裁定;
#
# 主实例的从实例,是由sentinel自行发现,因此不需要配置;
# 注意从实例晋升时,会重写配置文件;
# 所有实例命名应该在标准范围内:A-z 0-9 以及 ".-_".
sentinel monitor mymaster 127.0.0.1 6379 2

# 设定监视的master/slave的连接密码(主从服务都得使用同一个密码)
#
# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd


# 多少毫秒内,master无法应答,则认为是宕机,默认值是30s(30000ms);
sentinel down-after-milliseconds mymaster 30000

# sentinel parallel-syncs <master-name> <numreplicas>
#
# 配置故障转移后,同时与主实例进行同步的从服务数量;
# 故障转移后,某个副本晋升为新的主实例,这时需要进行数据同步,如果我们在主从复制中,设定当主实例暂停服务时,从服务器可以提供旧数据;
# 那么这个值应该设定的尽量小,如果所有从实例都与主实例进行同步,那此时的所有查询都将丢失;
# 虽然设定的值越小,全部同步完成的时间就越长,但是这
sentinel parallel-syncs mymaster 1

# sentinel failover-timeout <master-name> <milliseconds>
#
# 以毫秒为单位指定故障切换超时;如下几种形式都会 用到这个值:
#
# - 对一个已经尝试过故障转移(超时)的主机,进行重新故障转移时,将会耗费两倍于故障转移超时的时间;
#
# - 由于当前哨兵的配置导致将从实例复制到一个错误主实例下后,再强制使用正确的主机对该从实例进行复制;(这个过程所需的时间等于故障转移超时的时间,计算是从哨兵检测到自己配置错误的时刻开始)
#
# - 取消已经在进行晋升的动作(还没有任何副本连接到晋升后的master);(这个过程所需的时间,等于故障转移超时的时间);
#
# - 将所有从实例的主实例配置为本次晋升的新主实例的最长等待时间;(这时间等于故障转移超时的时间,注意,在超过此时间之后,还是一样会进行主从配置,但是进度将不由本配置文件决定);
#
# 默认3分钟(180000 ms)
sentinel failover-timeout mymaster 180000

# SCRIPTS EXECUTION
# 脚本执行
# notification-script(通知脚本) 用于 故障转移后通知系统管理员;
# reconfig-script(重新配置脚本) 用于 故障转移后重新配置客户端;
# 
# 下面是脚本的运行规则:
#
# 如果脚本以"1"退出,则稍后会重试执行(当前最多设置为10次)
#
# 如果脚本以"2"(或更高的值)退出,则不会重试脚本执行.
#
# 如果脚本因为收到信号而终止,则行为与退出代码1相同.
#
# 一个脚本的最长执行时间是60s;超时后江湖被sigkill杀掉,然后重新尝试执行;


# NOTIFICATION SCRIPT(通知脚本)
#
# sentinel notification-script <master-name> <script-path>
#
# 为在警告级别中生成的哨兵事件调用指定的脚本(例如: -sdown, -odown等等);
# 这个脚本应该通过邮件/SMS或其他消息渠道通知管理员;
#
# 这个脚本只有两个传入参数,事件类型,事件描述;
#
# 如果此项配置,必须可执行,否则哨兵启动失败;
# 示例:
sentinel notification-script mymaster /usr/sentinel/script/notification.sh

# CLIENTS RECONFIGURATION SCRIPT(客户端重配置脚本)
#
# sentinel client-reconfig-script <master-name> <script-path>
#
# 故障转移完成后,调用此配置的脚本通知客户端新主机的地址;
# 
# 将会传递如下参数给脚本:
# 主机名称 角色(leader/observer) 状态(始终是failover) from-ip/from-port (指故障转移前的主机地址/端口) to-ip/to-port(指故障转移后的主机地址/端口)
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 这个脚本应该可以进行多线程调用.
#
# 示例:
sentinel client-reconfig-script mymaster /usr/sentinel/script/reconfig.sh

# SECURITY
#
# 默认情况下,哨兵运行后不能修改脚本,可以避免将脚本改为其他某些不可执行文件,从而导致触发故障转移后调用文件出错;
sentinel deny-scripts-reconfig yes

# 重命名命令,可以将主实例及其从实例的某些命令,修改为非常规命令名;
# 下面的意思是:将 mymaster 及其 从实例 的 CONFIG 命令重命名为 guessme
# SENTINEL rename-command mymaster CONFIG GUESSME
#
# 在配置此项后,哨兵在mymaster实例及其从实例上使用config时将以guessme代替
# 也可以使用Sentinel Set在运行时执行此配置.
#
# 要将命令设置回其原始名称(撤消重命名),可以只将命令重命名为其自身:
#
# SENTINEL rename-command mymaster CONFIG CONFIG
# 日志文件位置:
logfile /var/log/redis/sentinel.log

  • redis cluster

redis3.0开始支持的官方集群解决方案

通常一个健壮的redis集群,需要三个主节点,三个从节点;所以我们需要先配置好6个redis;
大致过程:同一个机器上可以启动主从节点,复制redis.conf,修改端口/pid文件名/rdb文件名/日志文件名/aof文件名;复制后的文件可以命名为redis-6379.conf(其实就是用端口作区分);
分别启动这6个主从服务;
然后从实例上执行集群发现命令:

[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.130 6380
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.129 6380
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.129 6379
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.128 6379
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.128 6380
OK

再分配哈希槽给三个主节点:
注意这里如果出现连接失败异常,就需要去关闭centos的防火墙:

#关闭防火墙
[root@localhost bin]# systemctl stop firewalld.service
#取消开机启动防火墙
[root@localhost bin]# systemctl disable firewalld.service
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost bin]# for i in {0..5400}; do redis-cli -h 192.168.50.128 -p 6379 cluster addslots $i; done
OK
OK
...

这里大致说一下,哈希槽是什么:
每个哈希槽里存放了很多的键值对;
我们将哈希槽分配给主节点,存键值对的时候根据算法用key计算出这一次的键值对应该存储于哪一个哈希槽;
redis中有16383个哈希槽,每个主节点负责一部分哈希槽;如果新加入一个主节点,那么必须从之前的主节点中,分出一部分交给新的主节点,这样以确保每个主节点都能接收数据;

分配好哈希槽之后,应声明主从节点关系:

#先获取到当前集群的所有节点信息;第一列是node-id;
[root@localhost bin]# redis-cli -h 192.168.50.129 -p 6379 cluster nodes
23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c 192.168.50.130:6379@16379 master - 0 1592496118000 1 connected 11001-16383
cf05aa186b5ad3a5aa38201648cb5dcdccb42159 192.168.50.129:6380@16380 master - 0 1592496119086 2 connected
ff96cb067229e1ac984dc8ed1e29ab64c32f6bd7 192.168.50.128:6380@16380 master - 0 1592496120094 0 connected
9a2543b264bc93239d8c34f70f2c2ebedc3081eb 192.168.50.128:6379@16379 master - 0 1592496118000 4 connected 0-5400
6c167ad58b9eab89df19b4b458fe7b11492d2b34 192.168.50.129:6379@16379 myself,master - 0 1592496119000 3 connected 5401-11000
e81c63b42150fa81b822f3696401bc1773b65407 192.168.50.130:6380@16380 master - 0 1592496118077 5 connected
#声明一个节点作为另一个节点的从节点;
#redis-cli -h 从节点ip -p 从节点端口 cluster replicate 主节点的node-id;
[root@localhost bin]# redis-cli -h 192.168.50.129 -p 6379 cluster replicate cf05aa186b5ad3a5aa38201648cb5dcdccb42159
(error) ERR To set a master the node must be empty and without assigned slots.
[root@localhost bin]# redis-cli -h 192.168.50.129 -p 6380 cluster replicate 6c167ad58b9eab89df19b4b458fe7b11492d2b34
OK
[root@localhost bin]# redis-cli -h 192.168.50.128 -p 6380 cluster replicate 9a2543b264bc93239d8c34f70f2c2ebedc3081eb
OK
[root@localhost bin]# redis-cli -h 192.168.50.130 -p 6380 cluster replicate 23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c
OK
#从新查看集群节点信息,可以清晰的看到主从关系;
[root@localhost bin]# redis-cli -h 192.168.50.130 -p 6380 cluster nodes
6c167ad58b9eab89df19b4b458fe7b11492d2b34 192.168.50.129:6379@16379 master - 0 1592496683792 3 connected 5401-11000
9a2543b264bc93239d8c34f70f2c2ebedc3081eb 192.168.50.128:6379@16379 master - 0 1592496682785 4 connected 0-5400
ff96cb067229e1ac984dc8ed1e29ab64c32f6bd7 192.168.50.128:6380@16380 slave 9a2543b264bc93239d8c34f70f2c2ebedc3081eb 0 1592496682000 4 connected
e81c63b42150fa81b822f3696401bc1773b65407 192.168.50.130:6380@16380 myself,slave 23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c 0 1592496681000 5 connected
23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c 192.168.50.130:6379@16379 master - 0 1592496681000 1 connected 11001-16383
cf05aa186b5ad3a5aa38201648cb5dcdccb42159 192.168.50.129:6380@16380 slave 6c167ad58b9eab89df19b4b458fe7b11492d2b34 0 1592496681775 3 connected

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章