【Redis】内存数据库Redis进阶(Redis分片集群)
目录
- 分布式缓存 Redis 四大问题
- 搭建Redis分片集群
- 分片原理
- 散列插槽(插槽原理)
- 集群伸缩
- 需求设定
- 配置集群伸缩
- 故障转移
- 自动故障转移
- 手动故障转移
- RedisTemplate访问分片集群
分布式缓存 Redis 四大问题
基于 Redis 集群解决单机 Redis 存在的四大问题:

主从 和 哨兵 可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:
-
海量数据存储问题
-
高并发写的问题
使用分片集群可以解决上述问题
搭建Redis分片集群
分片集群需要的节点数量较多,这里搭建一个最小的分片集群,包含 3 个 master 节点,每个 master 包含一个 slave 节点,结构图:

在同一台虚拟机中开启 6 个 Redis 实例,模拟分片集群,信息:
| IP | PORT | 角色 |
|---|---|---|
| 192.168.150.101 | 7001 | master |
| 192.168.150.101 | 7002 | master |
| 192.168.150.101 | 7003 | master |
| 192.168.150.101 | 8001 | slave |
| 192.168.150.101 | 8002 | slave |
| 192.168.150.101 | 8003 | slave |
准备实例和配置:
# 进入/tmp目录
cd /tmp
# 删除之前的7001、7002、7003这几个目录,避免配置干扰,重新创建出7001、7002、7003、8001、8002、8003目录
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
虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。需要执行命令来创建集群,在 Redis 5.0 之前创建集群比较麻烦,5.0 之后集群管理命令都集成到了 redis-cli 中。
(1)Redis 5.0之前
Redis 5.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)Redis 5.0以后
使用的是Redis 6.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。


查看集群状态:
redis-cli -p 7001 cluster nodes

测试尝试连接7001节点,存储一个数据:
# 连接
redis-cli -p 7001
# 存储数据
set num 123
# 读取数据
get num
# 再次存储
set a 1# 报错
# (error) MOVED 15495 192.168.150.101:7003
集群操作时,需要给redis-cli加上-c参数才可以:
redis-cli -c -p 7001
# 读取数据
get num
redis-cli
-c参数:连接集群结点时使用,此选项可防止 moved 和 ask 异常。
分片原理
分片集群特征:
-
集群中有多个 master,每个 master 保存不同数据。
-
每个 master 都可以有多个 slave 节点。
-
master 之间通过 ping 监测彼此健康状态。
-
客户端请求可以访问集群任意节点,最终都会被转发到正确节点。
散列插槽(插槽原理)
Redis 会把每一个 master 节点映射到 0~16383 共 16384 个插槽(hash slot)上,查看集群信息时就能看到。


查看集群状态:
redis-cli -p 7001 cluster nodes

