Spring Boot 3 配置 Redis 兼容单例和集群
配置项
Spring Boot 3.x 的 redis 配置和 Spring Boot 2.x 是不一样的, 路径多了一个data
spring:...data:redis:host: @redis.host@port: @redis.port@password: @redis.password@database: @redis.database@
兼容单例和集群的配置
开发时一般用一个Redis单例就足够, 测试和生产环境再换成集群, 但是在application.yml中默认的 Redis 单例和集群配置格式是不同的, 如果要用同一套格式兼容两种配置, 需要自定义 RedisConnectionFactory 这个bean的初始化.
@Configuration
public class RedisConfig {@Value("${spring.data.redis.host}")public String host;@Value("${spring.data.redis.port}")public int port;@Value("${spring.data.redis.password}")public String password;@Value("${spring.data.redis.database}")public int database;@Beanpublic RedisTemplate<String, String> redisStringTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setDefaultSerializer(new StringRedisSerializer());return redisTemplate;}@Beanpublic RedisTemplate<String, byte[]> redisBytesTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, byte[]> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);RedisSerializer<String> redisKeySerializer = new StringRedisSerializer();redisTemplate.setKeySerializer(redisKeySerializer);redisTemplate.setHashKeySerializer(redisKeySerializer);redisTemplate.setValueSerializer(RedisSerializer.byteArray());redisTemplate.setHashValueSerializer(RedisSerializer.byteArray());return redisTemplate;}@Beanpublic RedisConnectionFactory lettuceConnectionFactory() {if (host.contains(",")) {RedisClusterConfiguration config = new RedisClusterConfiguration(Arrays.asList(host.split(",")));config.setMaxRedirects(3);if (password != null && !password.isEmpty()) {config.setPassword(RedisPassword.of(password));}LettuceConnectionFactory factory = new LettuceConnectionFactory(config);factory.afterPropertiesSet();return factory;} else {RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();config.setHostName(host);config.setPort(port);config.setDatabase(database);if (password != null && !password.isEmpty()) {config.setPassword(RedisPassword.of(password));}LettuceConnectionFactory factory = new LettuceConnectionFactory(config);factory.afterPropertiesSet();return factory;}}}
这样, 当配置改为集群时, 只需要修改 spring.data.redis.host 的内容为 1.1.1.1:6379,1.1.1.2:6379,1.1.1.3:6379
这样的格式就可以了.
使用 Byte 作为值存储
ByteUtil.java
public class ByteUtil {public static byte[] toByte(String str) {if (str == null) return null;return str.getBytes();}public static byte[][] toByte(String[] strs) {if (strs == null) return null;byte[][] arr = new byte[strs.length][];for (int i = 0; i < strs.length; i++) {arr[i] = strs[i].getBytes();}return arr;}public static String toString(byte[] bytes) {return bytes == null ? null : new String(bytes);}public static Set<String> toString(Set<byte[]> byteset) {if (byteset == null) return null;return byteset.stream().map(String::new).collect(Collectors.toSet());}public static List<String> toStrings(List<byte[]> byteslist) {if (byteslist == null) return null;return byteslist.stream().map(String::new).collect(Collectors.toList());}public static byte[] toByte(int x) {ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);buffer.putInt(x);return buffer.array();}public static int toInteger(byte[] bytes) {ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);buffer.put(bytes);buffer.flip();//need flipreturn buffer.getInt();}public static byte[] toByte(long x) {ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);buffer.putLong(x);return buffer.array();}public static long toLong(byte[] bytes) {ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);buffer.put(bytes);buffer.flip();//need flipreturn buffer.getLong();}public static byte[] toByte(Object object) {if (object == null) return null;try (ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos)) {oos.writeObject(object);return baos.toByteArray();} catch (IOException e) {throw new RuntimeException(e);}}public static <T> List<T> toObjs(List<byte[]> byteslist) {if (byteslist == null) return null;List<T> list = new ArrayList<>();for (byte[] bytes : byteslist) {T t = toObj(bytes);list.add(t);}return list;}@SuppressWarnings("unchecked")public static <T> T toObj(byte[] bytes) {if (bytes == null || bytes.length < 8) return null;try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);ObjectInputStream ois = new ObjectInputStream(bais)) {return (T)ois.readObject();} catch (IOException|ClassNotFoundException e) {throw new RuntimeException(e);}}
}
在服务中的调用方式
@Autowired
private RedisTemplate<String, byte[]> redisBytesTemplate;@Override
public Boolean hasKey(String key) {return redisBytesTemplate.hasKey(key);
}@Override
public Boolean hashHasKey(String key, String field) {return redisBytesTemplate.opsForHash().hasKey(key,field);
}@Override
public Integer hashGetInt(String key, String field) {HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();byte[] bytes = opsForHash.get(key, field);return bytes == null? null : ByteUtil.toInteger(bytes);
}@Override
public void hashSetInt(String key, String field, int value) {HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();opsForHash.put(key, field, ByteUtil.toByte(value));
}@Override
public <T> T hashGetObj(String key, String field) {HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();return ByteUtil.toObj(opsForHash.get(key, field));
}@Override
public <T> void hashSetObj(String key, String field, T value) {HashOperations<String, String, byte[]> opsForHash = redisBytesTemplate.opsForHash();opsForHash.put(key, field, ByteUtil.toByte(value));
}/*** @param timeout seconds to block*/
@Override
public <T> T bLPopObj(int timeout, String key) {ListOperations<String, byte[]> opsForList = redisBytesTemplate.opsForList();byte[] bytes = opsForList.leftPop(key, timeout, TimeUnit.SECONDS);return ByteUtil.toObj(bytes);
}@Override
public <T> Long rPush(String key, T value) {ListOperations<String, byte[]> opsForList = redisBytesTemplate.opsForList();return opsForList.rightPush(key, ByteUtil.toByte(value));
}
参考
- https://vincentbogousslavsky.com/post/configuration-for-spring-data-redis-reactive-for-connecting
创建 RedisClusterConfiguration - https://blog.csdn.net/weixin_67601403/article/details/129706748
创建 RedisConnectionFactory lettuceConnectionFactory - https://cloud.tencent.com/developer/article/2371793
默认的级联配置方式
相关文章:
Spring Boot 3 配置 Redis 兼容单例和集群
配置项 Spring Boot 3.x 的 redis 配置和 Spring Boot 2.x 是不一样的, 路径多了一个data spring:...data:redis:host: redis.hostport: redis.portpassword: redis.passworddatabase: redis.database兼容单例和集群的配置 开发时一般用一个Redis单例就足够, 测试和生产环境…...
unsat钱包签名算法解析
unsat钱包签名算法解析 在数字货币领域,安全性是至关重要的,而签名算法则是确保交易和信息不可伪造的基础。本文将深入解析 unsat 钱包中使用的签名算法,重点关注如何生成和验证消息签名。 1. 签名算法概述 unsat 钱包使用 ECDSAÿ…...
mysql删除唯一索引
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...
学习之面试题:偏函数
偏函数(Partial Function)是 Python 中的一个实用工具,通常用于函数式编程中,可以固定一个函数的部分参数,从而生成一个新的函数。偏函数在 Python 中通常通过 functools.partial 实现。在面试中,考察偏函数…...

