Redis-08 SpringBoot集成Redis常见问题

        SpringBoot集成Redis的教程网上很多,总体来说就是三个步骤:添加依赖、修改配置文件、自定义Redis配置类(自定义序列化器),具体步骤可自行搜索,本文主要解惑集成中的常见疑问。

1,选择什么依赖?

        SpringBoot集成Redis共有三种依赖可选:spring-boot-starter-data-redis,spring-data-redis,redisson-spring-boot-start。先说结果:

        优先选择 ​​spring-boot-starter-data-redis​​,快速实现缓存功能,避免过度设计。

        高并发或分布式系统​​,直接使用 ​​redisson-spring-boot-starter​​,其内置的分布式锁、限流器可显著降低复杂度。

    1),spring-boot-starter-data-redis(官方推荐)

        定位​​:Spring Boot官方提供的开箱即用方案,封装了Spring Data Redis的核心功能。
​​        底层客户端​​:默认使用Lettuce(基于Netty的非阻塞I/O),也可切换为Jedis(传统阻塞式I/O)。
​​        核心优势​​:
​​                自动化配置​​:仅需配置spring.redis.host/port等参数即可自动初始化连接池和RedisTemplate。
​​                统一操作接口​​:提供RedisTemplate和StringRedisTemplate,支持字符串、哈希、列表等数据结构操作。
​​                与Spring生态无缝集成​​:支持Spring Cache抽象、事务管理和Repository模式。
​​        局限性​​:
                高级功能(如分布式锁、限流)需自行实现(如Lua脚本或第三方库)。
                默认序列化方式为JDK序列化(可读性差),需手动配置JSON序列化。
        适用场景:简单缓存、基础数据操作
        性能:中等(依赖Lettuce/Jedis)
        高级功能:需自行实现

    2),spring-data-redis

        非SpringBoot项目(如Springmvc,Spring)引入的依赖,不包含客户端、连接池,需手动配置连接工厂。spring-boot-starter-data-redis​​已包含​​ spring-data-redis。

    3),redisson-spring-boot-start(分布式redis依赖)

        定位​​:Redisson提供的增强方案,支持分布式对象和高级分布式功能。
        核心优势​​:
                开箱即用的分布式工具​​:内置分布式锁(支持自动续期)、信号量、限流器(RRateLimiter)、延迟队列等。
        高性能本地缓存​​:通过RLocalCachedMap减少网络IO,缓存命中率提升显著(压测可达百万级QPS)。
        异步与响应式支持​​:基于Netty的非阻塞通信,支持RBatch批量操作提升吞吐量。
        局限性​​:
                学习成本高,需理解分布式对象(如RMap、RBucket)的API设计。
                部分简单操作(如基础字符串存取)代码量略多于RedisTemplate。
        适用场景:分布式锁、限流、高并发系统
        性能:高于spring-boot-starter-data-redis,基于Netty异步+本地缓存优化
        高级功能:内置分布式工具

2,多模块怎么将Redis配置文件和配置类独立出来,避免各模块重复工作?

  • 微服务系统可将做配置中心;
  • 非微服务系统可设置一个base-module模块,在需要使用redis的模块的pom文件中引入该模块的依赖。

3,为什么要配置Redis连接池,其作用是什么,有哪些连接池可选?

        Redis连接池(Pool)是指客户端连接池,是为了管理客户端(如Jedis或Lettuce)与Redis服务器之间的网络连接而存在的。

        Redis服务端可简单理解成单线程应用(实际非单线程,参考文章Redis-02 单线程与高性能-CSDN博客),无连接池一说。

        Redis客户端(即自己的程序,是多线程的)通常是Springboot应用,是多线程的web服务,可同时处理上万用户请求,可能产生并发的Redis操作请求,配置客户端连接池,可在客户端请求Redis时,减少客户端连接Redis服务器带来的创建、销毁等开销(如建立tcp连接、tcp断开、认证等)。

4,RedisTemplate和StringRedisTemplate是什么,有什么区别,生产环境一般怎么使用?

        科普:

        它们都是Spring Data Redis提供的核心工具类,用于在Java应用中与Redis服务器进行交互,封装了底层的连接管理、序列化/反序列化等复杂操作,让你可以用面向对象的方式操作Redis。

        区别:

        核心的区别是默认的序列化器不同。序列化器决定了Java对象如何转换成二进制数据存入Redis,以及如何从二进制数据变回Java对象。可以把 StringRedisTemplate 看作是 RedisTemplate<String, String> 的一个特例,它强制要求键和值都是字符串,并使用字符串序列化器。