数据 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} 为前缀。
集群伸缩
redis-cli --cluster提供了很多操作集群的命令,可以通过redis-cli --cluster help 查看,例如添加节点命令 add-node。
需求设定
向集群中添加一个新的 master 节点,并向其中存储 num = 10
- 启动一个新的 Redis 实例,端口为 7004。
- 添加 7004 到之前的集群,并作为一个 master 节点。
- 给 7004 节点分配插槽,使得 num 这个 key 可以存储到 7004 实例。
这里需要两个新的功能:
- 添加一个节点到集群中。
- 将部分插槽分配到新插槽。
配置集群伸缩
# 创建一个文件夹
mkdir 7004# 拷贝配置文件
cp redis.conf /7004# 修改配置文件
sed /s/6379/7004/g 7004/redis.conf# 启动
redis-server 7004/redis.conf
# 添加节点 add-node: new_host:new_port existing_host:existing_port
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的插槽是多少
192.168.150.101:7003> get num
-> Redirected to slot [2765] located at 192.168.150.101:7001 # num的插槽为 2765
"123"
将 0~3000 的插槽从 7001 转移到 7004
[root@localhost tmp]redis-cli --cluster help
...
reshard host:port--cluster-from <arg>--cluster-to <arg>--cluster-slots <arg>...[root@localhost tmp]redis-cli --cluster reshard 192.168.150.101:7001[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move(from 1 to 16384)? 3000 # 询问要移动多少个插槽,计划是3000个
What is the receiving node ID? # 哪个node来接收这些插槽,配置是7004,那么7004节点的id是多少呢
前面一串就是 7004 节点的 id

继续询问,你的插槽是从哪里移动过来的?
- all:代表全部,也就是三个节点各转移一部分
- 具体的id:目标节点的id
- done:没有了

命令查看结果
# # 通过命令查看集群状态
[root@localhost tmp]redis-cli -p 7001 cluster node

故障转移
之前 7001、7002、7003 都是 master,我们计划让 7002 宕机。
自动故障转移
# 直接停止一个redis实例,例如7002
redis-cli -p 7002 shutdown
-
首先是该实例与其它实例失去连接
-
然后是疑似宕机

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

-
当 7002 再次启动,就会变为一个 slave 节点

手动故障转移
&emsp利用 cluster failover 命令可以手动让集群中的某个 master 宕机,切换到执行 cluster failover 命令的这个 slave 节点,实现无感知的数据迁移。

这种 failover 命令可以指定三种模式:
- 缺省:默认的流程,如图 1~6 步。
- force:省略了对 offset 的一致性校验。
- takeover:直接执行第 5 步,忽略数据一致性、忽略 master 状态和其它 master 的意见。
例子:在 7002 这个 slave 节点执行手动故障转移,重新夺回 master 地位
步骤如下:
- 利用 redis-cli 连接7002这个节点
- 执行
cluster failover命令
redis-cli -p 7002
> cluster failover
OK

RedisTemplate访问分片集群
RedisTemplate 底层同样基于 lettuce 实现了分片集群的支持,而使用的步骤与哨兵模式基本一致。
【Redis】内存数据库Redis进阶(Redis哨兵集群)
- 引入 Redis 的 starter 依赖
- 配置分片集群地址
- 配置读写分离
与哨兵模式相比,其中只有分片集群的配置方式略有差异
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
相关文章:
【Redis】内存数据库Redis进阶(Redis分片集群)
目录 分布式缓存 Redis 四大问题搭建Redis分片集群分片原理散列插槽(插槽原理)集群伸缩需求设定配置集群伸缩 故障转移自动故障转移手动故障转移 RedisTemplate访问分片集群 分布式缓存 Redis 四大问题 基于 Redis 集群解决单机 Redis 存在的四大问题&a…...
替代LT8711龙讯替代RTD2172 CS5265中文规格书4K60HZ转接线 设计Type-C转HDMI2.0高清投屏方案
龙迅LT8711是一款Type-C/DP1.2 to HDMI2.0方案芯片,北京集睿致远(ASL)推出的CS5265可以完全代替LT8711UX,封装尺寸比LT8711UX小的同时,CS5265的芯片集成度高,内置MCU,内置lLDO等,CS5…...
HCIA-datacom数通题库和录播视频资料
HCIA-Datacom,是华为数通认证的初级考试,培训与认证具备数通基础通用知识和技能水平的工程师,只是入门了解数通的一些基础通用知识,适用于小白了解和学习数通知识点起点。 个人建议还是有必要考的,如果在企业考试考试…...
优思学院|质量工程师应具备什么能力?
质量工程师是一个需要耐心、细心、坚持态度、沟通能力、协调能力的工作,更需要持续学习强化自身的专业知识。 质量工程师负责审核、客户投诉的调查、过程的改进以达到质量之提升,他們也必须要预警生产线风险、质量异常,并且协调不同的部門一…...
数据分析 VS 数据可视化:决战时刻
数据分析和数据可视化是数据科学领域中两个重要的组成部分,很多人不明白两者之间的关系,会误认为是一个东西,其实不然。本文就带大家简单了解一下它们的区别与联系吧! 数据分析是指通过收集、处理和解释数据来获取有关特定问题或…...
Vue3中无法为el-tree-select设置反选问题分析
环境:Vue3.2、Element Plus 问题:子组件 setting.vue > 弹窗组件 Dialog > 树选择组件el-tree-select ,无法设置默认选中项 default-checked-keys 场景:在一个后台系统的列表页,选中一行数据,点击设置…...
Redis - 缓存持久化
Redis 的缓存持久化有两种技术 : RDB 和 AOF RDB Redis 的数据快照 简单说就是将缓存中的所有数据都记录到磁盘中,当Redis发生故障的时候,只需读取快照文件,就可恢复数据 相应的命令是 save 和 bgsave ,这两个命名…...
Pandas进阶修炼120题-第三期(金融数据处理,51-80题)
目录 往期内容:第一期:Pandas基础(1-20题)第二期:Pandas数据处理(21-50题) 第三期 金融数据处理51.使用绝对路径读取本地Excel数据方法一:双反斜杠绝对路径方法二:r 拓展…...
3、HAproxy高级配置
基于cookie的会话保持 在 HAProxy 中,可以通过使用 cookie 配置来实现基于 Cookie 的会话保持。cookie 配置用于配置与会话保持相关的选项,允许您定义要在HTTP响应中插入或重写的Cookie以及其他与Cookie会话保持相关的参数。 以下是一些常用的 cookie 配…...
tcpdump网络抓包工具的使用
tcpdump 是一款用在linux系统上的网络抓包工具 1、 基本语法 tcpdump 的常用参数如下: tcpdump -i eth0 -nn -s0 -v port 80-i : 选择要捕获的接口,通常是以太网卡或无线网卡,也可以是 vlan 或其他特殊接口。如果该系统上只有一个网络接口&…...
AMEYA360旗下品牌:日本SUSUMU推出RGV系列贴片电阻器新产品
电动汽车、机器人、精密测量仪器——在上述三例应用领域中,具有高精度、坚固性和长期稳定性的组件是必不可少的。对于这些和类似的应用,RGV系列精密电阻器是理想的选择。 RGV系列电阻器 RGV系列金属薄膜贴片电阻器的电阻值范围为120kΩ至3MΩ(…...
git-版本控制器
集中式版本控制工具(不常用) 版本库集中于中央服务器,team要联网才能工作(下载代码) SVN CVS 分布式版本控制工具 每个电脑上都有一个完整的版本库,工作时无需联网,可以把修改推送给其他人来…...
台式机/工控机通过网线共享笔记本电脑无线网络linux系统下 usb网卡的驱动安装
一、台式机/工控机通过网线共享笔记本电脑无线网络 1、 将台式机通过网线和笔记本连接。 2、 将笔记本的“本地连接”和“无线网络连接”的ipv4均设置为自动获取。 4.修改台式机的IP地址为如下(对应笔记本信息) IP地址为192.168.XXX.12 子网掩码为255.2…...
kotlin 编写一个简单的天气预报app(五)增加forcast接口并显示
参考资料 OpenWeatherMap提供了一个/forecast接口,用于获取未来几天的天气预报。你可以使用HTTP GET请求访问该接口,并根据你所在的城市或地理坐标获取相应的天气数据。 以下是一个示例请求的URL和一些常用的参数: URL: http://api.openwe…...
vs调试引发了异常:读取访问权限冲突,argv是0x7
vs2019写了几句小代码,结果报错: 引发了异常:读取访问权限冲突,argv是0x7 查了一堆是什么数组越界了,空指针异常了啥的。 只好都注释掉只留下主函数,结果还是报错,定睛一看才发现原因:main函数忘写第一…...
【电影推荐系统】实时推荐
概览 技术方案: 日志采集服务:通过利用Flume-ng对业务平台中用户对于电影的一次评分行为进行采集,实时发送到Kafka集群。消息缓冲服务:项目采用Kafka作为流式数据的缓存组件,接受来自Flume的数据采集请求。并将数据推…...
Delphi 开发不一样的窗体标题栏:TTitleBarPanel
目录 TTitleBarPanel 的使用 TTitleBarPanel 的使用进阶 一、设置标题栏高度、颜色 二、个性化标题栏的关闭等按键 我们在用Delphi开发程序的时候,窗体的标题栏一般都是标准的windows标题栏,上面包括:程序图标、标题、最小化、最大化、关闭…...
Quartz中禁止并发机制源码级解析
文章目录 Quartz进行任务调度时通常会要求一个任务禁止并发执行,此时只需要在Job类上面添加一个注解DisallowConcurrentExecution即可。在保存到数据库里面时,对应QRTZ_JOB_DETAILS表中的IS_NONCONCURRENT字段的值为1(true)。那么…...
为什么从公有云迁移到私有云的越来越多?
随着云计算的快速发展,越来越多的组织开始考虑将其IT基础设施从公有云迁移到私有云。这种转变背后存在着一系列的原因和动机,下面我们将探讨一些常见的迁移原因。 首先,数据安全和隐私是许多组织选择私有云的主要原因之一。在公有云中&#…...
用shell实现MySQL分库分表操作
#!/bin/bash mysql_cmd-uroot -p123 #定义变量保存密码 exclude_dbinformation_schema|performance_schema|sys #数据库 bak_path/backup/db #备份路径 mysql ${mysql_cmd} -e show databases -N | egrep -v "${exclude_db}" > dbname while read line do …...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
