Redis --- 哨兵、分片集群

news2024/11/19 13:20:16

一、Redis哨兵

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。

 

1.1、哨兵原理

集群结构和作用


哨兵的结构如图:

 

哨兵的作用如下:

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作

  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主

  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端


集群监控原理


Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

  • 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。


集群故障恢复原理


一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  • 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点

  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举

  • 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高

  • 最后是判断slave节点的运行id大小,越小优先级越高。

当选出一个新的master后,该如何实现切换呢?

流程如下:

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master

  • sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。

  • 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

小结

Sentinel的三个作用是什么?

  • 监控

  • 故障转移

  • 通知

Sentinel如何判断一个redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线

  • 如果大多数sentinel都认为实例主观下线,则判定服务下线

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one

  • 然后让所有节点都执行slaveof 新master

  • 修改故障节点配置,添加slaveof 新master

 

1.2、搭建哨兵集群

集群结构


这里我们搭建一个三节点形成的Sentinel集群,来监管之前的Redis主从集群。如图:

三个sentinel实例信息如下:

节点IPPORT
s1192.168.xxx.xxx27001
s2192.168.xxx.xxx27002
s3192.168.xxx.xxx27003

准备实例和配置


要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。

我们创建三个文件夹,名字分别叫s1、s2、s3:

# 进入/tmp目录
cd /tmp
# 创建目录
mkdir s1 s2 s3

 

然后我们在s1目录创建一个sentinel.conf文件,添加下面的内容:  

port 27001
sentinel announce-ip 192.168.150.101
sentinel monitor mymaster 192.168.150.101 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/s1"

解读:

  • port 27001:是当前sentinel实例的端口

  • sentinel monitor mymaster 192.168.150.101 7001 2:指定主节点信息

    • mymaster:主节点名称,自定义,任意写

    • 192.168.150.101 7001:主节点的ip和端口

    • 2:选举master时的quorum值

然后将s1/sentinel.conf文件拷贝到s2、s3两个目录中(在/tmp目录执行下列命令):

# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf

修改s2、s3两个文件夹内的配置文件,将端口分别修改为27002、27003:

sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf

启动


为了方便查看日志,我们打开3个ssh窗口,分别启动3个redis实例,启动命令:

# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf


测试


尝试让master节点7001宕机,查看sentinel日志:

 

查看7003的日志

 

查看7002的日志:

 

1.3、RedisTemplate

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。

下面,我们通过一个测试来实现RedisTemplate集成哨兵机制。

项目中引入依赖


在项目的pom文件中引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis地址


然后在配置文件application.yml中指定redis的sentinel相关信息:

spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - 192.168.150.101:27001
        - 192.168.150.101:27002
        - 192.168.150.101:27003

配置读写分离


在项目的启动类中,添加一个新的bean:

@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
    return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

这个bean中配置的就是读写策略,包括四种:

  • MASTER:从主节点读取

  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica

  • REPLICA:从slave(replica)节点读取

  • REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master

 

 

二、Redis分片集群

2.1、搭建分片集群

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:

  • 海量数据存储问题

  • 高并发写的问题

使用分片集群可以解决上述问题,如图:

分片集群特征:

  • 集群中有多个master,每个master保存不同数据

  • 每个master都可以有多个slave节点

  • master之间通过ping监测彼此健康状态

  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

集群结构


分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个slave节点,结构如下:

 

这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下:

IPPORT角色
192.168.xxx.xxx7001master
192.168.xxx.xxx7002master
192.168.xxx.xxx7003master
192.168.xxx.xxx8001slave
192.168.xxx.xxx8002slave
192.168.xxx.xxx8003slave

准备实例和配置


创建7001、7002、7003、8001、8002、8003目录:

# 进入/tmp目录
cd /tmp
# 删除旧的,避免配置干扰
rm -rf 7001 7002 7003
# 创建目录
mkdir 7001 7002 7003 8001 8002 8003

在/tmp下准备一个新的redis.conf文件,内容如下:

port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /tmp/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /tmp/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.150.101
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /tmp/6379/run.log

将这个文件拷贝到每个目录下:

# 进入/tmp目录
cd /tmp
# 执行拷贝
echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf

修改每个目录下的redis.conf,将其中的6379修改为与所在目录一致:

# 进入/tmp目录
cd /tmp
# 修改配置文件
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf

启动


因为已经配置了后台启动模式,所以可以直接启动服务:

# 进入/tmp目录
cd /tmp
# 一键启动所有服务
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf

通过ps查看状态:

