当前位置: 首页 > news >正文

RedisCluster客户端路由智能缓存

通俗理解:客户端如何找到数据所在节点

具体流程分解:

1、客户端初始状态

public class RedisClusterClient {// 刚开始,客户端不知道任何槽位对应关系private Map<Integer, String> slotToNodeCache = new HashMap<>();// 空的!像一张空白地图
}

2、第一次查询 - “问路过程”

// 客户端想要执行:SET user:1001 "张三"
public void firstTimeRequest() {String key = "user:1001";int slot = CRC16(key) % 16384; // 计算槽位,比如得到 5000// 情况1:缓存中没有 → 随机选个节点发送请求if (!slotToNodeCache.containsKey(5000)) {// 随便选一个已知节点(比如节点A)sendCommandToNode("节点A", "SET", "user:1001", "张三");}
}

3、服务端响应 - “MOVED重定向”

# 节点A检查槽位5000不属于自己,返回:
MOVED 5000 192.168.1.101:7001
# 意思是:"这个数据在5000号槽,应该去192.168.1.101:7001节点"

4. 客户端学习 - “更新地图”

// 客户端处理MOVED响应
public void handleMovedResponse(String movedResponse) {// 解析:MOVED 5000 192.168.1.101:7001String[] parts = movedResponse.split(" ");int slot = Integer.parseInt(parts[1]);String correctNode = parts[2];// 重要:更新缓存!"记住5000槽在192.168.1.101:7001"slotToNodeCache.put(slot, correctNode);// 重新发送请求到正确节点resendToCorrectNode(correctNode, "SET", "user:1001", "张三");
}

5、后续请求 - “直接到达”

// 第二次查询相同槽位的键
public void subsequentRequest() {String key = "user:1002"; // 相同用户ID,大概率在相同槽位int slot = CRC16(key) % 16384; // 还是5000左右// 现在缓存中有记录了!if (slotToNodeCache.containsKey(slot)) {String correctNode = slotToNodeCache.get(slot);// 直接去正确节点,不用问路了sendCommandToNode(correctNode, "GET", "user:1002");}
}

为什么需要这种设计?

性能:避免每次请求都先问路
减负:减少服务端的路由查询压力
智能:客户端自己会学习,越来越聪明

问题

如果槽位和节点重新分布后,客户端的缓存怎么办?

详细的重定向处理流程

  1. MOVED重定向(永久迁移)

场景:槽位1000从节点A迁移到节点B已完成

public class SmartRedisClient {
private Map<Integer, String> slotCache = new HashMap<>();

// 初始缓存:槽位1000在节点A
public void initCache() {slotCache.put(1000, "192.168.1.101:6379"); // 节点A
}public void handleCommand(String key) {int slot = calculateSlot(key); // 假设是1000// 1. 客户端根据缓存发送到节点AString targetNode = slotCache.get(slot); // "192.168.1.101:6379"sendCommandToNode(targetNode, "SET", key, "value");// 2. 节点A返回MOVED重定向// 响应: "MOVED 1000 192.168.1.102:6379" (节点B)
}public void processMovedResponse(String response) {// 解析MOVED响应: "MOVED <slot> <new-node>"String[] parts = response.split(" ");int movedSlot = Integer.parseInt(parts[1]);String newNode = parts[2];// 重要:永久更新缓存!slotCache.put(movedSlot, newNode);System.out.println("更新缓存: 槽位 " + movedSlot + " → " + newNode);// 重新发送请求到新节点resendToNewNode(newNode, movedSlot);
}

}

  1. ASK重定向(迁移中)

场景:槽位1000正在从节点A迁移到节点B

public class SmartRedisClient {
public void handleCommandDuringMigration(String key) {
int slot = calculateSlot(key); // 1000

    // 1. 客户端根据缓存发送到节点A(源节点)String targetNode = slotCache.get(slot); // 仍然是节点AsendCommandToNode(targetNode, "SET", key, "value");// 2. 节点A检查键的迁移状态:if (isKeyMigrated(key, slot)) {// 键已迁移到节点B,返回ASK重定向return "ASK 1000 192.168.1.102:6379";} else {// 键还在节点A,正常处理return executeCommand(key);}
}public void processAskResponse(String response) {// 解析ASK响应: "ASK <slot> <temp-node>"String[] parts = response.split(" ");int askSlot = Integer.parseInt(parts[1]);String tempNode = parts[2];// 重要:不更新永久缓存!System.out.println("临时重定向: 槽位 " + askSlot + " → " + tempNode + " (不更新缓存)");// 特殊流程:先发ASKING,再发命令sendAskingCommand(tempNode);    // 1. 发送ASKING命令resendToTempNode(tempNode);    // 2. 发送原命令// 缓存保持不变,后续请求仍然发往节点A
}private void sendAskingCommand(String node) {// ASKING命令告诉目标节点:"我知道这是临时访问"sendCommandToNode(node, "ASKING");
}

}

http://www.dtcms.com/a/576999.html

相关文章:

  • K8s从Docker到Containerd的迁移全流程实践
  • Rust语言高级技巧 - RefCell 是另外一个提供了内部可变性的类型,Cell 类型没办法制造出直接指向内部数据的指针,为什么RefCell可以呢?
  • 【Python后端API开发对比】FastAPI、主流框架Flask、Django REST Framework(DRF)及高性能框架Tornado
  • 计算机外设与CPU通信
  • 玩转Rust高级应用 如何编译器对于省略掉的生命周期,不使用“自动推理”策略呢?
  • Python全栈项目:基于Django的电子商务平台开发
  • 网站建设怎么开票网站设计网页设计公司
  • Python实现GPT自动问答与保存
  • 深度强化学习,用神经网络代替 Q-table
  • seo网站建设技巧电线电缆技术支持中山网站建设
  • supabase外键查询语句
  • 【linux端cursor CLI常用命令】
  • 表的增删改查
  • Git 工作区、暂存区和版本库
  • MIT-矩阵链相乘
  • Go语言实战:入门篇-5:函数、服务接口和Swagger UI
  • 国产化Excel处理控件Spire.XLS教程:使用Java将CSV转换为PDF(含格式设置)
  • 【Hot100|3 LeetCode 128. 最长连续序列】
  • 一键搭建 Coze 智能体对话页面:支持流式输出 + 图片直显,开发效率拉满!
  • 十大免费ae模板网站短视频素材下载网站
  • 那里做直播网站网页打不开是什么问题
  • 论文分享 | AirRoom:物体是关键!革新室内房间重识别的新范式
  • 游戏 IPA 如何防修改,面向开发者的多工具实战(IPA 加固/无源码混淆/Ipa Guard CLI)
  • 从0到1做一个“字母拼词”Unity小游戏(含源码/GIF)- 项目的创建及准备
  • 在扣子上搭建测试用例自动编写智能体
  • 2023年第二十届五一数学建模竞赛-A题 无人机定点投放问题-基于抛体运动的无人机定点投放问题研究
  • 影刀RPA一键生成销售日报!AI智能分析,效率提升1000%[特殊字符]
  • Rust开发实战之密码学基础——哈希计算与对称加密实战
  • 技术解析:清洗无人机在高空清洁中的应用与优势
  • Linux LVM NAT 模式部署实践