Redis 多数据源 Spring Boot 实现

1.前言

本文为大家提供一个 redis 配置多数据源的实现方案,在实际项目中遇到,分享给大家。后续如果有时间会写一个升级版本,升级方向在第5点。

2.git 示例地址

git 仓库地址:https://github.com/huajiexiewenfeng/redis-multi-spring/tree/master/redis-multi-spring

不同的 spring boot 版本,对应的写法可能有小的区别,但思想不变

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.0.1.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.0.1.RELEASE</version></dependency>

3.需求分析

对于 redis 配置多数据源的需求,至少可以分析出以下需求和实现点

  • 在同一个项目中,可以操作多个 redis 服务实例
    • 通过不同的 redisTemplate 可以调用不同的 redis 实例服务
    • Spring @Qualifier 来实现
  • 如果原项目已经引入spring-redis,不能影响 Spring boot 里面默认配置的 redis 自动配置服务
    • org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
    • 要与 RedisAutoConfiguration 里面的 spring bean 完全隔离
  • 因为 host port 等重要参数都在 RedisConnectionFactory 中,所以 RedisConnectionFactory 我们需要配置多个

4.代码实现

不能影响 Spring boot 里面默认配置的 redis 自动配置服务,以 JedisConnectionConfiguration 自动配置实现为例。

  • @ConditionalOnMissingBean({RedisConnectionFactory.class}) 表示如果 spring 容器中存在 RedisConnectionFactory 的具体实现,那么该自动配置 bean 方法不会生效;所以在我们后面的实现中要避免这种写法。

请添加图片描述

4.1 第一个 RedisTemplate 配置

需要特别注意的是,在某些 spring boot 版本里面,如果不写或者少写该配置,使用过程中会报错

  • template.afterPropertiesSet();
  • jedisConnectionFactory.afterPropertiesSet();

为了避免 getJedisConnectionFactory 方法影响 spring redis 默认配置,不能增加 @Bean 注解的方式,用 name 属性区分也不行。

4.1.1 RedisOneProperties Properties 类
@Configuration
@ConfigurationProperties(prefix = "multi.redis.one")
@Data
public class RedisOneProperties {private String host;private int port;private int database = 1;private String password;}
4.1.2 RedisMultiConfiguration 具体配置
    @Autowiredprivate RedisOneProperties properties;// 第一个Redis服务器的配置@Bean("oneRedisTemplate")public RedisTemplate<String, Object> oneRedisTemplate() {JedisConnectionFactory jedisConnectionFactory = this.getJedisConnectionFactory();RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置key的序列化方式StringRedisSerializer keySerializer = new StringRedisSerializer();template.setConnectionFactory(jedisConnectionFactory);template.setKeySerializer(keySerializer);// 设置value的序列化方式Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是无论什么都可以序列化om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 启用DefaultTyping,方便我们反序列化时知道对象的类型om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);valueSerializer.setObjectMapper(om);template.setValueSerializer(valueSerializer);// 设置Hash的key和value序列化方式template.setHashKeySerializer(keySerializer);template.setHashValueSerializer(valueSerializer);// 设置value的泛型类型,这样在存取的时候才会序列化和反序列化成设置的对象类型// 注意:这里只是设置了value的泛型,key还是String类型template.afterPropertiesSet();return template;}private JedisConnectionFactory getJedisConnectionFactory() {JedisPoolConfig poolConfig = new JedisPoolConfig();// 设置连接池参数,例如最大连接数、最大空闲连接数等poolConfig.setMaxTotal(100);poolConfig.setMaxIdle(30);poolConfig.setMinIdle(10);JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);jedisConnectionFactory.setHostName(properties.getHost());jedisConnectionFactory.setPort(properties.getPort());jedisConnectionFactory.setDatabase(properties.getDatabase());jedisConnectionFactory.setPassword(properties.getPassword());jedisConnectionFactory.afterPropertiesSet();return jedisConnectionFactory;}

4.2 第二个 RedisTemplate 配置

以此类推

