【Redis】Redis Cluster 简单介绍
Redis Cluster 是 Redis 3.0 提供的一种分布式解决方案, 允许数据在多个节点之间分散存储, 从而实现高可用性和可扩展性。
特点:
- 分片: Redis Cluster 将数据分散到多个节点, 通过哈希槽 (hash slots) 机制将键映射到不同的节点上。总共有 16384 个哈希槽, 每个节点负责一部分槽。
- 高可用性: Redis Cluster 支持主从复制, 每个主节点可以有多个从节点, 从节点可以在主节点故障时自动提升为主节点。
- 自动故障转移: 当主节点宕机时, Cluster 会自动检测并选择从节点提升为新的主节点, 保持服务的可用性。
- 无中心化: Redis Cluster 是去中心化的, 没有单点故障。所有节点都可以处理请求, 提升了系统的健壮性。
解决的问题:
- 数据存储限制: 单个 Redis 实例的内存限制使其在处理大规模数据时受到约束, Redis Cluster 通过分片技术克服了这一限制, 支持更大规模的数据存储。
- 高可用性需求: 在传统的 Redis 配置中, 主节点故障会导致服务不可用。Redis Cluster 通过主从复制和自动故障转移确保服务的连续性, 满足高可用性的需求。
- 负载均衡: 随着数据量和访问量的增加, Redis Cluster 可以通过增加节点和分配哈希槽实现负载均衡, 避免某一节点过载。
1 Redis Cluster 的搭建
Redis Cluster 可以看成是由多个 Redis 实例组成的数据集合。
客户端不需要关注数据的子集到底存储在哪个节点, 只需要关注这个集合整体。
那么如何搭建一个这样的集群呢?
注: 这里用一台集群搭建集群, Ip 地址为 192.169.10.10, 7000/7001/7002 为主节点的端口, 8000/8001/8002 为对应的从节点的端口。
1.1 修改配置
修改 redis.conf 配置文件中的 3 个参数
- cluster-enabled yes
- cluster-config-file “node-7000.conf”
- cluster-node-timeout 5000
其他的参数和单个 Redis 实例的一样。
cluster-enabled yes
: Redis 实例可以分为单机模式 (standalone) 和集群模式 (cluster)。 yes 开启为集群模式。
cluster-config-file
: 该参数指定了集群配置文件的位置。每个节点在运行过程中, 会维护一份集群配置文件; 每当集群信息发生变化时 (如增减节点), 集群内所有节点会将最新信息更新到自己维护的配置文件。
当节点重启后, 会重新读取该配置文件, 获取集群信息, 可以方便的重新加入到集群中。
也就是说当 Redis 节点以集群模式启动时, 会首先寻找是否有集群配置文件, 如果有则使用文件中的配置启动, 如果没有, 则初始化配置并将配置保存到文件中。 集群配置文件由 Redis 节点维护, 不需要人工修改。
cluster-node-timeout
: 节点之间心跳超时时间
cluster-require-full-coverage
: 默认值为 yes, 将其修改为 no, 表示 Redis 节点的槽没有完全分配时,集群仍可以上线。
1.2 启动节点
通过 redis-server redis.conf
配置文件启动 Redis。
可以通过 cluster nodes 查看当前的节点集群信息。
1.3 节点握手
执行 redis-cli --cluster create 命令
节点启动以后是相互独立的,并不知道其他节点存在, 需要进行节点握手。
将独立的节点组成一个网络。注下面的操作, 不能使用 localhost 和 127.0.0.1, 需要使用局域网 Ip 或 公网 Ip。
redis-cli --cluster create 192.169.10.10:7000 192.169.10.10:7001 192.169.10.10:7002 192.169.10.10:8000 192.169.10.10:8001 192.169.10.10:8002 --cluster-replicas 1
–cluster-replicas 1 表示每个主节点有 1 个从节点, 后面的多个 {ip:port} 表示节点地址。(默认: 所有节点平均分成 2 组, 前面一组为主节点, 后面一组为从节点)
执行创建命令后, Redis 会给出一个预计的方案, 对 6 个节点分配 3 主 3 从, 如果认为没有问题,输入 yes 确认
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.169.10.10:8000 to 192.169.10.10:7000
Adding replica 192.169.10.10:8001 to 192.169.10.10:7001
Adding replica 192.169.10.10:8002 to 192.169.10.10:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c 192.169.10.10:7000slots:[0-5460] (5461 slots) master
M: 8c878b45905bba3d7366c89ec51bd0cd7ce959f8 192.169.10.10:7001slots:[5461-10922] (5462 slots) master
M: aeeb7d7076d9b25a7805ac6f508497b43887e599 192.169.10.10:7002slots:[10923-16383] (5461 slots) master
S: ebc479e609ff8f6ca9283947530919c559a08f80 192.169.10.10:8000replicates aeeb7d7076d9b25a7805ac6f508497b43887e599
S: 49385ed6e58469ef900ec48e5912e5f7b7505f6e 192.169.10.10:8001replicates dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c
S: 8d6227aefc4830065624ff6c1dd795d2d5ad094a 192.169.10.10:8002replicates 8c878b45905bba3d7366c89ec51bd0cd7ce959f8
Can I set the above configuration? (type 'yes' to accept):
输入 yes 后
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 192.169.10.10:7000)
M: dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c 192.169.10.10:7000slots:[0-5460] (5461 slots) master1 additional replica(s)
M: 8c878b45905bba3d7366c89ec51bd0cd7ce959f8 192.169.10.10:7001slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: ebc479e609ff8f6ca9283947530919c559a08f80 192.169.10.10:8002slots: (0 slots) slavereplicates aeeb7d7076d9b25a7805ac6f508497b43887e599
S: 49385ed6e58469ef900ec48e5912e5f7b7505f6e 192.169.10.10:8000slots: (0 slots) slavereplicates dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c
M: aeeb7d7076d9b25a7805ac6f508497b43887e599 192.169.10.10:7002slots:[10923-16383] (5461 slots) master1 additional replica(s)
S: 8d6227aefc4830065624ff6c1dd795d2d5ad094a 192.169.10.10:8001slots: (0 slots) slavereplicates 8c878b45905bba3d7366c89ec51bd0cd7ce959f8
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
1.4 Redis Cluster 相关的命令
集群命令
命令 | 效果 |
---|---|
cluster info | 打印集群的信息 |
cluster nodes | 列出集群当前已知的所有节点 (node), 以及这些节点的相关信息 |
cluster meet | 将 ip 和 port 所指定的节点添加到集群当中, 让它成为集群的一份子, 这时候没有主从关系 |
cluster forget <node_id> | 从集群中移除 node_id 指定的节点 (保证空槽道) |
cluster replicate <node_id> | 将当前节点设置为 node_id 指定的节点的从节点 |
cluster saveconfig | 将节点的配置文件保存到硬盘里面 |
槽slot命令
命令 | 效果 |
---|---|
cluster addslots [slot …] | 将一个或多个槽 (slot) 指派 (assign) 给当前节点 |
cluster delslots [slot …] | 移除一个或多个槽对当前节点的指派 |
cluster flushslots | 移除指派给当前节点的所有槽, 让当前节点变成一个没有指派任何槽的节点 |
cluster setslot node <node_id> | 将槽 slot 指派给 node_id 指定的节点, 如果槽已经指派给另一个节点, 那么先让另一个节点删除该槽, 然后再进行指派 |
cluster setslot migrating <node_id> | 将本节点的槽 slot 迁移到 node_id 指定的节点中 |
cluster setslot importing <node_id> | 从 node_id 指定的节点中导入槽 slot 到本节点 |
cluster setslot stable | 取消对槽 slot 的导入 (imort) 或者迁移 (migrate) |
键命令
命令 | 效果 |
---|---|
cluster keyslot | 计算键 key 应该被放置在哪个槽上 |
cluster countkeysinslot | 返回槽 slot 目前包含的键值对数量 |
cluster getkeysinslot | 返回 count 个 slot 槽中的键 |
2 故障转移
集群的实现与哨兵思路类似: 通过定时任务发送 PING 消息检测其他节点状态。节点下线分为主观下线和客观下线, 客观下线后选取从节点进行故障转移。
与哨兵一样, 集群只实现了主节点的故障转移, 从节点故障时只会被下线, 不会进行故障转移。因此, 使用集群时, 应谨慎使用读写分离技术, 因为从节点故障会导致读服务不可用, 可用性变差。
大体是:
- slave 发现自己的 maste 变为 Fail 状态, 偏尝试进行 Failover, 以期成为新的 master
- slave 将自己记录的集群 currentEpoch + 1, 然后广播 FAILOVER_AUTH_REQUEST 信息
- 其他节点收到改消息后, 只有 master 节点会进行响应, 判断请求这的合法性, 并发送 FAILOVER_AUTH_ACK, 对每一个 epoch 只发送一次 ack
- 尝试 Failover 的 slave 收集 FAILOVER_AUTH_ACK
- 超过半数后变成新的 master
- 广播 Pong 通知其他集群节点
节点数量: 在故障转移阶段, 需要由主节点投票选出哪个从节点成为新的主节点, 从节点选举胜出需要的票数为 N/2+1, 其中 N 为主节点数量 (包括故障主节点), 但故障主节点实际上不能投票。
因此为了能够在故障发生时顺利选出从节点, 集群中至少需要3个主节点 (且部署在不同的物理机上)。
故障转移时间: 从主节点故障发生到完成转移, 所需要的时间主要消耗在主观下线识别、主观下线传播、选举延迟等几个环节。具体时间与参数 cluster-node-timeout 有关, 一般来说:
故障转移时间(毫秒) ≤ 1.5 * cluster-node-timeout + 1000
cluster-node-timeout 的默认值为 15000ms (15s), 因此故障转移时间会在 20s 量级
3 Hash Tag
有些 multi key 操作是不能跨阶段的, 如果要让某些数据统一分配到同一个节点上, 可以借助 Hast Tag 功能。
Hash Tag 原理是: 当一个 key 包含 {} 的时候, 不对整个 key 做 hash, 而仅对 {} 包括的字符串做 hash。
Hash Tag 可以让不同的 key 拥有相同的 hash 值, 从而分配在同一个槽里, 这样针对不同 key 的批量操作 (mget/mset等), 以及事务、Lua 脚本等都可以支持。
Hash Tag 可能会带来数据分配不均的问题, 这时可以
- 调整不同节点中槽的数量,使数据分布尽量均匀
- 避免对热点数据使用 Hash Tag, 导致请求分布不均
4 Redis Cluster 的不足
- Client 实现复杂, 驱动要求实现 Smart Client, 缓存 slots mapping 信息并及时更新, 提高了开发难度, 客户端的不成熟影响业务的稳定性
- 节点会因为某些原因发生阻塞 (阻塞时间大于 cluster-node-timeout), 被判断下线, 这种 failover 是没必要的
- 数据通过异步复制, 不保证数据的强一致性
- 多个业务使用同一套集群时, 无法根据统计区分冷热数据, 资源隔离性较差, 容易出现相互影响的情况
5 参考
深入学习Redis(5):集群
相关文章:
【Redis】Redis Cluster 简单介绍
Redis Cluster 是 Redis 3.0 提供的一种分布式解决方案, 允许数据在多个节点之间分散存储, 从而实现高可用性和可扩展性。 特点: 分片: Redis Cluster 将数据分散到多个节点, 通过哈希槽 (hash slots) 机制将键映射到不同的节点上。总共有 16384 个哈希槽, 每个节点负责一部分…...

