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

如何实现在Redis集群情况下,同一类数据固定保存在同一个Redis实例中

1. 使用哈希标签(Hash Tags)

概述

Redis Cluster使用一致性哈希算法来分配数据到不同的节点上。为了确保相同类型的数据被分配到同一个Redis实例上,可以利用哈希标签(Hash Tags)。哈希标签是指在键名中用花括号 {} 包围的部分,Redis会根据这部分内容计算哈希值,并将其分配到相应的插槽。

关键点
  • 哈希标签:键名中被 {} 包围的部分用于计算哈希值。
  • 插槽分配:相同的哈希标签部分会导致相同的哈希值,从而保证数据分配到同一个插槽。

2. 键设计与哈希标签的结合

示例场景

假设我们有一个用户资料系统,每种类型的用户资料都有一个唯一的 typeId,我们希望所有 typeId=1 的用户资料都存储在同一个Redis实例上。

实现步骤
  1. 定义键格式:为每个类型的键添加 {typeId} 前缀,并使用哈希标签来确保同类型的数据被分配到相同的插槽。

  2. 操作示例:通过Java代码演示如何实现这一目标。

详细代码示例

1. 定义键生成函数
public class KeyGenerator {// 定义生成键的方法,确保包含哈希标签public static String generateKeyWithHashTag(String typeId, String uniqueId) {return String.format("{user:type:%s}:profile:%s", typeId, uniqueId);}public static void main(String[] args) {// 测试键生成函数String key1 = generateKeyWithHashTag("1", "12345");String key2 = generateKeyWithHashTag("1", "67890");System.out.println(key1);  // 输出:{user:type:1}:profile:12345System.out.println(key2);  // 输出:{user:type:1}:profile:67890}
}
2. Redis Cluster操作
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;import java.util.HashSet;
import java.util.Set;public class RedisClusterTypeExample {// 定义生成键的方法,确保包含哈希标签public static String generateKeyWithHashTag(String typeId, String uniqueId) {return String.format("{user:type:%s}:profile:%s", typeId, uniqueId);}public static void main(String[] args) {// 设置Redis集群节点Set<HostAndPort> jedisClusterNodes = new HashSet<>();jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));try (JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes)) {// 定义typeIdString typeId = "1";// 使用哈希标签确保同类型的数据在同一插槽String userKey1 = generateKeyWithHashTag(typeId, "12345");String userKey2 = generateKeyWithHashTag(typeId, "67890");// 存储用户资料jedisCluster.set(userKey1, "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}");jedisCluster.set(userKey2, "{\"name\": \"Jane Doe\", \"email\": \"jane@example.com\"}");// 获取用户资料String userData1 = jedisCluster.get(userKey1);System.out.println(userData1);  // 输出:{"name": "John Doe", "email": "john@example.com"}String userData2 = jedisCluster.get(userKey2);System.out.println(userData2);  // 输出:{"name": "Jane Doe", "email": "jane@example.com"}// 清理测试数据jedisCluster.del(userKey1);jedisCluster.del(userKey2);} catch (Exception e) {e.printStackTrace();}}
}

详细说明

1. 键生成函数
public static String generateKeyWithHashTag(String typeId, String uniqueId) {return String.format("{user:type:%s}:profile:%s", typeId, uniqueId);
}
  • {user:type:1}:这是哈希标签部分,Redis会根据这部分内容计算哈希值。
  • :profile:12345 和 :profile:67890:这是具体的数据标识部分,不会影响哈希值的计算。
2. Redis Cluster操作
Set<HostAndPort> jedisClusterNodes = new HashSet<>();
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));try (JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes)) {// ... 其他操作 ...
}
  • Redis Cluster节点配置:指定多个节点以形成一个Redis集群。
  • JedisCluster 对象:用于与Redis集群进行交互。
3. 数据操作
String userKey1 = generateKeyWithHashTag(typeId, "12345");
String userKey2 = generateKeyWithHashTag(typeId, "67890");// 存储用户资料
jedisCluster.set(userKey1, "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}");
jedisCluster.set(userKey2, "{\"name\": \"Jane Doe\", \"email\": \"jane@example.com\"}");// 获取用户资料
String userData1 = jedisCluster.get(userKey1);
System.out.println(userData1);String userData2 = jedisCluster.get(userKey2);
System.out.println(userData2);// 清理测试数据
jedisCluster.del(userKey1);
jedisCluster.del(userKey2);
  • 设置和获取数据:通过 set 和 get 方法操作Redis中的数据。
  • 清理测试数据:使用 del 方法删除不再需要的数据。

