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

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

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是一个异步的、基于事件驱动的网络应用框架,用于…...