RedisTemplate查詢不到redis中的數據問題(序列化)

RedisTemplate查詢不到redis中的數據問題(序列化)

一.問題描述
存入Redis中的值取出來卻為null,問題根本原因就是RedisTemplate和StringRedisTemplate的序列化問題、代碼示例:

@SpringBootTest
class Redis02SpringbootApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid contextLoads() {Object sd = redisTemplate.opsForValue().get("money");//獲取redis中key為“money"的值。System.out.println(sd);}
}

執行結果: idea斷點看無數據,但是直接連接redis服務器查詢,是有值得

二. 原因分析

redisTemplate 與StringRedisTemplate 區別

區別主要在于他們使用的序列化類。

RedisTemplate使用的是 JdkSerializationRedisSerializer
StringRedisTemplate使用的是 StringRedisSerializer
StringRedisTemplate 繼承了RedisTemplate,在構造器中,直接設置了序列化方式

在這里插入圖片描述
當然從Redis獲取數據的時候也會默認將數據當做字節數組轉化,當數組是正常形式時

在這里插入圖片描述
RedisTemplate就無法獲取到數據,這個時候獲取到的值就是NULL

當Redis當中的數據值是以可讀的形式顯示出來的時候,只能使用StringRedisTemplate才能獲取到里面的數據。所以當你使用RedisTemplate獲取不到數據的時候請檢查一下是不是Redis里面的數據是可讀形式而非字節數組。

使用StringRedisTemplate之后:

@SpringBootTest
class Redis02SpringbootApplicationTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid contextLoads() {Object sd = stringRedisTemplate.opsForValue().get("money");System.out.println(sd);}
}

拿到數據

三.總結
1.redisTemplate只能讀取字節數組,不能讀取字符串形式的。

2.字符串形式的值,只能使用StringRedisTemplate讀取。

四.補充
如果Redistemplate設置了值,在redis客戶端卻獲取不到問題,那該怎么辦?

首先,我們要明白一點Redistemplate可以保存所有可序列化的類型,是一個龐大的類,下面就是RedisTemplate類,可以看到倆個泛型

1 public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware
因為Template中set值時會先調用序列化器將鍵和值都序列化為byte字節數組放入redis數據庫中,在客戶端除非get后的key值是使用同樣的序列化器序列化后的值,否則取不到對應的值。

解決:

自定義Template實現序列化

1 import com.fasterxml.jackson.annotation.JsonAutoDetect;2 import com.fasterxml.jackson.annotation.PropertyAccessor;3 import com.fasterxml.jackson.databind.ObjectMapper;4 import org.springframework.context.annotation.Bean;5 import org.springframework.context.annotation.Configuration;6 import org.springframework.data.redis.connection.RedisConnectionFactory;7 import org.springframework.data.redis.core.RedisTemplate;8 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;9 import org.springframework.data.redis.serializer.StringRedisSerializer;
10 
11 
12 
13 @Configuration
14 public class RedisConfig{
15     // 這是寫好的一個固定模板,大家在企業中,拿去就可以直接使用!
16     // 自己定義了一個 RedisTemplate
17     @Bean
18     @SuppressWarnings("all")
19     public RedisTemplate<String, Object>redisTemplate(RedisConnectionFactory factory) {
20         // 我們為了自己開發方便,一般直接使用 <String, Object>
21         RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
22         template.setConnectionFactory(factory);
23         // Json序列化配置
24         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
25         ObjectMapper om = new ObjectMapper();
26         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
27         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
28         jackson2JsonRedisSerializer.setObjectMapper(om);
29         // String 的序列化
30         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
31         // key采用String的序列化方式
32         template.setKeySerializer(stringRedisSerializer);
33         // hash的key也采用String的序列化方式
34         template.setHashKeySerializer(stringRedisSerializer);
35         // value序列化方式采用jackson
36         template.setValueSerializer(jackson2JsonRedisSerializer);
37         // hash的value序列化方式采用jackson
38         template.setHashValueSerializer(jackson2JsonRedisSerializer);
39         template.afterPropertiesSet();
40         return template;
41     }//StringRedisTemplate默認使用的序列化方式
44     private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
45         redisTemplate.setKeySerializer(new StringRedisSerializer());
46         redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
47         redisTemplate.setHashKeySerializer(new StringRedisSerializer());
48         redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
49         redisTemplate.setConnectionFactory(factory); 
50     }
52 }

五.補RedisTemplate和StringRedisTemplate的區別
RedisTemplate和StringRedisTemplate的區別:

復制代碼

  1. 兩者的關系是StringRedisTemplate繼承RedisTemplate。
  2. 兩者的數據是不共通的;也就是說StringRedisTemplate只能管理StringRedisTemplate里面的數據,RedisTemplate只能管理RedisTemplate中的數據。
  3. SDR默認采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。
    StringRedisTemplate默認采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
    RedisTemplate默認采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

