2026/3/27 5:58:28
网站建设
项目流程
网站如何添加外链,wordpress为什么感觉加载慢,二次开发wordpress,网页设计与制作实训总结2000字Redis集群原理#xff1a;就像外卖平台的多店铺配送系统 #x1f69a;
一、整体比喻#xff1a;外卖平台如何运作#xff1f;
想象美团外卖平台#xff1a;
多个餐厅#xff1a;每个餐厅负责一部分菜品#xff08;数据分片#xff09;配送中心#xff1a;协调订单分配…Redis集群原理就像外卖平台的多店铺配送系统 一、整体比喻外卖平台如何运作想象美团外卖平台多个餐厅每个餐厅负责一部分菜品数据分片配送中心协调订单分配集群管理骑手网络互相传递信息节点通信备用厨房主厨病了副厨顶上主从复制Redis集群就是这样一个分布式外卖系统二、Redis集群的核心原理1.数据分片每个餐厅只做自己的拿手菜/* by yours.tools - online tools website : yours.tools/zh/tripledes.html */ # Redis集群把数据分成16384个菜品槽slots # 就像把全城分成16384个配送区域 # 假设有3个餐厅Redis节点 节点A: 负责槽 0-5460 # 做汉堡薯条 节点B: 负责槽 5461-10922 # 做披萨意面 节点C: 负责槽 10923-16383 # 做中餐 # 用户点宫保鸡丁 → 系统计算hash(宫保鸡丁) % 16384 12000 # 12000属于中餐区 → 自动派单给节点C中餐餐厅原理每个键通过CRC16算法计算哈希值对16384取模得到槽位数据存储到负责该槽的节点2.集群架构餐厅联盟的三种角色┌─────────────────┐ │ 客户端App │ └────────┬────────┘ │ ┌─────────────────┼─────────────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 主节点A │ │ 主节点B │ │ 主节点C │ │ (主厨) │ │ (主厨) │ │ (主厨) │ │ 槽0-5460 │ │5461-10922│ │10923-16383│ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │ 从节点A1 │ │ 从节点B1 │ │ 从节点C1 │ │ (副厨) │ │ (副厨) │ │ (副厨) │ └─────────┘ └─────────┘ └─────────┘节点类型主节点存储数据处理读写请求主厨从节点复制主节点数据只读副厨哨兵节点监控节点健康餐厅卫生监督员3.节点通信餐厅经理们的微信群/* by yours.tools - online tools website : yours.tools/zh/tripledes.html */ # 节点间通过Gossip协议通信就像微信群聊 # 每个节点都知道其他节点的槽分配、在线状态、地址 # 通信内容 1. 我是餐厅A负责汉堡区我健康 2. 餐厅C好像掉线了有谁联系得上 3. 新开了餐厅D接手了披萨区一部分 # Gossip协议特点 # - 定期广播每100ms # - 最终一致性消息慢慢传开 # - 容错性强几个餐厅掉线不影响4.故障转移主厨病了副厨顶上场景主节点A汉堡主厨突然心脏病发作宕机流程1. 从节点A1发现主厨失联主厨10秒没回我消息了 2. 向其他餐厅确认你们联系得上汉堡主厨吗 3. 多数餐厅确认失联我们也联系不上 4. 选举新主厨所有副厨投票A1得票最多 5. A1晋升为主厨我来接管汉堡区 6. 更新微信群名片A1改为主节点A技术实现# Redis哨兵Sentinel监控机制 1. 主观下线SDOWN一个哨兵认为主节点不可用 2. 客观下线ODOWN超过半数哨兵认为不可用 3. 选举领头哨兵Raft算法选举 4. 故障转移领头哨兵选择最合适的从节点升级 # Redis Cluster内置的故障检测 1. 每个节点定期ping其他节点 2. 标记疑似下线PFAIL 3. 广播下线信息其他节点确认 4. 标记为已下线FAIL 5. 从节点开始选举5.集群扩容开新分店场景生意太好要开第四家餐厅节点D流程1. 新餐厅加入大家好我是新开的日料店D 2. 重新分配菜品槽从A、B、C各分一些槽给D 3. 数据迁移把对应菜品搬到新餐厅 - A把薯条菜谱发给D - B把海鲜披萨菜谱发给D - C把麻婆豆腐菜谱发给D 4. 迁移期间用户点菜 - 如果菜还在老店稍等正在搬到新店去新店点 - 如果已搬到新店请去新店点餐技术命令# 1. 添加新节点 redis-cli --cluster add-node new_host:new_port existing_host:existing_port # 2. 重新分配槽 redis-cli --cluster reshard host:port # 3. 数据迁移是同步的迁移期间集群仍可用 # 迁移过程中客户端可能收到ASK重定向三、客户端如何与集群交互 场景用户点餐流程// 客户端用户想点一份宫保鸡丁 public class RedisClient { public void orderFood() { // 1. 第一次请求随便选个餐厅 String key 宫保鸡丁; JedisCluster jedis new JedisCluster(nodes); // 连接集群 // 2. 计算槽位hash(宫保鸡丁) % 16384 12000 // 3. 槽位12000属于节点C中餐 // 4. 直接发给节点C jedis.set(key, 一份宫保鸡丁); // 5. 如果发错餐厅比如发给AA会告诉你 // MOVED 12000 节点C的地址 // 客户端自动重定向到节点C // 6. 聪明的客户端会缓存槽位映射表 // 下次直接找对的餐厅不用重定向 } }两种重定向# 1. MOVED重定向永久重定向 # 就像这道菜不是我们做的你永远去中餐厅点 客户端→节点A: 我要宫保鸡丁 节点A→客户端: MOVED 12000 节点C地址 客户端→节点C: 我要宫保鸡丁 节点C→客户端: 好的给你做 # 2. ASK重定向临时重定向 # 发生在数据迁移时 # 就像这道菜正在从我们店搬到新店你去新店看看 客户端→节点A: 我要薯条 节点A→客户端: ASK 新节点地址 # 槽500正在迁移 客户端→新节点: ASKING命令 # 先打个招呼 客户端→新节点: 我要薯条 新节点→客户端: 好的我们刚接手这道菜四、集群的限制不是万能的 1.不支持跨节点事务# 事务要求所有键在同一个节点 # 就像不能同时点汉堡店的汉堡和中餐厅的宫保鸡丁在一个订单里 # ❌ 错误做法键在不同节点 MULTI SET key1 value1 # key1在节点A SET key2 value2 # key2在节点B EXEC # 会失败 # ✅ 正确做法使用哈希标签 # 用{}确保两个键在同一个槽 MULTI SET user:{1000}:name 张三 # 都在user:1000相关槽 SET user:{1000}:age 25 # {}内内容决定槽 EXEC2.批量操作限制# mget/mset只能用于同一个节点上的键 # 就像不能一次从汉堡店和中餐厅同时取餐 # ❌ 可能失败 MGET key1 key2 key3 # 如果key1、key2、key3在不同节点 # ✅ 解决方案 # 1. 使用哈希标签 # 2. 客户端分组发送 # 3. 使用Pipeline分别发送3.Lua脚本限制# Lua脚本中的所有键必须在同一个节点 # 就像脚本厨师不能同时用汉堡店和中餐厅的厨房 # 脚本示例必须所有键在同一个槽 EVAL return redis.call(GET, KEYS[1]) 1 user:{1000}:name五、集群搭建实战开个小型外卖平台 ️1.最少6个节点配置3主3从# 目录结构 redis-cluster/ ├── node-7000/ # 主节点1 ├── node-7001/ # 主节点2 ├── node-7002/ # 主节点3 ├── node-7003/ # 从节点1复制7000 ├── node-7004/ # 从节点2复制7001 └── node-7005/ # 从节点3复制7002 # 每个节点的redis.conf port 7000 cluster-enabled yes cluster-config-file nodes-7000.conf cluster-node-timeout 5000 appendonly yes2.一键创建集群# Redis 5.0 使用redis-cli创建 redis-cli --cluster create \ 127.0.0.1:7000 \ 127.0.0.1:7001 \ 127.0.0.1:7002 \ 127.0.0.1:7003 \ 127.0.0.1:7004 \ 127.0.0.1:7005 \ --cluster-replicas 1 # 每个主节点配1个从节点3.查看集群状态# 查看集群信息 redis-cli -p 7000 cluster info # 查看节点信息 redis-cli -p 7000 cluster nodes # 查看槽分配 redis-cli -p 7000 cluster slots4.集群健康检查# 检查集群状态 redis-cli --cluster check 127.0.0.1:7000 # 输出示例 [OK] All nodes agree about slots configuration. Check for open slots... Check slots coverage... [OK] All 16384 slots covered. # 所有槽都有节点负责六、集群 vs 哨兵 vs 主从三种外卖模式对比 ️模式比喻优点缺点适用场景主从复制一家餐厅一个备用厨房简单、读写分离主节点单点故障小餐厅可接受短暂停业哨兵模式餐厅备用厨房卫生监督员自动故障转移写操作单点、扩容麻烦中等餐厅需要高可用集群模式多个餐厅联盟高可用、高并发、易扩容实现复杂、客户端需支持大型连锁餐厅海量订单七、集群常见问题与解决方案 1.脑裂问题Split Brain# 场景网络分区形成两个外卖平台 # 节点A、B在一个网络C、D在另一个网络 # 两边都认为自己是正宗平台 # 解决方案多数派原则 # 集群需要至少3个主节点故障容忍度 (N-1)/2 # 3主节点允许1个节点故障 # 5主节点允许2个节点故障2.数据一致性# Redis集群采用异步复制 # 主节点写成功就返回然后异步复制到从节点 # 可能丢失少量数据主节点宕机前未同步的数据 # 解决方案根据业务选择 # 1. 等待复制WAIT命令等待N个从节点确认 # 2. 强一致性用Redlock等算法但性能下降 # 3. 最终一致性接受短暂不一致多数业务够用3.热点Key问题# 场景某个商品突然爆单如iPhone新品 # 所有请求都打到同一个节点造成压力 # 解决方案 # 1. 本地缓存客户端缓存热点数据 # 2. 拆分Keyiphone:13:stock → iphone:13:stock:1、iphone:13:stock:2 # 3. 限流降级对热点请求限流4.集群扩容时的性能问题# 迁移大量数据时网络和磁盘IO压力大 # 客户端频繁收到ASK重定向 # 解决方案 # 1. 业务低峰期迁移 # 2. 分批迁移控制迁移速度 # 3. 使用专业的迁移工具八、Redis集群最佳实践 1.合理规划节点数# 推荐配置至少3主3从最多1000个节点 # 主节点数最好是奇数选举时避免平票 # 每个主节点的从节点不超过2个太多复制影响性能 # 生产环境建议 # 小规模3主3从可承受1主1从同时故障 # 中规模5主5从可承受2主2从同时故障 # 大规模按业务分集群不要一个集群太大2.监控指标# 关键监控项 1. 集群状态cluster_state:ok? 2. 槽覆盖率16384个槽是否全部分配 3. 节点健康主从节点是否在线 4. 内存使用避免单个节点内存过大 5. 网络流量节点间通信是否正常 6. 命中率缓存命中率是否正常3.客户端使用规范public class RedisClusterBestPractice { // 1. 使用连接池 private JedisCluster jedisCluster; public void init() { JedisPoolConfig config new JedisPoolConfig(); config.setMaxTotal(100); config.setMaxIdle(20); SetHostAndPort nodes new HashSet(); nodes.add(new HostAndPort(127.0.0.1, 7000)); // ... 添加所有节点 // 2. 设置合理的超时时间 jedisCluster new JedisCluster(nodes, 2000, // 连接超时 2000, // 读取超时 3, // 重试次数 config); } // 3. 使用Pipeline批量操作相同节点 public void batchSetSameSlot() { String slotTag {user:1000}; // 使用哈希标签 Pipeline p jedisCluster.pipelined(); p.set(slotTag :name, 张三); p.set(slotTag :age, 25); p.sync(); } }九、一张图总结Redis集群 ️┌─────────────────────────────────────┐ │ Redis集群外卖平台联盟 │ └────────────────┬────────────────────┘ │ ┌─────────────────────────┼─────────────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 汉堡餐厅 │ │ 披萨餐厅 │ │ 中餐厅 │ │ (主节点A) │ │ (主节点B) │ │ (主节点C) │ │ 槽0-5460 │ │ 5461-10922 │ │ 10923-16383 │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ 微信群聊(Gossip) │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 备用厨房 │ │ 备用厨房 │ │ 备用厨房 │ │ (从节点A1) │ │ (从节点B1) │ │ (从节点C1) │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └────────────────────────┼────────────────────────┘ │ ┌────────────────▼────────────────┐ │ 客户端(用户) │ │ 自动路由 缓存槽位映射 │ └──────────────────────────────────┘十、一句话总结Redis集群 数据分片16384槽 主从复制高可用 Gossip通信自管理记住口诀一六三八四槽分三主三从起步稳Gossip协议传消息故障转移自动跟客户端需知槽映射哈希标签保同门。❤️ 如果你喜欢这篇文章请点赞支持 同时欢迎关注我的博客获取更多精彩内容本文来自博客园作者佛祖让我来巡山转载请注明原文链接https://www.cnblogs.com/sun-10387834/p/19457309