【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 …...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...

Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用
Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础,但这一子系统结构复杂,常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题,需要一套工具化、…...