RedisTemplate默認使用的序列類在在操作數據的時候,比如說存入數據會將數據先序列化成字節數組然后在存入Redis數據庫,這個時候打開Redis查看的時候,你會看到你的數據不是以可讀的形式展現的,而是以字節數組顯示

當然從Redis獲取數據的時候也會默認將數據當做字節數組轉化,這都是根據序列化策略來決定的。

而stringredistemplate,默認存入的數據就是原文,因為stringRedistemplate默認使用的是string序列化策略

造成兩者差異的原因是因為在初始化時,兩者使用的序列化策略不同導致的,翻開源碼可以看到,如下:

在這里插入圖片描述
// 該方法是重寫RedisAccessor的方法 RedisAccessor實現了spring的InitializingBean 也就是在啟動時會執行該方法 可以看到該方法默認的序列化為JdkSerializationRedisSerializer

在這里插入圖片描述
可以看到redistemplate在初始化時是無參構造,通過spring的bean加載機制在項目啟動時執行afterPropertiesSet來完成序列化設置,如果需要自定義序列化配置,可以自己寫一個redistemplate的bean,來完成配置。

stringredistemplate就比較簡單了,直接繼承了redistemplate,在初始化時默認使用了string序列化,源碼如下:
在這里插入圖片描述
那么就可以得出一個結論,如果你想使用默認的配置來操作redis,則如果操作的數據是字節數組,就是用redistemplate,如果操作的數據是明文,使用stringredistemplate。

當然在項目中真實使用時,一般是自定義redistemplate的bean實例,來設置具體的序列化策略,說白了就是redistemplate通過自定義bean可以實現和stringredistemplate一樣的序列化,使用起來更加靈活。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/82190.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/82190.shtml
英文地址,請注明出處:http://en.pswp.cn/web/82190.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Net】TCP粘包與半包

文章目錄 TCP粘包與半包1 背景2 粘包&#xff08;packet stick&#xff09;3 半包&#xff08;packet split&#xff09;4 為什么會出現粘包/半包&#xff1f;5 如何解決&#xff1f;6 示例7 總結 TCP粘包與半包 在網絡編程中&#xff0c;粘包和半包問題是常見的 TCP 協議特有…

Leetcode 3566. Partition Array into Two Equal Product Subsets

Leetcode 3566. Partition Array into Two Equal Product Subsets 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3566. Partition Array into Two Equal Product Subsets 1. 解題思路 這一題我的實現還是比較暴力的&#xff0c;首先顯而易見的&#xff0c;若要滿足題目要求&…

QT中更新或添加組件時出現“”qt操作至少需要一個處于啟用狀態的有效資料檔案庫“解決方法”

在MaintenanceTool.exe中點擊下一步 第一個&#xff1a; 第二個&#xff1a; 第三個&#xff1a; 以上任意一個放入資料庫中

52. N-Queens II