4.2.1 RedisTwoProperties Properties 类
@Configuration
@ConfigurationProperties(prefix = "multi.redis.two")
@Data
public class RedisTwoProperties {private String host;private int port;private int database = 1;private String password;}
4.2.2 RedisMultiConfiguration 具体配置
    @Autowiredprivate RedisTwoProperties propertiesTwo;@Bean("twoRedisTemplate")public RedisTemplate<String, Object> twoRedisTemplate() {JedisConnectionFactory jedisConnectionFactory = this.getJedisConnectionFactoryTwo();RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置key的序列化方式StringRedisSerializer keySerializer = new StringRedisSerializer();template.setConnectionFactory(jedisConnectionFactory);template.setKeySerializer(keySerializer);// 设置value的序列化方式Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是无论什么都可以序列化om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 启用DefaultTyping,方便我们反序列化时知道对象的类型om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);valueSerializer.setObjectMapper(om);template.setValueSerializer(valueSerializer);// 设置Hash的key和value序列化方式template.setHashKeySerializer(keySerializer);template.setHashValueSerializer(valueSerializer);// 设置value的泛型类型,这样在存取的时候才会序列化和反序列化成设置的对象类型// 注意:这里只是设置了value的泛型,key还是String类型template.afterPropertiesSet();return template;}private JedisConnectionFactory getJedisConnectionFactoryTwo() {JedisPoolConfig poolConfig = new JedisPoolConfig();// 设置连接池参数,例如最大连接数、最大空闲连接数等poolConfig.setMaxTotal(100);poolConfig.setMaxIdle(30);poolConfig.setMinIdle(10);JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);jedisConnectionFactory.setHostName(propertiesTwo.getHost());jedisConnectionFactory.setPort(propertiesTwo.getPort());jedisConnectionFactory.setDatabase(propertiesTwo.getDatabase());jedisConnectionFactory.setPassword(propertiesTwo.getPassword());jedisConnectionFactory.afterPropertiesSet();return jedisConnectionFactory;}

4.3 application.properties 配置文件

spring.application.name=${APPLICATION_NAME:redis-multiple}
server.port=${SERVER_PORT:22216}# spring 默认配置
spring.redis.database=${REDIS_DB_INDEX:1}
spring.redis.flushdb=${REDIS_FLUSHDB:false}
spring.redis.host=${REDIS_HOST:127.0.0.1}
spring.redis.port=${REDIS_PORT:6379}
spring.redis.password=123456#第一个 redis 实例配置
multi.redis.one.database=${REDIS_DB_INDEX:2}
multi.redis.one.flushdb=${REDIS_FLUSHDB:false}
multi.redis.one.host=${REDIS_HOST:127.0.0.1}
multi.redis.one.port=${REDIS_PORT:6379}
multi.redis.one.password=123456#第二个 redis 实例配置
multi.redis.two.database=${REDIS_DB_INDEX:3}
multi.redis.two.flushdb=${REDIS_FLUSHDB:false}
multi.redis.two.host=${REDIS_HOST:127.0.0.1}
multi.redis.two.port=${REDIS_PORT:6379}
multi.redis.two.password=123456

4.4 测试 Demo

@RestController
public class TestController {@Autowiredprivate RedisTemplate<String,String> redisTemplate;@Autowired@Qualifier("oneRedisTemplate")private RedisTemplate<String, Object> redisTemplateOne;@Autowired@Qualifier("twoRedisTemplate")private RedisTemplate<String, Object> redisTemplateTwo;@GetMapping("/test/redis/add")public void profileDetails() {redisTemplate.opsForValue().set("test1", "1");redisTemplateOne.opsForValue().set("test2", 2);redisTemplateTwo.opsForValue().set("test3", 3);}}

浏览器输入

http://127.0.0.1:22216/test/redis/add

执行结果如下:

db1

请添加图片描述

db2
请添加图片描述

db3

请添加图片描述

5.版本升级想法

1.不需要每一个配置都写一个 Properties 类

2.不需要每一个配置都写一个 RedisTemplate 配置

    @Bean("oneRedisTemplate")public RedisTemplate<String, Object> oneRedisTemplate() {...}@Bean("twoRedisTemplate")public RedisTemplate<String, Object> twoRedisTemplate() {...}

3.使用方法可以与 properties 里面的配置直接对应,比如 oneRedisTemplate

    @Autowired@Qualifier("oneRedisTemplate")private RedisTemplate<String, Object> redisTemplateOne;

对应 application.properties 中的 multi.redis.one 前缀

multi.redis.one.database=${REDIS_DB_INDEX:2}
multi.redis.one.flushdb=${REDIS_FLUSHDB:false}
multi.redis.one.host=${REDIS_HOST:127.0.0.1}
multi.redis.one.port=${REDIS_PORT:6379}
multi.redis.one.password=123456

如果有时间,会在下篇文章中实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1473161.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Cesium 二三维热力图

Cesium 二三维热力图 原理&#xff1a;主要依靠heatmap.js包来实现 效果图&#xff1a;

昇思25天学习打卡营第18天|Pix2Pix实现图像转换

Pix2Pix概述 Pix2Pix是基于条件生成对抗网络实现的一种深度学习图像转换模型。Pix2Pix是将cGAN应用于有监督的图像到图像翻译&#xff0c;包括生成器和判别器。 基础原理 cGAN的生成器是将输入图片作为指导信息&#xff0c;由输入图像不断尝试生成用于迷惑判别器的“假”图像…

【JavaSE】异常(Exception)

目录 异常是什么异常的分类异常的处理方法throw抛出异常异常的声明异常的捕获和处理finally 自定义异常类 异常是什么 异常就是程序在进行时的不正常行为&#xff0c;就像之前数组时会遇到空指针异常&#xff08;NullPointerException&#xff09;&#xff0c;数组越界异常&am…

lua入门(1) - 基本语法

本文参考自&#xff1a; Lua 基本语法 | 菜鸟教程 (runoob.com) 需要更加详细了解的还请参看lua 上方链接 交互式编程 Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。 Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用&#xff1a; 如下图: 按…

用Python轻松转换PDF为CSV

数据的可访问性和可操作性是数据管理的核心要素。PDF格式因其跨平台兼容性和版面固定性&#xff0c;在文档分享和打印方面表现出色&#xff0c;尤其适用于报表、调查结果等数据的存储。然而&#xff0c;PDF的非结构化特性限制了其在数据分析领域的应用。相比之下&#xff0c;CS…

Golang | Leetcode Golang题解之第218题天际线问题

题目&#xff1a; 题解&#xff1a; type pair struct{ right, height int } type hp []pairfunc (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].height > h[j].height } func (h hp) Swap(i, j int) { h[i], h[j]…

python: create Envircomnet in Visual Studio Code 创建虚拟环境

先配置python开发环境 1.在搜索栏输入“>" 或是用快捷组合键ctrlshiftP键 就会显示”>",再输入"python:" 选择已经安装好的python的版本,选定至当前项目中&#xff0c;都是按回车 就可以看到创建了一个虚拟环境的默认的文件夹名".venv" 2 …

14-38 剑和诗人12 - RAG+ 思维链 ⇒ 检索增强思维(RAT)

在快速发展的 NLP 和 LLM 领域&#xff0c;研究人员不断探索新技术来增强这些模型的功能。其中一种备受关注的技术是检索增强生成 (RAG) 方法&#xff0c;它将 LLM 的生成能力与从外部来源检索相关信息的能力相结合。然而&#xff0c;最近一项名为检索增强思维 (RAT) 的创新通过…

大数据平台之数据同步

数据同步也成为CDC (Chanage Data Capture) 。Change Data Capture (CDC) 是一种用于跟踪和捕获数据库中数据变更的技术&#xff0c;它可以在数据发生变化时实时地将这些变更捕获并传递到下游系统。以下是一些常用的开源 CDC 方案&#xff1a; 1. Flink CDC Flink CDC 是基于 …

iptables与firewalld

iptables Linux上常用的防火墙软件 1、 防火墙的策略 防火墙策略一般分为两种&#xff0c;一种叫通策略&#xff0c;一种叫堵策略&#xff0c;通策略&#xff0c;默认门是关着的&#xff0c;必须要定义谁能进。堵策略则是&#xff0c;大门是洞开的&#xff0c;但是你必须有身…

迅捷PDF编辑器合并PDF

迅捷PDF编辑器是一款专业的PDF编辑软件&#xff0c;不仅支持任意添加文本&#xff0c;而且可以任意编辑PDF原有内容&#xff0c;软件上方的工具栏中还有丰富的PDF标注、编辑功能&#xff0c;包括高亮、删除线、下划线这些基础的&#xff0c;还有规则或不规则框选、箭头、便利贴…

C++ volatile 关键字

C volatile &#xff08;只有release下才会生效&#xff09; 1、告诉编译器volatile修饰的变量不要进行指令顺序的优化&#xff0c;以保证代码编写者的真实意图&#xff1b; int a 0;int b 10;int c 100;int* p &a;p &b;p &c;如果不加volatile修饰 p , 编译…

香橙派AIpro测评:yolo8+usb鱼眼摄像头的Camera图像获取及识别

一、前言 近期收到了一块受到业界人士关注的开发板"香橙派AIpro",因为这块板子具有极高的性价比&#xff0c;同时还可以兼容ubuntu、安卓等多种操作系统&#xff0c;今天博主便要在一块832g的香橙派AI香橙派AIpro进行YoloV8s算法的部署并使用一个外接的鱼眼USB摄像头…

Bellman equation的不同形式及变化

总忘记贝尔曼方程的推导过程&#xff0c;自己推一遍吧 matrix-vector form就省略了 对于matrix-vector form形式的状态价值贝尔曼方程求解&#xff0c;若已知MDP的动态&#xff08;转移矩阵P和奖励函数R&#xff09;&#xff0c;则计算复杂度的贡献主要来自矩阵求逆&#xff…

HTTP与HTTPS的主要区别

HTTP&#xff08;超文本传输协议&#xff09;与HTTPS&#xff08;超文本传输安全协议&#xff09;的主要区别在于安全性、数据传输方式、默认使用的端口以及对网站的影响。 一、安全性&#xff1a; HTTP是一种无加密的协议&#xff0c;数据在传输过程中以明文形式发送&#x…

日志自动分析-Web---360星图GoaccessALBAnolog

目录 1、Web-360星图(IIS/Apache/Nginx) 2、Web-GoAccess &#xff08;任何自定义日志格式字符串&#xff09; 源码及使用手册 安装goaccess 使用 输出 3-Web-自写脚本&#xff08;任何自定义日志格式字符串&#xff09; 4、Web-机器语言analog&#xff08;任何自定义日…

Ros2中动作通信的goal_handle类型在不同回调函数中的区别

在进行Ros2学习和进行项目的开发途中&#xff0c;准确来说实在动作通信项目的实战中&#xff0c;我给出了以下示例的ActionServer端初始化&#xff0c;并且使用goal_handle进行下一步操作。 self.server ActionServer(self,Nav,"nav",execute_callbackself.execute,…

APP渗透-android12夜神模拟器+Burpsuite实现

一、夜神模拟器下载地址&#xff1a;https://www.yeshen.com/ 二、使用openssl转换证书格式 1、首先导出bp证书 2、将cacert.der证书在kali中转换 使用openssl生成pem格式证书,并授予最高权限 openssl x509 -inform der -in cacert.der -out cacert.pem chmod 777 cacert…

七、MyBatis-Plus高级用法:最优化持久层开发-个人版

七、MyBatis-Plus高级用法&#xff1a;最优化持久层开发 目录 文章目录 七、MyBatis-Plus高级用法&#xff1a;最优化持久层开发目录 一、MyBatis-Plus快速入门1.1 简介1.2 快速入门回顾复习 二、MyBatis-Plus核心功能2.1 基于Mapper接口CRUDInsert方法Delete方法Update方法Se…

加入运动健康数据开放平台,共赢鸿蒙未来

HarmonyOS SDK运动健康服务&#xff08;Health Service Kit&#xff09;是为华为生态应用打造的基于华为帐号和用户授权的运动健康数据开放平台。在获取用户授权后&#xff0c;开发者可以使用运动健康服务提供的开放能力获取运动健康数据&#xff0c;基于多种类型数据构建运动健…