目录
引言
在现代互联网应用中,高速、可靠的缓存服务是支撑高性能系统的重要支柱。Redis,作为一个流行的内存数据存储系统,以其出色的性能和丰富的数据结构赢得了广泛的青睐。为进一步提升Redis的扩展性和可用性,Redis集群成为了许多大规模应用场景下的理想选择。本文将深入探讨Redis集群的原理以及如何搭建和优化一个Redis集群。
一、Redis集群模式
Redis 提供了多种方式来实现高可用性和数据冗余,其中最为常见的三种分别是主从复制(Replication)、哨兵模式(Sentinel)和集群(Cluster)。
(一)主从复制
1.基本概念及优缺点
Redis主从复制(Replication)是一种数据同步机制,通过它可以实现数据的高可用性和可扩展性。主从复制的基本概念是创建一个或多个从属节点(Slave),它们将复制主节点(Master)的数据和命令执行历史,从而达到数据备份和分布式的目的。
优点
实现了数据的热备份,增强了数据的安全性。
当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复
可以通过从节点提供只读服务,实现读写分离,缓解主节点压力。
缺点
主节点故障后,需要手动切换从节点为主节点。
单纯的主从复制并不能解决多个主节点间的数据一致性问题。
2.主从复制流程
主从复制是基于持久化的方式进行的数据备份,它的实现过程为
1.建立连接
从节点(Slave)通过replicaof参数(通常在/etc/redis/6379.conf配置文件中)指定主节点(Master)的地址和端口,建立起与主节点的连接
主节点在收到从节点的同步请求后,会确认连接并进入复制状态。
2.全量同步
第一次建立复制链接或者主从数据差异过大时,主节点会执行一个BGSAVE操作生成RDB文件,将当前内存中的所有数据以二进制的形式保存到硬盘上。
完成RDB文件生成后,主节点将RDB文件发送给从节点。
从节点接收到RDB文件后,将其载入到自己的内存中,完成数据的全量同步。
3.增量同步
全量同步完成后,主节点会将自从节点开始同步以来的所有写命令发送给从节点。
从节点执行这些命令,逐步更新自己的数据集,以保持与主节点的数据一致
持续复制
在全量同步和增量同步完成后,主节点与从节点进入正常同步状态,主节点将后续的每一次写命令都发送给从节点执行。
从节点会持续监听主节点发来的命令流,并执行这些命令,确保数据实时更新。
(二)哨兵模式
1.基本概念及优缺点
哨兵模式是对主从复制的改进,它通过引入一组哨兵(Sentinel)进程来监控主从节点的健康状态。哨兵之间互相通信并选举领导者,当主节点故障时,哨兵自动进行故障检测和主从切换,无需人工干预。
优点
自动故障转移,提高了系统的可用性。
监控并报告节点健康状态。
缺点
增加了系统复杂度,需要管理哨兵进程。
仍然是主从复制的扩展,不支持数据分片和水平扩展。
2.主要功能
监控
Sentinel系统包含一个或多个Sentinel实例,每个Sentinel都会不断地监控它所配置的所有主服务器(Master)和从服务器(Slave)的运行状态。
Sentinel通过定期向Redis服务器发送ping命令检查其健康状况,并通过info命令获取服务器的信息。
主观下线与客观下线
如果Sentinel无法在一定时间内(可配置)从主服务器得到响应,则认为该主服务器处于主观下线状态。
当足够数量的Sentinel(通常超过配置的一半数量)同意某个主服务器已经下线时,该主服务器会被宣布为客观下线。
自动故障转移
当主服务器客观下线后,Sentinel系统会自动选择一个从服务器作为新的主服务器
选择的过程通常是根据从服务器的优先级、复制偏移量等因素决定,最终选举出的从服务器会被提升为主服务器。
Sentinel会负责修改其他从服务器的配置,使其指向新的主服务器,并完成重新配置的过程。
通知
Sentinel能够通过API通知客户端关于主服务器状态变更的信息,例如主服务器地址的变化,使得客户端可以自动切换到新的主服务器进行读写操作。
同时,也可以通过API提供Redis实例的当前状态报告。
配置中心
Sentinel充当了配置中心的角色,客户端连接到Sentinel获取当前主服务器的地址信息。
在故障转移后,Sentinel会主动推送最新的主服务器地址给已连接的客户端,无需客户端自己去发现和切换。
高可用配置:
为了提高系统的容错能力,通常会部署奇数个Sentinel实例(例如3、5个),确保在部分Sentinel发生故障的情况下,依然可以进行有效的故障判定和转移决策。
(三)Redis 集群
1.基本概念及优缺点
Redis 集群是更高层次的分布式解决方案,它将数据分布在多个节点上,每个节点都可以是主节点,处理一部分槽(Slot)的读写操作。客户端通过CRC16算法计算键所在的槽位,然后将命令发送到对应的节点。
优点
实现了真正的分布式存储,支持数据分片和水平扩展。
提供了自动故障转移和数据恢复功能。
缺点
需要更多的运维复杂度,如数据迁移、扩容缩容等操作。
部分命令在集群模式下不可用,如跨槽操作等。
对客户端有一定的兼容性要求,需要支持集群协议。
2.主要作用
数据分片(Slots): Redis集群将整个数据域划分为16384个槽(编号为0-16383),每个键会通过CRC16算法映射到一个槽上。集群中的每个节点负责一部分槽的键值对。当客户端执行命令时,客户端库或代理会根据键计算槽的位置,并将命令路由到负责该槽的节点。
以3主3从节点组成的集群为例
节点A包含0到5460号哈希槽
节点B包含5461到10922号哈希槽
节点C包含10923到16383号哈希槽
每个Key通过CRC16校验后对16384取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
主从结构: 每个槽有一个主节点负责处理写操作,并将数据同步给一个或多个从节点。这种主从复制机制确保了数据的冗余备份,提高了可用性。
在主从结构中,master节点的主要作用是,提高读写服务,且所有主之间进行信息共享,利用分布式特性,突破存储上限的瓶颈;还可以进行故障转移。而slave节点的主要作用,主要是同步自身master节点的数据信息,只提供读服务,随时准备替代master
同样以3主3从为例
集群中具有A、B、C三个主节点,如果主节点B失败了,整个集群就会因缺少5461-10922这个范围的槽而不可以用。为每个节点添加一个从节点A1、B1、C1整个集群便有三个Master节点和三个slave节点组成,在节点B失败后,集群选举从节点B1为主节点继续服务。当B和B1都失败后,集群将不可用
故障转移与自动修复: 当主节点失效时,集群中的其他节点能够感知并自动进行故障转移(failover)。通过Raft共识算法或Sentinel模式,从节点可以被提升为主节点,继续提供服务。在Sentinel模式下,Sentinel节点监控主从节点的状态,并负责故障转移和通知客户端。
二、实现主从同步
环境准备
Master节点 | 192.168.83.70 |
Slave1节点 | 192.168.83.30 |
Slave2节点 | 192.168.83.40 |
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
(一)配置master节点
bind 0.0.0.0:
#这个配置项表示Redis服务器监听所有网络接口,即允许来自任何IP地址的客户端连接。
daemonize yes
#当设置为 yes 时,Redis将以守护进程(daemon)模式运行,即在后台运行而不是在前台。
#这意味着Redis服务器将在后台一直运行,除非显式地停止它。
logfile /var/log/redis_6379.log
#Redis服务器的日志文件路径设置
dir /var/lib/redis/6379
#Redis的工作目录设置。在这个目录下,Redis会存储持久化数据以及其他可能需要在本地存储的文件
appendonly yes
#这个配置项表示启用Redis的AOF(Append-Only File)持久化方式。
(二)配置slave节点
bind 0.0.0.0:
#这个配置项表示Redis服务器监听所有网络接口,即允许来自任何IP地址的客户端连接。
daemonize yes
#当设置为 yes 时,Redis将以守护进程(daemon)模式运行,即在后台运行而不是在前台。
#这意味着Redis服务器将在后台一直运行,除非显式地停止它。
logfile /var/log/redis_6379.log
#Redis服务器的日志文件路径设置
dir /var/lib/redis/6379
#Redis的工作目录设置。在这个目录下,Redis会存储持久化数据以及其他可能需要在本地存储的文件
replicaof 192.168.83.70 6379
#这个配置项表明当前Redis实例将作为另一个Redis实例(IP地址为192.168.83.70,端口为6379)
#的从节点(replica)。这意味着这个Redis实例将从主节点那里复制数据,并遵循主节点的所有写操
#作,以实现数据的备份和冗余
appendonly yes
#这个配置项表示启用Redis的AOF(Append-Only File)持久化方式。
多台slave服务器同样的配置
三、配置哨兵模式
哨兵模式是基于主从复制的基础之上实现的
环境准备
Master节点 | 192.168.83.70 |
Slave1节点 | 192.168.83.30 |
Slave2节点 | 192.168.83.40 |
(一)启用哨兵模式
修改所有节点服务器的哨兵配置文件,开启哨兵模式
在源码包目录下修改sentinel.conf文件
protected-mode no
#关闭Redis Sentinel的保护模式,允许所有网络接口连接。
#在生产环境中,出于安全考虑,建议配置防火墙规则,只允许授权的客户端连接
port 26379
#设置Redis Sentinel监听的端口号为26379,不同于Redis服务器默认的6379端口,
#避免与主从Redis服务冲突。
daemonize yes
#Sentinel以守护进程(daemon)模式运行,这意味着在后台持续运行,而不是在前台阻塞终端
logfile "/usr/local/redis/log/sentinel.log"
#指定Sentinel的日志文件路径,所有Sentinel的运行日志都将记录到这个文件中
dir /usr/local/redis/6379
#设置Sentinel的工作目录,这个目录主要用于存放Sentinel运行过程中可能产生的临时文件
sentinel monitor mymaster 192.168.83.70 6379 2
#Sentinel监视名为mymaster的主服务器实例,该主服务器的IP地址为192.168.83.70,端口号为6379
#后面的2表示至少需要有2个Sentinel同意主服务器下线(客观下线),才会执行故障转移操作
sentinel down-after-milliseconds mymaster 30000
#设置Sentinel判断mymaster主服务器是否下线的时间阈值为30000毫秒(即30秒)。
#如果在这段时间内Sentinel无法成功与主服务器通信,那么主服务器会被标记为主观下线
sentinel failover-timeout mymaster 180000
#设置在执行故障转移前,Sentinel等待故障转移操作完成的最大时间为180000毫秒(即30分钟)
#如果在这个时间内故障转移还未完成,Sentinel会认为故障转移失败并尝试重新选举
mkdir -p /usr/local/redis/log/
mkdir -p /usr/local/redis/6379
#建立哨兵配置文件中指定的目录文件
cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &
#切换到源码包目录使用redis-sentinel工具,加入&符号,将哨兵放入后台运行
#首先启动master节点,再启用slave节点
使用redis-cli工具,调用数据库的info Sentinel指令,来查看哨兵信息
sentinel_masters:
#显示Sentinel正在监控的主服务器总数,这里是1,即有一个名为mymaster的主服务器正在被监控。
sentinel_tilt
#当Sentinel进入故障状态时,该值会变为1。
sentinel_running_scripts
#正在运行的Sentinel脚本数量,此处为0,意味着当前没有Sentinel脚本正在执行。
sentinel_scripts_queue_length
#Sentinel脚本待执行队列的长度,也是0,表明目前没有待执行的Sentinel脚本。
sentinel_simulate_failure_flags
#Sentinel模拟故障标志位,用于测试目的,0表示没有模拟任何故障。
master0
#这部分详细描述了被监控的主服务器实例信息
name #主服务器的名字,这里是 mymaster。
status #主服务器当前状态,ok 表示主服务器正常运行。
address #主服务器的IP地址和端口号,这里是 192.168.83.70:6379。
slaves #主服务器拥有2个从服务器,正在进行数据复制。
sentinels #监控该主服务器的Sentinel实例数量,这里有3个Sentinel在监控这个主服务器
(二)故障模拟
杀死Master节点上redis-server的进程号
可以在指定的哨兵日志当中查看故障切换的信息
cat /usr/local/redis/log/sentinel.log
使用新的redis服务的master节点添加键值,进行测试
四、实现集群
生产环境中,需要使用6台服务器进行搭建,可以使用单机多实例进行搭建
Master1 | 192.168.83.30:10001 |
Master2 | 192.168.83.30:10002 |
Master3 | 192.168.83.30:10003 |
Master4 | 192.168.83.30:10004 |
Master5 | 192.168.83.30:10005 |
Master6 | 192.168.83.30:10006 |
(一)创建多实例目录
对每个实例创建指定目录,防止配置文件冲突
(二)修改配置文件
#bind 127.0.0.1
#注释此行,表示监听本机的所有网卡,可以通过本机IP地址去建立集群
#如果使用多机配置集群模式,需要取消注释并设置合适的IP地址以便其他节点可以访问。
protected-mode no
#开启了无保护模式,允许所有客户端访问Redis服务器,若在生产环境中,应当谨慎配置访问控制以保证安全。
port 10001
#指定了Redis服务器监听的端口号为10001,集群中的每个节点通常需要使用不同的端口。
daemonize yes
#表示Redis服务器将以守护进程(后台)模式运行,不会阻塞当前的终端。
appendonly yes
#启用了AOF持久化
cluster-enabled yes
#启用了Redis集群模式,该节点将参与Redis集群的构建,与其他节点共享数据和处理请求。
cluster-config-file nodes-10001.conf
#指定了集群节点配置文件的路径和名称,集群节点会将自己的信息写入这个文件,以便于与
#其他节点通信和维护集群状态。
cluster-node-timeout 15000
#设置了集群节点间的超时时间,当集群中某个节点在15000毫秒(15秒)内未响应心跳检测
#或其他通信,集群将认为该节点已下线。这个值应根据网络状况和实际需求进行合理配置。
将修改好的配置文件复制到其它实例的目录下
修改其它实例的监听端口号,并指定集群节点配置文件的路径和名称
将redis执行程序文件与客户端命令工具复制到每个实例的目录下,用于启动不同的实例
启动不同目录下的程序
使用ps命令查看不同实例的进程
(三)启用集群服务
redis-cli
#Redis的命令行客户端工具。
--cluster create
#执行集群创建操作。
127.0.0.1:10001 127.0.0.1:10002 127.0.0.1:10003 127.0.0.1:10004
127.0.0.1:10005 127.0.0.1:10006
#列出了六个Redis实例的地址和端口,每个实例都在本机的不同端口上运行,准备将它们组合成一个集群
#第1、3、5个为master节点。2、4、6为slave节点
--cluster-replicas 1
#表示为集群中的每个主节点分配1个从节点,
#也就是说,总共将创建3个主节点(10001、10003、10005)和
#3个从节点(10002、10004、10006),从节点会复制对应主节点的数据。
查看集群
#上图中的方框代表一主一从节点
(integer) 5461 和 (integer) 10922
#哈希槽的范围
第一个节点信息:主节点
"127.0.0.1":
#节点的IP地址,即本机地址。
(integer) 10002
#节点的端口号,表示该节点监听在10002端口上。
"723d1d87541b688cf817193db3304d81574c180f"
#节点的NodeId,这是一个唯一标识该节点的字符串,用于在集群内部识别和通信。
第二个节点信息:从节点
"127.0.0.1"
#同样也是本机地址。
(integer) 10004
#这个节点监听在10004端口上。
"ef09c11faca633bfdd0638b5246800be92fdfcc8"
#这是另一个节点的NodeId
测试集群
也可以通过cluster keyslot key_name指令查看键的编号
使用kill结束其中一个master节点
使用kiil结束其中一对主从节点
总结
Redis主从复制(Replication)
- 主从模式:一个Redis实例作为主节点(Master),其他实例作为从节点(Slave)。主节点接收所有的写操作,并将命令复制到从节点,实现数据的备份和冗余。
- 数据同步:从节点通过复制主节点的写命令流来更新自己的数据集,初始同步可以采用全量同步(RDB文件)或部分同步(只复制未同步的命令)。
- 读写分离:主节点处理写操作,从节点可以处理只读请求,从而实现读写负载均衡。
- 故障恢复:主节点故障时,需要手动将从节点提升为主节点,并通知客户端切换到新的主节点。
Redis Sentinel(哨兵)
- 监控与故障检测:Sentinel是一套分布式系统,用于监控主从节点的健康状态,当主节点不可达时,自动进行故障检测。
- 自动故障转移:检测到主节点故障后,Sentinel自动触发故障转移流程,选举一个从节点升级为主节点,并通知其他从节点和客户端更新主节点信息。
- 配置中心:Sentinel还能提供配置服务,客户端可以通过Sentinel获得主节点信息,实现动态连接到正确的主节点。
Redis集群(Cluster)
- 数据分片:Redis集群将数据划分为16384个槽(slot),通过哈希槽的方式将数据分散到多个节点,每个节点负责一部分槽的读写操作。
- 分布式存储:集群中的每个节点都是独立的,客户端通过计算键的哈希值将请求路由到相应的节点。
- 主从结构:集群中的每个槽点均有主从节点结构,实现冗余和故障恢复。
- 自动故障转移:当主节点失效时,集群自动进行故障转移,不需要人工干预,新主节点由集群内部选举产生。
- 客户端支持:集群模式下,客户端需支持集群协议,能自动识别并连接到正确节点。
总结而言,Redis主从复制提供了简单的数据备份和读写分离,适用于简单的高可用场景;哨兵模式增加了主节点自动故障检测和转移的功能,进一步提升了系统的自动化程度;而集群模式则通过数据分片实现了水平扩展,能够在更大的数据量和更高的并发请求下提供服务。在实际部署中,可以根据业务需求和规模选择合适的方式进行部署和运维。