ps -ef | grep redis

 

如果要关闭所有进程,可以执行命令:

ps -ef | grep redis | awk '{print $2}' | xargs kill

或者(推荐这种方式):

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown

创建集群


虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。

我们需要执行命令来创建集群,在Redis5.0之前创建集群比较麻烦,5.0之后集群管理命令都集成到了redis-cli中。

 

1、Redis5.0之前

Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。因为redis-trib.rb是有ruby语言编写的所以需要安装ruby环境。

# 安装依赖
yum -y install zlib ruby rubygems
gem install redis

然后通过命令来管理集群:

# 进入redis的src目录
cd /tmp/redis-6.2.4/src
# 创建集群
./redis-trib.rb create --replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003

 

2、Redis5.0以后

我们使用的是Redis6.2.4版本,集群管理以及集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003

命令说明:

  • redis-cli --cluster或者./redis-trib.rb:代表集群操作命令

  • create:代表是创建集群

  • --replicas 1或者--cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master

运行后的样子:

 

这里输入yes,则集群开始创建:

  

通过命令可以查看集群状态:

redis-cli -p 7001 cluster nodes


测试


尝试连接7001节点,存储一个数据:

# 连接
redis-cli -p 7001
# 存储数据
set num 123
# 读取数据
get num
# 再次存储
set a 1

 

集群操作时,需要给redis-cli加上-c参数才可以:

redis-cli -c -p 7001

 

 

2.2、散列插槽

插槽原理

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:

数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分

  • key中不包含“{}”,整个key都是有效部分

例如:key是num,那么就根据num计算,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。  

如图,在7001这个节点执行set a 1时,对a做hash运算,对16384取余,得到的结果是15495,因此要存储到103节点。

到了7003后,执行get num时,对num做hash运算,对16384取余,得到的结果是2765,因此需要切换到7001节点

 

小结

Redis如何判断某个key应该在哪个实例?

  • 将16384个插槽分配到不同的实例

  • 根据key的有效部分计算哈希值,对16384取余

  • 余数作为插槽,寻找插槽所在实例即可

如何将同一类数据固定的保存在同一个Redis实例?

  • 这一类数据使用相同的有效部分,例如key都以{typeId}为前缀

 

2.3、集群伸缩

redis-cli --cluster提供了很多操作集群的命令,可以通过下面方式查看:

比如,添加节点的命令:

 

需求分析


需求:向集群中添加一个新的master节点,并向其中存储 num = 10

  • 启动一个新的redis实例,端口为7004

  • 添加7004到之前的集群,并作为一个master节点

  • 给7004节点分配插槽,使得num这个key可以存储到7004实例

这里需要两个新的功能:

  • 添加一个节点到集群中

  • 将部分插槽分配到新插槽


创建新的redis实例


创建一个文件夹:

mkdir 7004

拷贝配置文件:

cp redis.conf /7004

修改配置文件:

sed /s/6379/7004/g 7004/redis.conf

启动

redis-server 7004/redis.conf

添加新节点到redis


添加节点的语法如下:

  

执行命令:

redis-cli --cluster add-node  192.168.150.101:7004 192.168.150.101:7001

通过命令查看集群状态:

redis-cli -p 7001 cluster nodes

如图,7004加入了集群,并且默认是一个master节点:

但是,可以看到7004节点的插槽数量为0,因此没有任何数据可以存储到7004上  


转移插槽


我们要将num存储到7004节点,因此需要先看看num的插槽是多少:

如上图所示,num的插槽为2765.

 

我们可以将0~3000的插槽从7001转移到7004,命令格式如下:

 

具体命令如下:

建立连接:

redis-cli --cluster reshard 192.168.xxx.xxx:7001

得到下面的反馈:  

询问要移动多少个插槽,我们计划是3000个:

新的问题来了:

那个node来接收这些插槽??

显然是7004,那么7004节点的id是多少呢?

复制这个id,然后拷贝到刚才的控制台后:

这里询问,你的插槽是从哪里移动过来的?

  • all:代表全部,也就是三个节点各转移一部分

  • 具体的id:目标节点的id

  • done:没有了

这里我们要从7001获取,因此填写7001的id:

填完后,点击done,这样插槽转移就准备好了:

  

确认要转移吗?输入yes:

然后,通过命令查看结果:

redis-cli -p 7001 cluster node

可以看到:

  

2.4、故障转移

集群初识状态是这样的:

其中7001、7002、7003都是master,我们计划让7002宕机。  

 

2.4.1、自动故障转移