RedisTemplate与StringRedisTemplate对比
StringRedisTeplateRedisTeplate
key序列化器StringRedisSerializerJdkSerializationRedisSerializer
value序列化器StringRedisSerializerJdkSerializationRedisSerializer
存储结果可读的字符串。set("name", "Alice") 在Redis中存的就是 "Alice"不可读的JDK序列化字节码。存进去是乱码,如 \xac\xed\x00\x05t\x00\x04name
使用场景处理字符串和文本结构的数据处理复杂的Java对象(但需要配置序列化器)

        生产环境怎么使用:

        优先使用 StringRedisTemplate 来处理字符串键值对。

        对于需要存储复杂Java对象的场景,会配置一个专门化的 RedisTemplate(例如 RedisTemplate<String, Object>),并将其值的序列化器改为JSON序列化器(如 Jackson2JsonRedisSerializer 或 GenericJackson2JsonRedisSerializer)。

        绝对要避免使用默认配置(JDK序列化)的 RedisTemplate!

5,生产环境怎么设置RedisTemplate的序列化器?

        以常用的GenericJackson2JsonRedisSerializer序列化器为例,生产环境各种配置方式如下:

        1),简单快速使用设置

@Configuration
public class RedisTemplateConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置Key和HashKey的序列化器为StringRedisSerializertemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置Value和HashValue的序列化器为GenericJackson2JsonRedisSerializer (JSON格式)GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();return template;}}

        上述序列化器设置完成即可使用Redis,但是有个弊端,假如存放的是对象,如User(id, name, age, sex, position),在Redis中是Json数据格式,web端获取User时,返回的是LinkedHashMap<String, Object>,无法直接强转成User对象。同样,如果存放的是List<User>,在Redis中是Json数组,返回则是List<LinkedHashMap>。

        2),优化序列化设置

@Configuration
public class RedisTemplateConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置Key和HashKey的序列化器为StringRedisSerializertemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置Value和HashValue的序列化器为GenericJackson2JsonRedisSerializer (JSON格式),并配置返回序列化类型// 创建 ObjectMapper 并配置多态类型支持/*** 作用:* 这行代码配置 ObjectMapper 在序列化 JSON 时,自动嵌入类的类型信息。* 这样在反序列化时,Jackson 就能根据这些信息准确地还原成原始对象类型,而不是简单的 LinkedHashMap。*/ObjectMapper objectMapper = new ObjectMapper();objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, // 非严格验证,更严谨的使用方式是将类型验证器LaissezFaireSubTypeValidator替换为TypeValidatorObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();return template;}}

        如上述代码,多添加了ObjectMapper,并激活了如下几个配置:

  • LaissezFaireSubTypeValidator.instance:配置了对象的类型验证器,允许反序列化任何类型(有安全风险,但操作简单方便开发)。
  • ObjectMapper.DefaultTyping.NON_FINAL:指定哪些类型需要包含类型信息。NON_FINAL:所有非final类都需要包含类型信息。可选项还有:NON_CONCRETE_AND_ARRAYS(非具体类型和数组), EVERYTHING(所有类型)
  • JsonTypeInfo.As.PROPERTY:指定类型在Redis中如何潜入到JSON里。PROPERTY:作为单独属性添加到JSON中。可选项还有:WRAPPER_ARRAY(包装为数组),WRAPPER_OBJECT(包装为对象)。

        添加如上反序列化配置后,假如存放的是List<User>,则Redis中存储格式如下:

["java.util.ArrayList",[["com.example.User",{"id":1,"name":"张三"}],["com.example.User", {"id":2,"name":"李四"}]]
]

        客户端获取数据时,反序列化就知道该对象是List,内部对象是User,这样结果就可以直接强转。

        3),反序列化类型验证器