最佳实践

1. 错误处理

确保捕获并处理所有可能的异常,避免程序崩溃。特别是在网络不稳定或Redis服务不可用的情况下。

try {// Redis操作
} catch (Exception e) {e.printStackTrace();  // 或者记录日志
}

例如,在上述代码中,我们在 main 方法中已经包含了 try-catch 块来捕获异常。

2. 性能优化
  • 连接池:使用 JedisPool 来管理与Redis集群的连接,避免频繁创建和销毁连接带来的开销。
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Jedis;public class RedisConnectionPoolExample {private static final JedisPool pool = new JedisPool("localhost", 6379);public static void main(String[] args) {try (Jedis jedis = pool.getResource()) {jedis.set("user:profile:12345", "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}");String userData = jedis.get("user:profile:12345");System.out.println(userData);  // 输出:{"name": "John Doe", "email": "john@example.com"}jedis.del("user:profile:12345");} catch (Exception e) {e.printStackTrace();}}
}
  • 批量操作:尽量使用批量操作(如 mset 和 mget),减少网络往返次数。
Map<String, String> dataMap = new HashMap<>();
dataMap.put("user:profile:12345", "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}");
dataMap.put("user:profile:67890", "{\"name\": \"Jane Doe\", \"email\": \"jane@example.com\"}");// 批量设置数据
jedis.mset(dataMap);// 批量获取数据
List<String> keys = Arrays.asList("user:profile:12345", "user:profile:67890");
List<String> values = jedis.mget(keys.toArray(new String[0]));
for (String value : values) {System.out.println(value);
}
3. 数据一致性

在分布式环境中,使用分布式锁或其他机制来保证数据的一致性,尤其是在并发写入场景下。

import redis.clients.jedis.Jedis;public class RedisDistributedLockExample {private static final String LOCK_KEY = "lock:key";public static void main(String[] args) {try (Jedis jedis = new Jedis("localhost")) {String lockValue = "lock-value";long timeout = 10000;  // 超时时间10秒// 尝试获取锁long end = System.currentTimeMillis() + timeout;boolean isLocked = false;while (System.currentTimeMillis() < end) {if (jedis.setnx(LOCK_KEY, lockValue) == 1) {isLocked = true;break;}Thread.sleep(100);  // 等待100毫秒后重试}if (isLocked) {try {// 执行需要加锁的操作jedis.set("user:profile:12345", "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}");} finally {// 释放锁if (lockValue.equals(jedis.get(LOCK_KEY))) {jedis.del(LOCK_KEY);}}} else {System.out.println("Failed to acquire lock.");}} catch (Exception e) {e.printStackTrace();}}
}

扩展性考虑

  • Redis集群扩展:如果系统规模进一步扩大,可以增加Redis集群节点的数量,Redis Cluster会自动重新分配数据。
  • 监控和维护:定期监控Redis集群的状态,确保其健康运行。可以使用Prometheus、Grafana等工具进行监控。

具体应用场景示例

1. 用户资料系统

假设我们有一个用户资料系统,每个用户的资料包括姓名和电子邮件地址。我们需要确保所有属于特定类型的用户资料(例如 typeId=1)都存储在同一个Redis实例上。

步骤:
  1. 定义键格式

    public static String generateUserKey(String typeId, String userId) {return String.format("{user:type:%s}:profile:%s", typeId, userId);
    }
  2. 存储用户资料

    String userKey = generateUserKey("1", "12345");
    jedisCluster.set(userKey, "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}");
  3. 读取用户资料

    String userData = jedisCluster.get(userKey);
    System.out.println(userData);  // 输出:{"name": "John Doe", "email": "john@example.com"}
2. 日志系统

假设我们有一个日志系统,不同类型的日志(例如 logType=errorlogType=info)需要分别存储在不同的Redis实例上。

步骤:
  1. 定义键格式

    public static String generateLogKey(String logType, String logId) {return String.format("{log:type:%s}:entry:%s", logType, logId);
    }
  2. 存储日志条目

    String errorLogKey = generateLogKey("error", "1");
    jedisCluster.set(errorLogKey, "{\"message\": \"An error occurred\", \"timestamp\": \"2025-02-25T14:35:00Z\"}");
  3. 读取日志条目

    String errorLogData = jedisCluster.get(errorLogKey);
    System.out.println(errorLogData);  // 输出:{"message": "An error occurred", "timestamp": "2025-02-25T14:35:00Z"}

总结

        通过上述详细的实现步骤和代码示例,你可以确保同一类数据固定保存在同一个Redis实例中。这种方法不仅适用于用户资料系统和日志系统,还可以广泛应用于其他需要对不同类型数据进行分类管理的场景。通过合理设计键结构和利用哈希标签,可以简化数据管理和查询操作,同时提高系统的可维护性和性能。此外,结合错误处理、性能优化和数据一致性机制,可以构建一个更加健壮和高效的Redis应用。

相关文章:

如何实现在Redis集群情况下,同一类数据固定保存在同一个Redis实例中

1. 使用哈希标签&#xff08;Hash Tags&#xff09; 概述 Redis Cluster使用一致性哈希算法来分配数据到不同的节点上。为了确保相同类型的数据被分配到同一个Redis实例上&#xff0c;可以利用哈希标签&#xff08;Hash Tags&#xff09;。哈希标签是指在键名中用花括号 {} 包…...

kotlin 知识点 七 泛型的高级特性

对泛型进行实化 泛型实化这个功能对于绝大多数Java 程序员来讲是非常陌生的&#xff0c;因为Java 中完全没有这个概 念。而如果我们想要深刻地理解泛型实化&#xff0c;就要先解释一下Java 的泛型擦除机制才行。 在JDK 1.5之前&#xff0c;Java 是没有泛型功能的&#xff0c;…...

Transformer LLaMA

一、Transformer Transformer&#xff1a;一种基于自注意力机制的神经网络结构&#xff0c;通过并行计算和多层特征抽取&#xff0c;有效解决了长序列依赖问题&#xff0c;实现了在自然语言处理等领域的突破。 Transformer 架构摆脱了RNNs&#xff0c;完全依靠 Attention的优…...

Qt学习 网络编程 TPC通信

一 基本网络端口 1 网络编程基本概念 通讯方式&#xff1a;信息的通讯时通过网络来进行&#xff0c;通讯方式有两种&#xff0c;TCP和UDP通信&#xff0c;TCP通讯是专用通道&#xff0c;指定某个信息只能走某个通道&#xff0c;UDP则是非专用通道&#xff0c;比如一个车队&am…...

ESP32-S3 实战指南:BOOT-KEY 按键驱动开发全解析

一、基础知识 本篇我们使用 BOOT 按键来学习一下 GPIO 功能&#xff0c;首先补充一下相关术语介绍。 1、GPIO&#xff08;General Purpose Input/Output&#xff09; GPIO 是微控制器上的通用引脚&#xff0c;既可以作为输入&#xff08;读取外部信号&#xff09;&#xff0…...

ssh配置 远程控制 远程协作 github本地配置

0.设备版本 windows11 ubuntu24.0.4 1.1 在 Linux 上启用 SSH 服务 首先&#xff0c;确保 Linux 计算机上安装并启用了 SSH 服务。 安装和启动 OpenSSH 服务&#xff08;如果未安装&#xff09; # 在终端安装 OpenSSH 服务&#xff08;如果尚未安装&#xff09; sudo apt …...

C++知识整理day9——继承(基类与派生类之间的转换、派生类的默认成员函数、多继承问题)

文章目录 1.继承的概念和定义2.基类与派生类之间的转换3.继承中的作用域4.派生类的默认成员函数5.实现一个不能被继承的类6.继承与友元7.继承与静态成员8.多继承和菱形继承问题8.1 继承分类及菱形继承8.2 虚继承 1.继承的概念和定义 概念&#xff1a; 继承(inheritance)机制是⾯…...

2024年国赛高教杯数学建模A题板凳龙闹元宵解题全过程文档及程序

2024年国赛高教杯数学建模 A题 板凳龙闹元宵 原题再现 “板凳龙”&#xff0c;又称“盘龙”&#xff0c;是浙闽地区的传统地方民俗文化活动。人们将少则几十条&#xff0c;多则上百条的板凳首尾相连&#xff0c;形成蜿蜒曲折的板凳龙。盘龙时&#xff0c;龙头在前领头&#x…...

华为认证考试证书下载步骤(纸质+电子版)

华为考试证书可以通过官方渠道下载相应的电子证书&#xff0c;部分高级认证如HCIE还支持申请纸质证书。 一、华为电子版证书申请步骤如下&#xff1a; ①访问华为培训与认证网站 打开浏览器&#xff0c;登录华为培训与认证官方网站 ②登录个人账号 在网站首页&#xff0c;点…...

[杂学笔记]工厂模式、多态、内存空间区域划分、cp指令破坏软连接问题、UDP如何实现可靠传输、滑动窗口的原理、进程与线程、线程之间的通信

目录 1.工厂模式 2.多态 3.内存空间区域划分 4.cp指令破坏软连接问题 5.UDP实现可靠传输 6.滑动窗口的原理 7.进程与线程 8.线程之间的通信 1.工厂模式 工厂模式是一种创建对象的设计模式。它提供了一种创建对象的方式&#xff0c;将对象的创建和使用分离&#xff0c;通…...

开源RAG主流框架有哪些?如何选型?

开源RAG主流框架有哪些?如何选型? 一、开源RAG框架全景图 (一)核心框架类型对比 类型典型工具技术特征适用场景传统RAGLangChain, Haystack线性流程(检索→生成)通用问答、知识库检索增强型RAGRAGFlow, AutoRAG支持重排序、多路召回优化高精度问答、复杂文档处理轻量级…...

【Android】用 chrome://inspect/#devices 调试H5页面

通常做Android开发的过程中&#xff0c;不可避免的需要遇到去与H5交互&#xff0c;甚至有时候需要去调试H5的信息。 这里分享一下Android工程里如何调试H5页面信息&#xff1a; 直接在浏览器地址栏输入 &#xff1a; chrome://inspect/#devices 直接连接手机usb,打开开发者模式…...

贪心算法精品题

1.找钱问题 本题的贪心策略在于我们希望就可能的保留作用大的5元 class Solution { public:bool lemonadeChange(vector<int>& bills) {std::map<int ,int> _map;for(auto ch:bills){if(ch 5) _map[ch];else if(ch 10){if(_map[5] 0) return false;else{_m…...

七、Spring Boot:初识与项目搭建

深入解析 Spring Boot&#xff1a;初识与项目搭建 Spring Boot 是基于 Spring Framework 的开源 Java 基础框架&#xff0c;旨在简化 Spring 应用的开发过程。它通过“约定优于配置”的理念&#xff0c;极大地减少了开发中的配置工作&#xff0c;同时提供了“开箱即用”的功能…...

WEB1~6通杀

##解题思路 这六道题&#xff0c;通杀了&#xff0c;只因为是PHP的特性 来&#xff0c;看web6&#xff0c;过滤最复杂的正则&#xff0c;而且不能解析成大于999的值&#xff0c;但是&#xff0c;php是弱类型的语言&#xff0c;我只要输入任意字符数字&#xff0c;最终值就为0&…...

孜然单授权系统V2.0PHP授权系统

孜然单授权V1.0系统&#xff0c;延续了2022年开发的孜然多应用授权系统V2.0 变更&#xff1a;多应用变单系统&#xff0c;去除没用的垃圾代码&#xff0c;从0开发&#xff0c;去除了一些没用的功能 完善了开发文档&#xff0c;之前那套是我写着玩的屎山代码&#xff0c;V1.0将展…...

Apache SeaTunnel 构建实时数据同步管道(最新版)

文章作者 王海林 白鲸开源 数据集成引擎研发 Apache SeaTunnel Committer & PMC Member&#xff0c;Apache SkyWalking Committer&#xff0c;多年平台研发经验&#xff0c;目前专注于数据集成领域。 导读 在当今数字化快速发展的时代&#xff0c;数据已然成为企业决策…...

数据保护API(DPAPI)深度剖析与安全实践

Windows DPAPI 安全机制解析 在当今数据泄露与网络攻击日益频繁的背景下&#xff0c;Windows 提供的 DPAPI&#xff08;Data Protection API&#xff09;成为开发者保护本地敏感数据的重要工具。本文将从 双层密钥体系、加密流程、跨上下文加密、已知攻击向量与防御措施、企业…...

服务器离线部署DeepSeek

目标 本次部署的目标是在本地服务器上部署DeepSeek。但是该服务不能连接外网&#xff0c;因此只能使用离线部署的方式。为了一次完成部署。现在云服务器上进行尝试。 云服务器部署尝试 云服务器配置 CentOS72080Ti 11GB 安装准备 1、上传iso并配置为本地yum源 安装前先将…...

ComfyUI:Stable Diffusion 及 LoRA、VAE 、ControlNet模型解析

目录 Stable Diffusion流程 扩散过程 去噪过程 checkpoints LoRA LoRA 位置与结构 LoRA 层与原层的关系 LoRA 层的参数拆解 VAE 训练特定 VAE 时更新的参数部分 ControlNet ControlNet 位置与结构 ControlNet 的训练过程 ControlNet 的参数处理与信息融合 Contr…...

微信小程序:多菜单栏设计效果

一、实现效果 二、代码 wxml 编辑前端界面,步骤 菜单逻辑: 逐步取出数组中的项,首先取出顶部菜单项,然后选中后取出选中的底部数据(左侧菜单+右侧内容),然后点击左侧菜单取出选中的左侧菜单对应的右侧内容 ①这里我的数据是全部封装到一个数组对象的,首先我的循环…...

【Linux Oracle】time命令+oracle exp压缩

Linux && Oracle相关文档&#xff0c;希望互相学习&#xff0c;共同进步 风123456789&#xff5e;-CSDN博客 1.说明 Linux中的time命令&#xff1a;主要用于测量命令的执行时间&#xff0c;并显示该命令在执行过程中所使用的系统资源情况&#xff0c;如CPU时间、内存和…...

20分钟 Bash 上手指南

文章目录 bash 概念与学习目的第一个 bash 脚本bash 语法变量的使用位置参数管道符号&#xff08;过滤条件&#xff09;重定向符号条件测试命令条件语句case 条件分支Arrayfor 循环函数exit 关键字 bash 脚本记录历史命令查询文件分发内容 bash 概念与学习目的 bash&#xff0…...

v4l2子系统学习(三)编写虚拟摄像头驱动

文章目录 1、声明2、前言3、虚拟摄像头驱动编写3.1、编写硬件相关代码3.2、程序示例 1、声明 本文是在学习韦东山《驱动大全》V4L2子系统时&#xff0c;为梳理知识点和自己回看而记录&#xff0c;全部内容高度复制粘贴。 韦老师的《驱动大全》&#xff1a;商品详情 其对应的…...

【前端定位线上问题的多种方案(不依赖 Sentry)】

前端定位线上问题的多种方案&#xff08;不依赖 Sentry&#xff09; &#x1f6e0;️ 一、构建时注入调试信息 &#x1f527; 1. 注入版本信息与 Git 提交哈希 Webpack 配置&#xff1a; // webpack.config.js const webpack require(webpack); const gitRevision require(…...

【虚拟仪器技术】labview操作指南和虚拟仪器技术习题答案(一)

今天是2025年2月24日&#xff0c;画的是fate/Grand Order里面的阿尔托莉雅.卡斯特&#xff0c;武内老师的画。 目录 第1章 第2章 第3章 第4章 第5章 关注作者了解更多 我的其他CSDN专栏 毕业设计 求职面试 大学英语 过程控制系统 工程测试技术 虚拟仪器技术 可编程…...

LabVIEW电能质量分析软件

随着电力系统的复杂性增加&#xff0c;电能质量问题日益突出&#xff0c;传统的电能质量检测装置多采用DSP技术&#xff0c;不仅开发周期长、功能单一&#xff0c;而且在多功能集成方面存在局限性。基于LabVIEW虚拟仪器开发平台的电能质量分析软件利用FFT、STFT、WT、HHT等多种…...

视频裂变加群推广分享引流源码

源码介绍 视频裂变加群推广分享引流源码 最近网上很火&#xff0c;很多人都在用&#xff0c;适合引流裂变推广 测试环境&#xff1a;PHP7.4(PHP版本不限制) 第一次访问送五次观看次数&#xff0c;用户达到观看次数后需要分享给好友或者群,好友必须点击推广链接后才会增加观看次…...

《深度剖析:AI与姿态估计技术在元宇宙VR交互中的应用困境》

在元宇宙的宏大版图里&#xff0c;虚拟现实&#xff08;VR&#xff09;交互是构建沉浸式体验的关键支柱&#xff0c;而人工智能&#xff08;AI&#xff09;与姿态估计技术的融合&#xff0c;本应成为提升交互体验的强大引擎。但在实际应用中&#xff0c;它们面临着诸多复杂且棘…...

项目一 - 任务3:搭建Java集成开发环境IntelliJ IDEA

通过本次实战&#xff0c;我们成功搭建了Java集成开发环境IntelliJ IDEA&#xff0c;并完成了多个任务。首先&#xff0c;安装了IntelliJ IDEA并进行了个性化设置&#xff0c;如选择主题、调整字体和编码等。接着&#xff0c;创建了Java项目、包和类&#xff0c;编写并运行了简…...