当集群中有一个master宕机会发生什么呢?

直接停止一个redis实例,例如7002:

redis-cli -p 7002 shutdown

1)首先是该实例与其它实例失去连接

2)然后是疑似宕机:

3)最后是确定下线,自动提升一个slave为新的master:

 4)当7002再次启动,就会变为一个slave节点了:  

 

2.4.2、手动故障转移

利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:

 这种failover命令可以指定三种模式:

  • 缺省:默认的流程,如图1~6歩

  • force:省略了对offset的一致性校验

  • takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见

 

案例需求:在7002这个slave节点执行手动故障转移,重新夺回master地位

步骤如下:

1)利用redis-cli连接7002这个节点

2)执行cluster failover命令

如图:

效果:  

 

2.5、RedisTemplate访问分片集群

RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致:

1)引入redis的starter依赖

2)配置分片集群地址

3)配置读写分离

与哨兵模式相比,其中只有分片集群的配置方式略有差异,如下:

spring:
  redis:
    cluster:
      nodes:
        - 192.168.150.101:7001
        - 192.168.150.101:7002
        - 192.168.150.101:7003
        - 192.168.150.101:8001
        - 192.168.150.101:8002
        - 192.168.150.101:8003

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/492197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql 排名与排序

MySQL 8.0 版本新增 两个排名函数 分别是 ROW_NUMBER() 与 RANK() 用法 SELECT ROW_NUMBER() OVER(ORDER BY id) AS rowNo, name FROM users; SELECT RANK() OVER(ORDER BY score DESC) AS rankNo, name, score FROM students;后面跟 OVER&#xff08;&#xff09;括号里…

惠普星 TP01-055ccn电脑重装系统步骤

如果你的惠普星 TP01-055ccn电脑出现了系统问题&#xff0c;或者你想更换一个全新的微软操作系统&#xff0c;自己有不清楚相关的重装系统步骤怎么办&#xff1f;别担心&#xff0c;你可以参考以下的惠普星 TP01-055ccn电脑重装系统步骤来执行。 ​ 惠普星 TP01-055ccn电脑怎…

第1章 .Net7 Areas实现