面试技术点
Java 一、jvm模块 jvm是什么? 是一用用于计算设备的规范,虚构出来的计算机,在计算机上仿真模拟各种计算机功能来实现 jvm 作用是什么? java中所有类必须装载jvm中才能运行,这个装载工作有jvm装载器完成,.class类型文件能在jvm虚拟器中运行,但不能直接在系统中运行,需要…...

基础sql
在执行删除操作之前,建议先运行一个 SELECT 查询来确认你要删除的记录。这可以帮助你避免误删数据。 删除字段id默认值为空字符串的所有数据 delete from users where id ; 删除字段id默认值为null的所有数据 delete from users where id is null; 删除字段upd…...

Jenkins整合Docker实现CICD自动化部署(若依项目)
前期准备 提前准备好jenkins环境 并且jenkins能使用docker命令,并且已经配置好了jdk、node、maven环境,我之前写了安装jenkins的博客,里面讲得比较详细,推荐用我这种方式安装 docker安装jenkins,并配置jdk、node和m…...
kali chrome 安装 hackbar
HackBar 是一个用于在 Kali Linux 中快速测试 SQL 注入和 XSS 漏洞的 Chrome 扩展程序。以下是如何在 Kali Linux 上安装 HackBar 的步骤: 首先,你需要确保你的系统已经安装了 Google Chrome 或 Chromium。如果没有安装,你可以使用以下命令安…...

