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,它与…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...