package com.mango.basedata.common;import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisTemplateConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置Key和HashKey的序列化器为StringRedisSerializertemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置Value和HashValue的序列化器为GenericJackson2JsonRedisSerializer (JSON格式),并配置返回序列化类型// 创建 ObjectMapper 并配置多态类型支持/*** 作用:* 这行代码配置 ObjectMapper 在序列化 JSON 时,自动嵌入类的类型信息。* 这样在反序列化时,Jackson 就能根据这些信息准确地还原成原始对象类型,而不是简单的 LinkedHashMap。*/ObjectMapper objectMapper = new ObjectMapper();// 创建更安全的类型验证器(白名单机制)BasicPolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder().allowIfSubType("com.example.models.entity").allowIfSubType("java.util.ArrayList").allowIfSubType("java.util.HashMap").build();objectMapper.activateDefaultTyping(typeValidator,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();return template;}}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构:选择排序 (Selection Sort)

目录 从学生排队开始 算法的初始状态和核心操作 代码的逐步完善 第一阶段&#xff1a;定义函数框架和外层循环 第二阶段&#xff1a;实现“寻找最小元素”的逻辑&#xff08;内层循环&#xff09; 第三阶段&#xff1a;完成“交换”操作 复杂度与特性分析 时间复杂度 (…

Django Admin 管理工具

一、简介Django Admin 是 Django 框架最受欢迎和强大的特性之一。它是一个自动生成的管理后台&#xff0c;允许开发者无需或仅需编写少量代码&#xff0c;就能对网站的数据模型&#xff08;数据库中的表&#xff09;进行直观的增、删、改、查&#xff08;CRUD&#xff09;操作。…

园区智慧水电管理系统:让能源管理从“成本黑洞”变“利润引擎”

园区智慧水电管理系统&#xff0c;是一套专为产业园区、科技园、企业总部等大型空间设计的集智能计量、远程管控、自动计费、能耗分析于一体的数字化能源解决方案。它用技术手段解决水电管理中的“抄表难、收费乱、浪费多、数据缺”四大顽疾&#xff0c;真正实现降本、提效、控…

DeepSeek应用技巧-通过MCP打造数据分析助手

本文章将通过MCP服务来打造一个数据分析助手&#xff0c;可以直接读取本地的excel或csv的文件&#xff0c;然后生成可视化的报告并保存在本地&#xff0c;十分有应用和实践的价值&#xff0c;话不多说&#xff0c;我们开始手把手搭建。一、知识应用&#xff08;1&#xff09;Fu…

React Hooks 完全指南:从基础到高级的实战技巧

概述 React Hooks 是 React 16.8 引入的新特性&#xff0c;允许在函数组件中使用状态和其他 React 特性。根据数据的使用场景和更新机制&#xff0c;可以将 Hooks 分为三大类&#xff1a; 1. 保存只读数据 useMemo 用途&#xff1a; 缓存计算结果&#xff0c;避免重复计算 …

PCIe 6.0 vs 5.0:带宽翻倍背后的技术革命

PCIe 6.0 vs 5.0&#xff1a;带宽翻倍背后的技术革命在数据中心、AI计算和高速存储需求爆炸式增长的今天&#xff0c;传统接口带宽已成为系统性能提升的瓶颈。PCIe 6.0的推出正是为了解决这一挑战&#xff0c;它通过革命性的技术创新&#xff0c;在保持向后兼容的同时实现了带宽…

突破传统企业组网瓶颈:某科技公司智能组网服务项目深度解析

在现代企业的数字化转型过程中&#xff0c;稳定、高效、安全的网络基础设施已成为业务发展的关键。然而&#xff0c;传统组网方案往往面临诸多挑战&#xff0c;如网络性能不足、组网复杂度高、扩展性不佳、以及安全防护薄弱等问题。为了解决这些痛点&#xff0c;某科技公司通过…

ubuntu单机实现10000个连接同时在线测试

连接前 成功连接后 前端测试连接脚本: c_5k.sh !/bin/bash ulimit -n 100000 # client_simulator.sh SERVER_IP="192.168.0.106" SERVER_PORT=8080 MAX_CLIENTS=5000 BATCH_SIZE=100echo "Starting $MAX_CLIENTS clients to $SERVER_IP:$SERVER_PORT"…

防护墙技术(一):NAT

###源NAT基本原理 NAT&#xff08;Network Address Translation&#xff09;网络地址转换技术 源NAT技术对IP报文的源地址进行转换&#xff0c;将私有IP地址转换为公网IP地址&#xff0c;使大量私网用户可以利用少量公网IP地址访问internet&#xff0c;大大减少对公网IP的消耗 …

动态规划2(c++)

