前言
redis有三种集群模式,其中主从是最常见的模式。Sentinel 哨兵模式是为了弥补主从复制集群中主机宕机后,主备切换的复杂性而演变出来的。哨兵顾名思义,就是用来监控的,主要作用就是监控主从集群,自动切换主备,完成集群故障转移。cluster 模式是redis官方提供的集群模式,使用了Sharding 技术,不仅实现了高可用、读写分离、也实现了真正的分布式存储。
一、主从复制
Redis的主从复制是一种数据复制技术,在主从复制模式中,有一个主节点和多个从节点。主节点负责处理写请求,而从节点则负责处理读请求。这种模式下的数据同步是单向的,即只能从主节点向从节点同步数据。当主节点出现故障时,其中一个从节点可以被提升为新的主节点,以保证服务的持续可用。
代码配置
1. 在application.yml中添加以下配置:
spring:
redis:
master:
url: redis://localhost:6379
slave:
url: redis://localhost:6380
2. Spring Boot集成Redis主从模式的代码示例:
@Configuration
public class RedisConfig {
@Value("${spring.redis.master.url}")
private String masterUrl;
@Value("${spring.redis.slave.url}")
private String slaveUrl;
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration(masterUrl, EnumSet.of(RedisClientConfiguration.Command.SLAVE_READ_ONLY)));
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory());
return template;
}
}
主要作用:
-
数据冗余:通过主从复制,可以实现数据的热备份,增加数据的安全性和可靠性。
-
故障恢复:当主节点出现异常时,可以从节点接管服务,从而快速恢复Redis服务的可用性。
-
负载均衡:结合读写分离,主节点负责写操作,而从节点负责读操作,这样可以分摊服务器负载,特别是在写操作较少的情况下,通过多个从节点分担读负载可以提高Redis服务器的并发能力。
-
高可用性:主从复制作为Redis高可用的基石之一,对于哨兵和集群等高级架构至关重要。
工作原理:
redis 的复制分为两部分操作 同步(SYNC)和 命令传播(command propagate)
-
同步(SYNC)用来将从服务器的状态 更新到 和主服务器 一致。白话文解释就是从服务器主动获取 主服务器的数据。保持数据一致。具体实现是,主服务器收到SYNC命令后,生成RDB快照文件,然后发送给从服务器。
-
命令传播 (command propagate)用于在主服务器数据被修改后,主从不一致,为了让从服务器保持和主服务器状态一致,而做的命令传播。白话文解释就是主服务器收到客户端修改数据命令后,数据库数据发生变化,同时将命令缓存起来,然后将缓存命令发送到从服务器,从服务器通过载入缓存命令来达到主从数据一致。这就是所谓的命令传播。
-
为什么需要有同步和命令传播的两种复制操作:当只有同步操作时候,那么在从服务器向主服务器发送SYNC命令时候,主服务器在生成RDB快照文件时候,仍然会收到客户端的命令修改数据状态,这部分数据如果不能传达给从服务器,那么就会出现主从数据不一致的现象。这时候就出现了命令传播,主服务器收到从服务器的SYNC命令后,生成RDB快照文件同时,将此段时间内收到的命令缓存起来,然后使用命令传播的操作发送从服务器。来达到主从数据一致。
在Redis 2.8版本之前,主从复制是通过全量复制实现的,这通常是一个较重的操作。而在Redis 2.8及其后续版本中,引入了增量复制,这是一种更高效的复制方式,它只在网络中断期间或从节点未及时同步数据时才发送写命令的快照。
总结来说,Redis的主从复制不仅提高了数据安全性,还增强了Redis服务的性能和可靠性。
优缺点
优点:
-
实现读写分离,提高了可用性,解决了单机故障;
-
主从复制期间master和slave都是非阻塞方式,仍然可用;
-
redis主从复制的优点主要是提高了可用性缺点。
缺点:
-
master宕机期间,需要手动切换主机,同时会有部分数据不能及时同步从服务器,造成数据不一致(需要人工手动介入);
-
slave宕机后,多个slave恢复后,大量的SYNC同步会造成master IO压力倍增(可以手动规避启动时间);
-
在线扩容较复杂。
环境搭建
创建redis-cluster目录,然后复制3份redis(也可以一个redis三份不同的配置文件,启动的时候,读取相应的配置文件);
分别修改它们的redis.conf配置文件,如下所示:
redis-6380/redis.conf
port 6380
pidfile /var/run/redis-6380.pid
logfile "redis-6380.log"
dbfilename dump-6380.rdb
daemonize yes
redis-6381/redis.conf
port 6381
pidfile /var/run/redis-6381.pid
logfile "redis-6381.log"
dbfilename dump-6381.rdb
daemonize yes
# 如果不通过修改配置文件,也可以在客户端中输入“SLAVEOF 127.0.0.1 6380”即刻生效!!
# 也可以在客户端中输入“SLAVEOF NO ONE”来断开主从关系
replicaof 127.0.0.1 6380
redis-6382/redis.conf
port 6382
pidfile /var/run/redis-6382.pid
logfile "redis-6382.log"
dbfilename dump-6382.rdb
daemonize yes
replicaof 127.0.0.1 6380
开启3个客户端,来连接这3个redis服务实例;利用ping查看服务是否正常,并且通过info replication查看自己在集群中的角色
二、Sentinel 哨兵模式
哨兵模式是为了解决主从复制集群中主机宕机后,主备切换的复杂性而演变出来的。在这种模式下,有一个或多个哨兵节点,它们的主要作用就是监控主从集群,自动切换主备,完成集群故障转移。
Redis的哨兵模式是一种特殊的高可用解决方案。哨兵能够实时检测master的状态,当master处于故障状态时,哨兵会根据一定的选举算法选出一个新的主节点,并将其他从节点切换到新的主节点上。Redis的哨兵模式中,为了确保其健壮性,至少需要部署3个实例。这三个实例分别扮演不同的角色:主节点、从节点和哨兵节点。
主要功能:
-
集群监控:负责监控 Redis master 和 slave 进程是否正常工作;
-
消息通知:如果某个 Redis 实例出现故障,那么哨兵负责发送消息作为报警通知给管理员;
-
故障转移:如果 master node 挂掉了,会自动转移到 slave node 上;
-
配置中心:如果故障转移发生了,通知 client 客户端习新的 master 地址。
工作原理:
每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)。
如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态。
当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)。
此时就会进行哨兵选举,选出一个领头的哨兵对主从数据库发起故障的修复(就是选一个从数据库作为新的Master)。
在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。
哨兵监控
-
如果 Redis 节点未在 [master-down-after-milliseconds] 指定的时间内,对向它发送 PING 命令的哨兵返回一个有效回复,该哨兵就会将这个服务器标记为下线。
-
当某个哨兵先检测到主节点不可用时,系统并不会马上进行 failover 过程【最终只有一个 sentinel 节点作为 failover 的发起者,就需要选举一个 leader(采用类似 Raft 协议实现选举算法)】。该哨兵会通知其它哨兵,发送 [SENTINEL is-master-down-by-addr] 来询问其他哨兵是否认为主节点的服务器已下线并提议选举自己为领导者哨兵。
-
如果在规定的时间内接收到多个哨兵(哨兵数量大于3且为奇数)的同意时,领导者哨兵产生。
哨兵通知及故障转移
-
领导者哨兵选出一个从节点,并将其升级为主节点。
-
向被选中的从节点发送 SLAVEOF NO ONE 命令,让它转变为主节点。
-
通过发布与订阅功能,将更新后的配置传播给所有其他 Sentinel,其他 Sentinel 对他们自己的配置进行更新。
-
向其他从节点发送 SLAVE OF 命令,让它们去复制新的主节点。
-
当所有的从节点都已经开始复制新的主节点时,领导者哨兵终止此次故障迁移操作。
-
每当一个 Redis 实例被重新配置(reconfigured),无论是被设置成主节点、从节点、又或者被设置成其他主节点的从节点,哨兵都会向被重新配置的实例发送一个 CONFIG REWRITE 命令,从而确保这些配置会持久化到硬盘。
哨兵配置
优缺点
优点:
-
哨兵模式基于主从复制,因此主从复制的优点哨兵都具备;
-
哨兵具备了主从切换和故障转移,因此集群有了更高的可用性。
-
sentinel 哨兵主要用来监控redis主从集群,提高了redis 主从集群的可用性。
缺点:
-
Redis较难支持在线扩容,在线扩容比较复杂。
环境搭建
1. 搭建 1 主 2 从共 3 个节点的 Redis 主从复制节点。
#8000 为主节点端口,8001和8002为对应从节点
8000>./redis-server redis.conf
8001>./redis-server redis.conf
8002>./redis-server redis.conf
2. 新建3个哨兵节点并配置哨兵 sentinel.conf 文件。新建端口为18000、18001、18002 共三个哨兵节点,启动:./redis-sentinel sentinel.conf
bind 127.0.0.1
port 18000 #其他两个分别为 18002、18003
protected-mode no #若想从远程连接redis集群,需要将sentinel的protected-mode修改为no
sentinel myid sentinel-1 #设定sentinel myid 每个都不一样,使用yum安装的时候,直接就生成了
sentinel monitor mymaster 127.0.0.1 8000 2 #数字2,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机。
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
sentinel parallel-syncs mymaster 2
sentinel auth-pass mymaster 123456 #设置用于与主服务器和从服务器进行身份验证的密码
3. 使用 Redis-cli 连接
$redis-cli -h 127.0.0.1 -p 8000 -a 123456
Redis -cli 连接到主库可以执行 set 命令,连接到从库执行 set 命令会有异常提示
(error)READONLY You cant write against a read only save
4. 使用 Jedis.jar 连接 Redis 哨兵
Set<String> sentinels = new HashSet<String>(Arrays.asList(
"127.0.0.1:18000",
"127.0.0.1:18001",
"127.0.0.1:18002"
));
JedisSentinelPool pool = new JedisSentinelPool("mymaster",sentinels,jedisPoolConfig,"123456");
Redis Sentinel是Redis高可用的实现方案。Sentinel是一个管理多个Redis实例的工具,它可以实现对Redis的监控、通知、自动故障转移。
三、Cluster 集群模式
Redis3.0版本之前只支持单例模式,在3.0版本及以后才支持集群 redis集群采用P2P模式,是完全去中心化的,不存在中心节点或者代理节点。
在集群模式下,Cluster实现了分布式存储,数据被分片存储在多个节点上,每个节点负责一部分数据。这种模式下的数据同步是双向的,即可以在各个节点之间进行数据同步。此外,当某个节点出现故障时,其负责的数据可以被其他节点接管,以保证服务的持续可用。
主要作用
1. 数据分区
-
数据分区(或称数据分片)是集群最核心的功能(分布式);
-
集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加,另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力;
-
Redis 单机内存大小受限问题,例如,如果单机内存太大,bgsave 和 bgrewriteaof 的 fork 操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。
2. 高可用
-
集群支持主从复制(模式)和主节点的自动故障转移(与哨兵类似),当任意节点发送故障时,集群仍然可以对外提供服务。
3. 数据分片
-
Redis 集群引入了哈希槽的概念,有 16384 个哈希槽(编号 0~16383);
-
集群的每个节点负责一部分哈希槽,每个 Key 通过 CRC16 校验后对 16384 取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
数据分片原理
redis 数据分片使用的是hash slot, redis集群有16384个哈希槽,每个Key通过CRC16校验后对16384取模来决定放置哪一个槽。
当存取redis key时候,redis会根据CRC16算法得到一个结果,然后把结果和16384求余,通过这个值去对应得节点获取数据。
这个时候,应用客户端实际上只需要连接其中任意一个节点即可,然后Redis Cluster 中每个节点都保存了其他节点得槽信息。这样当存取key计算完槽之后,通过保存槽信息从配置中获取节点信息,然后再去对应得节点获取数据。
综上所述,每个Redis集群理论上最多可以有16384个节点。
复制原理
redis-cluster集群引入了主从复制模型,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点 ping 一个主节点 A 时,如果半数以上的主节点与 A 通信超时,那么认为主节点 A 宕机了。如果主节点 A 和它的从节点 A1 都宕机了,那么该集群就无法再提供服务了。
一致性保存
Redis-Cluster 使用了异步复制:主节点对客户端请求回复状态后,异步发起写操作给从节点,会存在一个时间间隙。
Redis-Cluster 出现网络分区时,当一个客户端与至少包含一个主节点在内的少数节点被孤立,可能导致在节点超时时间(node timeout)内,另一个网络分区内的大部分节点重新选举被孤立主节点的从节点为新的主节点。节点超时时间选项为 cluster-node-timeout 15000(毫秒)。
群集部署
群集部署建议至少3台以上的master节点,建议使用3主3从六个节点的模式。
Cluster 群集由多个redis服务器组成的分布式网络服务群集,群集中有多个master主节点,每个主节点都可读可写,节点之间会互相通信,两两相连,redis群集无中心节点。
1. 新建3主3从 Redis-cluster:6 个 Redis 启动目录,并新建 6 份 Redis 配置文件 redis.conf。并启动 6 个 Redis。
port 8000
cluster-enabled yes
cluster-config-file nodes.conf #集群配置名
cluster-node-timeout 15000
appendonly yes #快照压缩功能开启
2. 配置 Ruby 运行环境:安装 Ruby 及 Ruby-Redis 管理工具(redis 的版本和 ruby 包的版本最好保持一致)
yum install ruby rubygems -y
gem install redis-5.0.4.gem
3. 配置 Redis-Cluster:
使用 redis-trib.rb 的 create 命令创建 Redis-Cluster;
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
根据命令提示输入选项后(输入“yes”),会创建一个新的集群。
选项 replicas 1:表示集群中的每个主节点对应一个从节点,后三个地址为从节点。
四、结语
以上三种模式各有优缺点,可以根据实际情况选择适合的模式来使用Redis。例如,如果对高可用性有较高要求,可以选择哨兵模式或集群模式;如果对性能有较高要求,可以选择主从复制模式。