題目描述 52. N-Queens II 回溯法 這道題與第51題是一樣的。51. N-Queens-CSDN博客 class Solution {int columns; //從低位到高位起算&#xff0c;第i位為0表示棋盤第i列可以放置皇后&#xff0c;第i位為1表示棋盤第i列不能放置皇后//邊長為n的棋盤分別有2n-1條正斜線和反…

解鎖AI智能Agent的“風格基因”

從“黑箱”到“智能Agent”:LangChain的架構哲學革新 在LangChain出現之前,開發者直接調用LLM API的方式,充滿了“黑箱”操作的挑戰: 緊耦合的業務邏輯與模型調用: 所有的業務邏輯、API調用、記憶管理、錯誤處理等都可能混雜在同一個代碼塊中。這導致代碼脆弱、難以測試,…

大數據運維過程中常見的一些操作

大數據運維是確保大數據系統穩定運行、高效處理數據的關鍵環節。以下是大數據運維過程中常見的一些操作和任務: 1. 集群部署與配置 基礎設施搭建:部署服務器、網絡設備、存儲系統,配置虛擬化環境(如 Docker、Kubernetes)。分布式系統安裝:安裝 Hadoop、Spark、Hive、Kaf…

STM32中,如何理解看門狗

在STM32微控制器中&#xff0c;看門狗&#xff08;Watchdog&#xff09;是一種硬件計時器&#xff0c;用于監控系統運行狀態&#xff0c;防止軟件死鎖或跑飛。其核心機制是&#xff1a;系統需定期“喂狗”&#xff08;復位看門狗計數器&#xff09;&#xff0c;若未及時喂狗&am…

[AI算法] LLM中的gradient checkpoint機制

文章目錄 什么是gradient checkpoint原理使用場景 注意事項 什么是gradient checkpoint gradient checkpoint是一種優化深度學習模型內存使用的技術&#xff0c;尤其在訓練大型模型時非常有用。它通過犧牲計算時間為代價來減少顯存占用。大多數情況下&#xff0c;transformers…

船舶二階非線性響應方程的EKF與UKF參數辨識

船舶二階非線性響應方程的EKF與UKF參數辨識 本文將詳細闡述使用Python實現擴展卡爾曼濾波(EKF)和無跡卡爾曼濾波(UKF)對船舶二階非線性響應方程進行參數辨識的過程。全文包含理論推導、算法實現、仿真驗證及結果分析。—### 1. 船舶二階非線性響應方程建模船舶運動可表示為&am…

【ARM AMBA APB 入門 1.1 -- APB 讀寫寄存器 RTL 實現】

請閱讀【ARM AMBA 總線 文章專欄導讀】 文章目錄 APB 寄存器訪問APB 讀寄存器 RTL 代碼實現APB 寫寄存器 RTL 代碼實現 APB 寄存器訪問 APB 讀寄存器 RTL 代碼實現 APB 總線讀寄存器操作代碼實現&#xff1a; wire [31:0] SOC_PLL_CFG_REG; wire [31:0] SOC_PLL_LOCK_REG; wi…

C++修煉:位圖和布隆過濾器

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《題海拾貝》、《C修煉之路》 1、引言 在計算機科學…

Java大廠后端技術棧故障排查實戰:Spring Boot、Redis、Kafka、JVM典型問題與解決方案

Java大廠后端技術棧故障排查實戰&#xff1a;Spring Boot、Redis、Kafka、JVM典型問題與解決方案 引言 在互聯網大廠&#xff0c;Java后端系統往往承載著高并發、高可用和復雜業務需求。系統架構日益復雜&#xff0c;涵蓋微服務、緩存、消息隊列、數據庫等多種組件&#xff0…

交叉編譯tcpdump工具

1.導出交叉編譯工具鏈 export PATH$PATH:/opt/rockchip/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin 下載源碼包libpcap-1.10.5&#xff0c;配置、并編譯安裝。 github倉庫地址 ./configure --hostarm-linux CCarm-linux-gnueabihf-gcc --prefix$PWD/install …

Pytest Fixture 是什么?

Fixture 是什么&#xff1f; Fixture 是 Pytest 測試框架的核心功能之一&#xff0c;用于為測試函數提供所需的依賴資源或環境。它的核心目標是&#xff1a; ? 提供測試數據&#xff08;如模擬對象、數據庫記錄&#xff09; ? 初始化系統狀態&#xff08;如配置、臨時文件&a…

【深度剖析】流處理系統性能優化:解決維表JOIN、數據傾斜與數據膨脹問題

目錄 前言:為什么你的流處理作業總是慢? 一、維表JOIN優化:從普通連接到高性能查詢 1.1 時態表的雙面性 1.2 Lookup Join 優化 1.3 多表JOIN優化策略 二、數據傾斜:單分區也會遇到的隱形殺手 2.1 單分區數據傾斜 2.2 熱點鍵打散技術 2.3 時間窗口預聚合 三、數據…

Codeforces Round 1028 (Div. 2)(ABC)

A. Gellyfish and Tricolor Pansy 翻譯&#xff1a; 水母和小花在玩一個叫 “決斗 ”的游戲。 水母有 a HP&#xff0c;花花有 b HP。 它們各有一個騎士。水母的騎士有 c HP&#xff0c;而花花的騎士有 d HP。 他們將進行一輪游戲&#xff0c;直到其中一方獲勝。對于 k1、2、.…

數字創新智慧園區建設及運維方案

該文檔是 “數字創新智慧園區” 建設及運維方案,指出傳統產業園區存在管理粗放等問題,“數字創新園區” 通過大數據、AI、物聯網、云計算等數字化技術,旨在提升園區產業服務、運營管理水平,增強競爭力,實現綠色節能、高效管理等目標。建設內容包括智能設施、核心支撐平臺、…

緩存一致性協議的影響

在操作系統中&#xff0c;線程切換相比進程切換更輕量級的關鍵原因之一是 緩存&#xff08;Cache&#xff09;的有效性&#xff0c;尤其是對 CPU 緩存&#xff08;如 L1/L2/L3&#xff09;和 TLB&#xff08;Translation Lookaside Buffer&#xff09;的影響。以下從緩存角度詳…

六月一日python-AI代碼

python 運行 import turtle as t # 導入turtle庫并簡稱為t&#xff0c;用于圖形繪制 import random # 導入random庫&#xff0c;用于隨機數生成t.delay(0) # 設置繪圖延遲為0&#xff0c;加快繪圖速度 colors ["red", "blue", "gr…

58、辣椒種植學習

辣椒&#xff08;學名&#xff1a;Capsicum annuum&#xff09;屬于茄科辣椒屬&#xff0c;是一種重要的蔬菜兼調味作物&#xff0c;具有較高的經濟價值和營養價值。其果實富含維生素C、辣椒素等成分&#xff0c;既可鮮食&#xff0c;也可加工成干辣椒、辣椒粉、辣椒醬等產品&a…