酒鬼#include <bits/stdc.h> using namespace std; int main() {int n;cin>>n;int a[10010];for(int i 1;i<n;i){cin>>a[i];}int dp[1010][5] {0};dp[0][0] 0;dp[1][0] 0;dp[1][1] a[1];dp[1][2] 0;dp[2][0] a[1];dp[2][1] a[2];dp[2][2] a[1]a[…

「LangChain 学习笔记」LangChain大模型应用开发:代理 (Agent)

「LangChain大模型应用开发」 系列文章目录&#xff1a; LangChain大模型应用开发&#xff1a;模型&#xff0c;提示和输出解释器 LangChain大模型应用开发&#xff1a;储存(Memory) LangChain大模型应用开发&#xff1a;模型链&#xff08;Chains&#xff09; LangChain大模…

python pyqt5开发DoIP上位机【介绍】

目录文章合集一、核心功能概述二、主要模块解析1. 导入的库2. 辅助函数3. DOIP协议处理&#xff08;DOIPProtocol类&#xff09;4. 网络工具&#xff08;NetworkUtils类&#xff09;5. 通信线程&#xff08;DOIPCommunicationThread类&#xff09;6. UDS命令输入组件&#xff0…

从零实现一个可扩展的规则解析引擎 —— 支持 AND/OR 优先级、短路求值与多类型运算符

在日常业务开发中&#xff0c;我们经常需要基于一些“规则”来决定程序的走向。比如&#xff1a; 客服机器人 根据用户问题领域和复杂度选择不同的模型&#xff1b;营销系统 根据用户画像匹配不同优惠券&#xff1b;风控引擎 根据请求参数、时间、分值判定是否放行。 这些规则往…

Preprocessing Model in MPC 3 - 基于同态加密的协议 - Over Rings 环

参考论文&#xff1a;SoK: Multiparty Computation in the Preprocessing Model MPC (Secure Multi-Party Computation) 博士生入门资料。抄袭必究。 本系列教程将逐字解读参考论文(以下简称MPCiPPM)&#xff0c;在此过程中&#xff0c;将论文中涵盖的40篇参考文献进行梳理与讲…

uni-app 跨平台项目的 iOS 上架流程:多工具组合的高效协作方案

跨平台框架的兴起&#xff0c;让许多团队选择 uni-app 来开发移动应用。 一套代码多端运行&#xff0c;确实大大降低了研发成本&#xff0c;但当项目进入 iOS 上架阶段 时&#xff0c;很多团队依旧面临挑战&#xff1a;证书复杂、环境不统一、上传繁琐。 本文结合实战经验&…

掌握 Linux 文件权限:chown 命令深度解析与实践

在 Linux 系统的日常运维与开发工作里&#xff0c;文件权限管理是保障系统安全、规范文件访问的关键环节。其中&#xff0c;chown 命令作为修改文件所有者及关联组的核心工具&#xff0c;对精准把控文件权限起着重要作用。接下来&#xff0c;我们将全面拆解 chown 命令&#xf…

计算机算术7-浮点基础知识

1. 浮点表示其中b表示基底&#xff0c;e表示指数&#xff0c;s表示尾数&#xff0c;注意在s的表示过程中&#xff0c;有个隐藏1.同时还有个符号位从下面这个图可以看出&#xff0c;向上溢出和向下溢出的概念&#xff0c;overflow表示的是数的绝对值超过了最大的表示范围&#x…

设计模式8-命令模式

定义 Command Partern: 将一个请求封装成一个对象&#xff0c;从而让你使用不同的请求把客户端参数化&#xff0c;对请求排队或者记录请求日志&#xff0c;可以提供命令的撤销和恢复功能。&#xff08;核心思想是将“动作”与“执行者”解耦&#xff09; 场景 GUI&#xff1a;…

数据结构(顺序表力扣刷题)

1.移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k&#xff0c;要通过此题&#xff0c;您需要执行以下操作&…

机器学习 - Kaggle项目实践(6)Dogs vs. Cats Redux: Kernels Edition 猫狗二分类

Dogs vs. Cats Redux: Kernels Edition | Kaggle 任务&#xff1a;给定猫狗图像数据集 进行二分类。 Cats or Dogs - using CNN with Transfer Learning | Kaggle&#xff08;参考&#xff09; Cats or Dogs | Kaggle &#xff08;我的kaggle&#xff09; 本文介绍了使用Re…