【EXCEL数据处理】000010 案列 EXCEL文本型和常规型转换。使用的软件是微软的Excel操作的。处理数据的目的是让数据更直观的显示出来,方便查看。
前言:哈喽,大家好,今天给大家分享一篇文章!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【EXCEL数据处理】000010 案列 EXCEL单元格格式。EXCEL文本型和常规型转…...

golang grpc进阶
protobuf 官方文档 基本数据类型 .proto TypeNotesGo Typedoublefloat64floatfloat32int32使用变长编码,对于负值的效率很低,如果你的域有可能有负值,请使用sint64替代int32uint32使用变长编码uint32uint64使用变长编码uint64sint32使用变长…...

Java JUC(三) AQS与同步工具详解
Java JUC(三) AQS与同步工具详解 一. ReentrantLock 概述 ReentrantLock 是 java.util.concurrent.locks 包下的一个同步工具类,它实现了 Lock 接口,提供了一种相比synchronized关键字更灵活的锁机制。ReentrantLock 是一种独占…...
使用rust写一个Web服务器——async-std版本
文章目录 实现异步代码并发地处理连接使用多线程提升性能 使用rust实现一个异步运行时是async-std的单线程Web服务器。 仓库地址: 1037827920/web-server: 使用rust编写的简单web服务器 (github.com) 在之前的单线程版本的Web服务器代码上进行修改,具体…...