一文了解 Linux 系统的文件权限管理
文章目录 引入Linux文件权限模型查看文件权限权限信息解析修改文件权限符号模式八进制数字模式 引入 在Linux操作系统中,我们想查看我们对文件拥有哪些权限时,可以在终端键入ls -l或ll命令,终端会输出当前路径下的文件信息,如文件…...

Spark:DataFrame介绍及使用
1. DataFrame详解 DataFrame是基于RDD进行封装的结构化数据类型,增加了schema元数据,最终DataFrame类型在计算时,还是转为rdd计算。DataFrame的结构化数据有Row(行数据)和schema元数据构成。 Row 类型 表示一行数据 …...

Linux系统:本机(物理主机)访问不了虚拟机中的apache服务问题的解决方案
学习目标: 提示:本文主要讲述-本机(物理主机)访问不了虚拟机中的apache服务情况下的解决方案 Linux系统:Ubuntu 23.04; 文中提到的“本机”:代表,宿主机,物理主机; 首先,…...

望繁信科技成功签约国显科技 流程挖掘助力制造业智造未来
近日,上海望繁信科技有限公司(简称“望繁信科技”)成功与深圳市国显科技有限公司(简称“国显科技”)达成合作。国显科技作为全球领先的TFT-LCD液晶显示及Mini/Micro LED显示产品供应商,致力于为笔记本、手机…...

枚举在Java体系中的作用
1. 枚举 枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式: //用public static final修饰常量 public static final int RED 1; public static final int GREEN 2; public static f…...

『气泡水』Web官网 案例赏析
前言 Schweppes,作为一家享誉全球的气泡水品牌,致力于与年轻消费者建立更紧密的联系,并提升品牌影响力。为此,其打造了一个充满创意和高度互动性的官网,利用前端技术和动画效果,将产品特性与用户浏览体验完…...

【前端】制作一个简单的网页(2)
单标签组成的元素 这类标签不需要内容产生效果,通常表示对网页的某种行为,它们不用标记任何内容,开始即是结束。 比如,<hr>标签的作用是在网页中添加一条分割线,它仅包含开始标签,是一个单标签元素。…...

OpenAI Canvas:提升编程与写作效率的全新工作界面
随着人工智能技术的飞速发展,大语言模型(LLM)不仅限于生成文本,还能逐步扩展至编程、设计等任务的支持。近期,OpenAI 推出了一个名为 Canvas 的全新功能,专门用于协助用户进行编程和写作。这一功能与 Claud…...

将SpringBoot的Maven项目打成jar包和war包
先需要明确的是,该项目打包的形态是可执行的jar包,还是在tomcat下运行的war包。 springboot自带的maven打包 1.创建一个springboot web项目 1.api控制层HelloWorld.java RestController RequestMapping("/hello") public class HelloWorld …...
【Iceberg分析】Spark与Iceberg集成之常用存储过程
文章目录 Spark与Iceberg集成之常用存储过程调用语法调用样例表快照管理快照回滚根据snapshotid进行回滚根据timestamp进行回滚 设置表当前生效的快照 表元数据管理设置快照过期时间清除孤岛文件重写数据文件运用参数示例optionsGeneral OptionsOptions for sort strategyOptio…...

[旧日谈]关于Qt的刷新事件频率,以及我们在Qt的框架上做实时的绘制操作时我们该关心什么。
[旧日谈]关于Qt的刷新事件频率,以及我们在Qt的框架上做实时的绘制操作时我们该关心什么。 最近在开发的时候,发现一个依赖事件来刷新渲染的控件会导致程序很容易异常和崩溃。 当程序在运行的时候,其实软件本身的负载并不高,所以…...

云上考场小程序+ssm论文源码调试讲解
2 关键技术简介 2.1 微信小程序 微信小程序,简称小程序,英文名Mini Program,是一种全新的连接用户与服务的方式,可以快速访问、快速传播,并具有良好的使用体验。 小程序的主要开发语言是JavaScript,它与…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...