1 集成路由匹配模式 var builder WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); var app builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { …

【LeetCode】376. 摆动序列

376. 摆动序列 思路 首先&#xff0c;我们可以将摆动序列分为两种&#xff1a; 「上升摆动序列」&#xff0c;当且仅当该序列是摆动序列&#xff0c;且最后一个元素呈上升趋势。如序列 [1,3,2,4] 即为「上升摆动序列」。 「下降摆动序列」&#xff0c;当且仅当该序列是摆动序…

深度解读:《数字孪生世界白皮书(2023)》全方位剖析

2023年初&#xff0c;中国信息通信研究院发布了《数字孪生城市产业图谱研究报告&#xff08;2022&#xff09;》&#xff0c;报告中提出我国数字孪生产业四阶段体系&#xff0c;2020年到2030年是我国数字孪生产业增长期&#xff0c;当前数字孪生市场需求和技术均处于高速发展阶…

腹部肿瘤内科专家朱利明:化疗也能“订制”,晚期结直肠癌不再“无药可救”

肠癌是发生在结肠和直肠的癌症&#xff0c;近二三十年来发病率快速上升。就在近期&#xff0c;“日本女大胃王菅原初代患肠癌病逝”的消息登上热搜&#xff0c;一时引发网友关注热议。 “人生有哲学三问&#xff1a;我是谁&#xff1f;我从哪里来&#xff1f;我到哪里去&#x…

window下sql-server备份后,拷贝到centos上

一.window下sql-server management 打开本地数据库&#xff0c;点备份 二.拷贝到centos下对应目录 mkdir -p /var/opt/mssql/backup 三.在 Linux 上还原数据库 下列步骤使用 sqlcmd 工具。 如果尚未安装 SQL Server 工具&#xff0c;请按照以下步骤安装&#xff1a; ●(1)用…

DJ5-3/4 中断处理程序和设备驱动程序

目录 5.3 中断机构和中断处理程序 5.3.1 中断简介 5.3.2 中断处理程序 5.4 设备驱动程序 5.4.1 设备驱动程序概述 5.4.2 设备驱动程序的处理过程 5.4.3 对 I/O 设备的控制方式 5.3 中断机构和中断处理程序 5.3.1 中断简介 1、中断和陷入 -- CPU 外部事件和内…

基于C++的通讯管理系统

1、系统需求 通讯录是一个可以记录亲人、好友信息的工具。本教程主要利用C来实现-个通讯录管理系统 系统中需要实现的功能如下: ●添加联系人:向通讯录中添加新人&#xff0c;信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人 ●显示联系人:显示通讯录中所有联系…

手把手教你搭建ROS阿克曼转向小车之(增量式PID代码实现)

在上一篇文章中我们已经成功的把编码器的反馈值给计算出来&#xff0c;这篇文章将会讲解怎么使用反馈回来的速度值进行PID计算&#xff0c;从而闭环控制电机的速度。 PID算法介绍 1.开环控制系统 开环控制系统(open-loop control system)是指被控对象的输出(被控制量)对控制器…

【软件开发】从单机到分布式

从单机到分布式 1.单台服务器应用 问题&#xff1a;由于流量越来越大出现服务器性能问题。 2.应用服务器和数据库服务器分离 对架构增加了一台服务器&#xff0c;应用和数据库分别部署到不同的服务器上&#xff0c;对于开发和测试没有任何影响&#xff0c;只需要应用服务器新…

画了个 MSP430F149的最小系统板 开源出来了

使用MSP430F149单片机设计的一个最小系统板&#xff0c;包含晶振电路、复位电路、CH340串口和BSL下载电路、按键和LED电路等&#xff0c;使用了Type-C接口作为供电和串口通信&#xff0c;另外引出了JTAG接口&#xff0c;所有IO口都引出了。 板载了3个按键和LED&#xff0c;可以…

项目范围说明书如何编写?

范围说明书是一份定义了项目范围的所有要素以及假设、项目要求和验收标准的文件。项目范围说明书将作为主要工具&#xff0c;供利益相关者和团队成员参考&#xff0c;并作为准确衡量项目成功的准则。 项目范围说明书是范围管理计划的一部分&#xff0c;包含了管理项目范围的所…

百度智能云联合发布《雄安新区2022年大数据研究报告》

近日&#xff0c;百度智能云、百度研究院商业智能实验室联合发布《未来之城 雄姿初显——雄安新区2022年大数据研究报告》&#xff08;以下简称《报告》&#xff09;&#xff0c;运用人工智能和大数据分析技术&#xff0c;全面呈现过去一年雄安新区在承接疏解、生态治理、城市建…

Golang当中的定时器

定时器 前言定时器的基本使用 前言 在平时写代码的时候&#xff0c;我们经常会遇到在将来某个时间点或者间隔一段时间重复执行函数。这个时候我们就可以考虑使用定时器。本片文章主要介绍一下golang当中的几个常用的定时器。time.Timer,time.Ticker,time.After以及time.AfterF…

文鼎创智能物联云原生容器化平台实践

作者&#xff1a;sekfung&#xff0c;深圳市文鼎创数据科技有限公司研发工程师&#xff0c;负责公司物联网终端平台的开发&#xff0c;稳定性建设&#xff0c;容器化上云工作&#xff0c;擅长使用 GO、Java 开发分布式系统&#xff0c;持续关注分布式&#xff0c;云原生等前沿技…

《安富莱嵌入式周报》第311期:300V可调节全隔离USB PD电源,开源交流负载分析仪,CANFD Trace,6位半多斜率精密ADC设计,开源数学库

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1Hh4y1H7dR 《安富莱嵌入式周报》第311期&#xff1a;300V可调…

【机器学习】决策树算法解读

【机器学习】决策树算法解读 文章目录 【机器学习】决策树算法解读1. 介绍1.1 优缺点1.2 结构1.3 学习过程1.4 决策树与条件概率分布 2. 决策树学习过程2.1 训练策略2.2 特征选择2.2.1 信息增益和条件熵 2.3 决策树的生成2.3.1 ID32.3.2 C4.52.3.3 CART2.3.4 小结 2.4 决策树的…

Nacos配置中心、配置热更新、及配置共享的记录

Nacos除了提供了注册中心的功能,同样也提供了配置中心的功能,用于管理一些叫常改动的配置 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就会让人抓狂&#xff0c;而且很容易出错。我们需要一种统一配置管理方案&#xff0c;可以集中…

计算时间复杂度详解

1&#xff0c;前置知识 我们在计算时间复杂度之前的前置知识是等差数列的通项公式和求和公式以及等比数 列的通项公式和求和公式 等差数列&#xff1a; 通项公式&#xff1a;ana1(n-1)d&#xff08;d是公差&#xff09; 求和公式&#xff1a;Snn(a1an)/2 等比数列&#xf…