C语言复习概要(一)
本文 C语言入门详解:从基础概念到分支与循环1. C语言常见概念1.1 程序的基本结构1.2 变量作用域和存储类1.3 输入输出1.4 编译与运行 2. C语言中的数据类型和变量2.1 基本数据类型2.2 变量的声明与初始化2.3 常量与枚举 3. C语言的分支结构3.1 if语句3.2 if-else语句…...

二、kafka生产与消费全流程
一、使用java代码生产、消费消息 1、生产者 package com.allwe.client.simple;import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.pr…...

本地搭建OnlyOffice在线文档编辑器结合内网穿透实现远程协作
文章目录 前言1. 安装Docker2. 本地安装部署ONLYOFFICE3. 安装cpolar内网穿透4. 固定OnlyOffice公网地址 前言 本篇文章讲解如何使用Docker在本地Linux服务器上安装ONLYOFFICE,并结合cpolar内网穿透实现公网访问本地部署的文档编辑器与远程协作。 Community Editi…...

ScrapeGraphAI 大模型增强的网络爬虫
在数据驱动的动态领域,从在线资源中提取有价值的见解至关重要。从市场分析到学术研究,对特定数据的需求推动了对强大的网络抓取工具的需求。 NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线…...

PDF转换为TIF,JPG的一个简易工具(含下载链接)
目录 0.前言: 1.工具目录 2.工具功能(效果),如何运行 效果 PDF转换为JPG(带颜色) PDF转换为TIF(LZW形式压缩,可以显示子的深浅) PDF转换为TIF(CCITT形…...

Wireshark 解析QQ、微信的通信协议|TCP|UDP
写在前面 QQ,微信这样的聊天软件。我们一般称为im,Instant Messaging,即时通讯系统。那大家会不会有疑问,自己聊天内容会不会被黑客或者不法分子知道?这种体量的im是基于tcp还是udp呢?这篇文章我们就来探索…...
网络编程(5)——模拟伪闭包实现连接的安全回收
六、day6 今天学习如何利用C11模拟伪闭包实现连接的安全回收,之前的异步服务器为echo模式,但存在安全隐患,在极端情况下客户端关闭可能会导致触发写和读回调函数,二者都进入错误处理逻辑,进而造成二次析构。今天学习如…...

C#绘制动态曲线
前言 用于实时显示数据动态曲线,比如:SOC。 //用于绘制动态曲线,可置于定时函数中,定时更新数据曲线 void DrawSocGraph() {double f (double)MainForm.readData[12]; //display datachart1.Series[0].Points.Add(f);if (ch…...
用Python实现运筹学——Day 10: 线性规划的计算机求解
一、学习内容 1. 使用 Python 的 scipy.optimize.linprog 进行线性规划求解 scipy.optimize.linprog 是 Python 中用于求解线性规划问题的函数。它实现了单纯形法、内点法等算法,能够处理求解最大化或最小化问题,同时满足线性约束条件。 线性规划问题的…...

[C++]使用C++部署yolov11目标检测的tensorrt模型支持图片视频推理windows测试通过
官方框架: https://github.com/ultralytics/ultralytics yolov8官方最近推出yolov11框架,标志着目标检测又多了一个检测利器,于是尝试在windows下部署yolov11的tensorrt模型,并最终成功。 重要说明:安装环境视为最基…...
霍夫曼树及其与B树和决策树的异同
霍夫曼树是一种用于数据压缩的二叉树结构,通常应用于霍夫曼编码算法中。它的主要作用是通过对符号进行高效编码,减少数据的存储空间。霍夫曼树在压缩领域扮演着重要角色,与B树、决策树等数据结构都有一些相似之处,但又在应用场景和…...

CompletableFuture常用方法
一、获得结果和触发计算 1.获取结果 (1)public T get() public class CompletableFutureAPIDemo{public static void main(String[] args) throws ExecutionException, InterruptedException{CompletableFuture<String> completableFuture Com…...

本地化测试对游戏漏洞修复的影响
本地化测试在游戏开发的质量保证过程中起着至关重要的作用,尤其是在修复bug方面。当游戏为全球市场做准备时,它们通常会被翻译和改编成各种语言和文化背景。这种本地化带来了新的挑战,例如潜在的语言错误、文化误解,甚至是不同地区…...
使用rust实现rtsp码流截图
中文互联网上的rust示例程序源码还是太稀少,找资料很是麻烦,下面是自己用业余时间开发实现的一个对批量rtsp码流源进行关键帧截图并存盘的rust demo源码记录。 要编译这个源码需要先安装vcpkg,然后用vcpkg install ffmpeg安装最新版本的ffmpe…...

Cpp::STL—string类的模拟实现(12)
文章目录 前言一、string类各函数接口总览二、默认构造函数string(const char* str "");string(const string& str);传统拷贝写法现代拷贝写法 string& operator(const string& str);传统赋值构造现代赋值构造 ~string(); 三、迭代器相关函数begin &…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...