一、初步認識
1、NoSQL
SQL = 關系型數據庫(表結構,強一致)NoSQL = 非關系型數據庫(靈活結構,最終一致,水平擴展爽)
維度 | SQL(關系型) | NoSQL(非關系型) |
---|---|---|
數據模型 | 二維表:行列、固定模式(Schema) | 鍵值、文檔、列族、圖等,可動態加字段 |
查詢語言 | 標準 SQL:SELECT / JOIN / GROUP / TRANSACTION | 各寫各的:Redis 命令、MongoDB JSON DSL、Cassandra CQL… |
事務 & 一致性 | ACID 強一致(原子、一致、隔離、持久) | BASE 最終一致(基本可用、軟狀態、最終一致) |
擴展方式 | 縱向擴容(買更貴的機器)+ 復雜分庫分表 | 橫向擴容(加普通機器就 OK) |
典型代表 | MySQL、PostgreSQL、Oracle、SQL Server | Redis(鍵值)、MongoDB(文檔)、Cassandra(列族)、Neo4j(圖) |
適用場景 | 復雜關聯、賬務、報表、強一致核心業務 | 高并發讀寫、海量數據、靈活模式、快速迭代 |
2、Redis
Redis(Remote Dictionary Server)是一個開源的、基于內存的 高性能鍵值數據庫,它支持多種數據結構,常用于緩存、消息隊列、排行榜、實時統計等場景。
特性 | 說明 |
---|---|
內存存儲 | 數據主要存在內存中,讀寫速度極快(每秒十萬次以上) |
持久化支持 | 支持將內存數據保存到磁盤(RDB 快照 和 AOF 日志) |
多種數據結構 | 字符串、列表、集合、哈希、有序集合、位圖、HyperLogLog、Stream 等 |
支持過期時間 | 可設置 key 的 TTL,自動刪除過期數據 |
發布/訂閱功能 | 可用作輕量級消息隊列 |
主從復制 + 哨兵 + 集群 | 支持高可用和分布式部署 |
注意:Redis 是內存數據庫,內存有限,不能當成 MySQL 那種“海量永久存儲”來用。適合熱數據或臨時數據。
2.1、創建容器
# 拉取最新鏡像# 當然也可以指定版本號docker pull redis# 查看是否拉取成功docker images?# 快速搭建一個無密碼的redis容器(不建議)docker run -d --name <自定義容器名> -p 6379:6379 redis?# 或者搭建一個帶密碼、持久化數據、自定義配置的redis容器?# 1. 先準備目錄和配置文件# 自定義路徑,我以在E盤container文件夾的redis文件夾中準備為例mkdir -p /mnt/e/container/redis/{conf,data}touch /mnt/e/container/redis/conf/redis.conf?# 2. 寫最小配置 /data/redis/conf/redis.conf# 可使用以下命令(不過需要將中文注釋去除)# 也可以直接vi編輯文件cat >/mnt/e/container/redis/conf/redis.conf <<'EOF'# 若不修改,bind 監聽地址默認127.0.0.1,即只允許本地訪問,修改為0.0.0.0任意IP均可訪問,生產環境不建議修改,當前是測試環境修改為0.0.0.0方便測試bind 0.0.0.0 ? ? ? ? ? ? ? ? ? ? ? ? ? port 6379requirepass <自定義密碼># 保護模式protected-mode no# 持久化設置appendonly yesappendfilename "appendonly.aof"appendfsync everysecEOF?# 3. 啟動docker run -d --name <自定義容器名> \-p 6379:6379 \-v /mnt/e/container/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \-v /mnt/e/container/redis/data:/data \redis redis-server /usr/local/etc/redis/redis.conf# 驗證成功docker exec -it <自定義容器名> bash# 連接本容器內的 redis-serverredis-cli -a <自定義密碼># 添加鍵值對set <鍵> <值>get <鍵>
2.2、實操演示
小貼士:vi編輯時可進入粘貼模式以快速編輯
①、剛進入vi編輯模式,默認是普通模式
②、輸入 :set paste
③、輸入i/a/o進入編輯模式,此時右下角會顯示 -- INSERT (paste) --,直接粘貼即可
④、輸入esc退回到普通模式
⑤、輸入 :set nopaste 退出粘貼模式(下次再進入就是正常插入模式),:wq保存并退出即可
2.3、客戶端
redis和MySQL差不多都是一個命令行,一個圖形化可視
①、命令行客戶端
# 進入命令行docker exec -it <容器名> redis-cli -a <自定義密碼># 或者docker exec -it <自定義容器名> bash# 連接本容器內的 redis-serverredis-cli -a <自定義密碼>
②、圖形化客戶端
Ⅰ、RedisInsight
官方頁 https://redisdesktop.com → Download → Windows → 選 .exe(或便攜版 .zip)。若訪問慢,可直接用 GitHub 發行頁:https://github.com/uglide/RedisDesktopManager/releases
Ⅱ、DataGrip
當然如果由于你的網絡問題,無法正確下載出來,考慮到DataGrip 從 2022.3 版本 開始原生支持 Redis,包括單機實例(Single Instance)和鍵值探索功能,故采用DataGrip 連接redis
二、常見命令
1、Redis數據結構
1.1、基礎數據結構
①、String(字符串)
存儲類型:二進制安全的字符串,最大 512MB
②、Hash(哈希表)
存儲類型:field-value 映射表
③、List(列表)
存儲類型:雙向鏈表
④、Set(集合)
存儲類型:無序唯一集合
⑤、Sorted Set(有序集合)
存儲類型:帶分數的有序集合
1.2、高級數據結構
①、Bitmaps
本質:String 的位操作
②、HyperLogLog
用途:基數統計(去重計數)
③、Geospatial
用途:地理位置信息
底層實現:Sorted Set
④、Stream
用途:消息隊列(Redis 5.0+)
2、Redis通用命令
通用命令即對所有數據類型都適用的命令
# 設置鍵值(支持過期時間)SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX]?# 獲取鍵值GET key# 獲取所有鍵值對,適用于數據量較少keys *?# 檢查鍵是否存在EXISTS key [key ...]?# 刪除鍵DEL key [key ...]?# 查看鍵類型TYPE key?# 重命名鍵RENAME key newkey?# 設置過期時間(秒)EXPIRE key seconds# 設置過期時間(毫秒)PEXPIRE key milliseconds?# 查看剩余生存時間(秒)TTL key# 查看剩余生存時間(毫秒)PTTL key?# 移除過期時間(持久化)PERSIST key
3、String類型
String 是 Redis 最基本的數據類型,可以存儲文本、數字或二進制數據。
3.1、基本特性
存儲內容:
-
文本字符串(最大 512MB)
-
數字(整數或浮點數)
-
二進制數據(如圖片序列化)
底層實現:
-
簡單動態字符串(SDS, Simple Dynamic String)
-
根據內容自動選擇編碼方式:
-
int
:8字節長整型 -
embstr
:≤44字節字符串 -
raw
:>44字節字符串
-
3.2、常用命令
# 設置鍵值(支持過期時間)SET key value [EX seconds] [PX milliseconds] [NX|XX]# 獲取值GET key# 批量設置MSET key1 value1 key2 value2# 批量獲取MGET key1 key2# 獲取字符串長度STRLEN key# 有就插入失敗,無則插入成功SETNX key value# 將SET和EXPIRE合二為一SETEX key seconds value?# 整數遞增INCR key ? ? ? ? # +1INCRBY key 5 ? ? # +n# 整數遞減DECR key ? ? ? ? # -1DECRBY key 3 ? ? # -n# 浮點數增減# 浮點數必須指定步長INCRBYFLOAT key 2.5?# 設置指定位的值(0/1)SETBIT key offset value# 獲取指定位的值GETBIT key offset# 統計值為1的位數BITCOUNT key [start end]# 位運算(AND/OR/XOR/NOT)BITOP AND destkey srckey1 srckey2?# 追加內容APPEND key value# 獲取子串GETRANGE key start end# 覆蓋子串SETRANGE key offset value# 設置新值并返回舊值GETSET key newvalue
3.3、層級結構
Redis 雖然本身是扁平的鍵值存儲,但通過合理的命名規范可以實現邏輯上的層級結構,提高數據組織性和可維護性。使用 :
作為層級分隔符。
4、哈希類型
哈希是 Redis 中用于存儲對象數據的理想數據結構,它特別適合存儲具有多個字段的鍵值對集合。
4.1、基本特性
①、存儲結構:
-
鍵值對集合,鍵是字符串,值可以是字符串或數字
-
每個哈希最多可存儲 232 -1 個字段-值對(約40億)
②、底層實現:
-
ziplist(壓縮列表):當字段數 ≤
hash-max-ziplist-entries
(默認512)且所有值 ≤hash-max-ziplist-value
(默認64字節) -
hashtable(哈希表):不滿足上述條件時自動轉換
③、適用場景:
-
對象存儲(用戶信息、商品屬性)
-
頻繁訪問部分字段的場景
-
需要原子更新多個字段的場景
4.2、常用命令
# 設置字段值HSET key field value [field value ...]?# 獲取字段值HGET key field?# 檢查字段是否存在HEXISTS key field?# 刪除字段HDEL key field [field ...]?# 獲取所有字段值HGETALL key?# 批量設置HMSET key field1 value1 field2 value2 ?# 新版HSET已兼容?# 批量獲取HMGET key field1 field2?# 獲取所有字段名HKEYS key?# 獲取所有字段值HVALS key
5、List類型
List 是 Redis 中的一種線性數據結構,它按照插入順序存儲多個字符串元素,支持從兩端高效插入和刪除操作。
類似雙向列表,可正向和反向檢索
5.1、基本特性
①、存儲結構:
-
有序的字符串元素集合
-
每個列表最多可存儲 232 -1 個元素(約40億)
-
元素可重復
②、底層實現:
-
ziplist(壓縮列表):當元素數量 ≤
list-max-ziplist-entries
(默認512)且所有元素 ≤list-max-ziplist-value
(默認64字節) -
linkedlist(3.2版本前)
-
quicklist(3.2+版本):ziplist組成的雙向鏈表
③、時間復雜度:
-
頭尾操作:O(1)
-
按索引訪問:O(n)
5.2、常用命令
# 左端插入元素LPUSH key element [element ...]# 右端插入元素RPUSH key element [element ...]# 左端彈出元素LPOP key [count] ?# Redis 6.2+支持批量彈出# 右端彈出元素RPOP key [count]# 獲取列表長度LLEN key?# 獲取指定范圍內的元素,第一個元素索引是 0LRANGE key start stop ?# 包含stop位置# 修剪列表,只保留指定范圍LTRIM key start stop# 獲取指定位置的元素LINDEX key index?# 左端阻塞彈出(超時秒)# 相較于LPOP(沒有就報錯),BLPOP(可等timeout這么長的時間,之后沒有才報錯)BLPOP key [key ...] timeout# 右端阻塞彈出BRPOP key [key ...] timeout# 右端彈出并左端插入到另一列表BRPOPLPUSH source destination timeout
當入口和出口在同一邊,即棧(先進后出),如LPUSH和LPOP、RPUSH和RPOP
當入口和出口不在同一邊,即隊列(先進先出),如LPUSH和RPOP、RPUSH和LPOP
6、SET類型
Set 是 Redis 中的一種無序且唯一的數據結構,它提供高效的成員檢查、集合運算等操作
6.1、基本特性
①、存儲結構:
-
無序的字符串元素集合
-
元素唯一不重復
-
最大可存儲 232 -1 個元素(約40億)
②、底層實現:
-
intset(整數集合):當所有元素都是整數且數量 ≤
set-max-intset-entries
(默認512) -
hashtable(哈希表):不滿足上述條件時使用
③、時間復雜度:
-
添加/刪除/檢查存在:O(1)
-
集合運算:O(n)
6.2、常用命令
# 添加元素SADD key member [member ...]# 刪除元素SREM key member [member ...]# 獲取所有元素SMEMBERS key# 檢查元素是否存在SISMEMBER key member# 獲取集合元素數量SCARD key?# 交集SINTER key [key ...]# 并集SUNION key [key ...]# 差集(第一個集合有而其他集合沒有的元素)SDIFF key [key ...]# 運算結果存儲到新集合SINTERSTORE destination key [key ...]SUNIONSTORE destination key [key ...]SDIFFSTORE destination key [key ...]
7、SortedSet類型
Sorted Set 是 Redis 中一種兼具 Set 的唯一性和排序特性的數據結構,每個元素都關聯一個分數(score),可以按分數排序
7.1、核心特性
①、存儲結構:
-
唯一成員(member) + 浮點數分數(score)
-
自動按分數排序(默認升序)
-
最大元素數:232 -1(約40億)
②、底層實現:
-
ziplist:元素數 ≤
zset-max-ziplist-entries
(默認128)且所有元素 ≤zset-max-ziplist-value
(默認64字節) -
skiplist + dict:不滿足條件時使用(跳表保證有序,字典保證O(1)查詢)
③、時間復雜度:
-
添加/刪除/更新:O(logN)
-
按分數范圍查詢:O(logN + M)(M為返回數量)
-
按排名查詢:O(logN)
7.2、常用命令
# 添加元素(分數可重復,成員唯一)ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...] # 默認自動升序排序# 獲取元素分數ZSCORE key member# 獲取元素排名(從0開始)ZRANK key member ? ? # 升序排名ZREVRANK key member ?# 降序排名# 獲取集合大小ZCARD key?# 按分數升序查詢ZRANGE key start stop [WITHSCORES] ?# 包含stopZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]# 按分數降序查詢ZREVRANGE key start stop [WITHSCORES]ZREVRANGEBYSCORE key max min [WITHSCORES]# 查詢分數范圍內的元素數量ZCOUNT key min max
三、Redis的Java客戶端
1、主流客戶端
客戶端 | 維護方 | 特點 | 適用場景 |
---|---|---|---|
Jedis | Redis官方 | 輕量級、同步阻塞、API直接,多線程 | 簡單應用、傳統項目 |
Lettuce | Spring官方 | 異步非阻塞、Netty實現、功能全面 | 高并發、Spring項目 |
Redisson | 社區 | 分布式服務、豐富高級功能 | 分布式系統、復雜場景 |
Spring Data Redis | Spring官方 | 抽象層、統一API、支持多種客戶端 | Spring生態整合 |
-
快速腳本、單元測試、低并發 Web
→ Jedis 足夠,引入少、代碼直觀。
-
Spring Boot 2.x+、高并發、響應式 WebFlux
→ Lettuce 是默認,直接
spring-boot-starter-data-redis
開箱即用。 -
分布式鎖、延遲隊列、限流、Tomcat 會話共享、對象映射
→ Redisson 一站式,提供
RLock
,RMap
,RDelayedQueue
等高級 API,節省自研成本
2、快速入門Jedis
為了實現快速入門,我就不進行連接池等配置,而是為了實現最簡單的導入依賴,測試連接。
注意前提是你已經下載好了Maven和JDK合適的版本
2.1、補充下載Maven
①、下載 Maven
-
進官網:Download Apache Maven – Maven
-
選 Binary zip(例如
apache-maven-3.9.11-bin.zip
)→ 解壓到 無中文無空格 路徑,比如"E:\java\maven\apache-maven-3.9.11-bin\apache-maven-3.9.11"
② 、配環境變量
-
Win + S 搜索 “環境變量” → 打開 “編輯系統環境變量”
-
新建系統變量變量名:
MAVEN_HOME
變量值:E:\java\maven\apache-maven-3.9.11-bin\apache-maven-3.9.11
-
選中 Path → 編輯 → 新建 → 把下面兩行依次加進去
%MAVEN_HOME%\bin
-
全部確認 → 重啟 PowerShell
③、 驗證
新開 PowerShell 輸入:
mvn -v?# 得到類似效果即正確安裝配置Apache Maven 3.9.11 (3e54c93a704957b63ee3494413a2b544fd3d825b)Maven home: E:\java\maven\apache-maven-3.9.11-bin\apache-maven-3.9.11Java version: 24.0.1, vendor: Oracle Corporation, runtime: E:\java\JDKDefault locale: zh_CN, platform encoding: UTF-8OS name: "windows 11", version: "10.0", arch: "amd64", family: "windows"
④、實操演示
2.2、非池化直連測試(Jedis為例)
①、創建 Maven 工程
注意選擇Java項目中的普通maven工程即可
②、導入核心依賴
// 導入依賴,這里使用的是5.2.0版本<dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.2.0</version> ? </dependency></dependencies>
③、非池化連接測試
package org.example;// 導入 Jedis 類import redis.clients.jedis.Jedis;public class Main {public static void main(String[] args) {// 簡單連接 Redis 服務器Jedis jedis = new Jedis("localhost", 6379);// 認證,設置的密碼jedis.auth("123456");// 選擇數據庫jedis.select(0);// 插入一個鍵值對進行測試jedis.set("name", "tb_first");System.out.println("name = " + jedis.get("name")); ? ? ?// name = tb_first}// 提供一個釋放連接的方法public static void close(Jedis jedis) {if (jedis != null) {jedis.close();}}}
④、實操演示
2.3、Jedis連接池連接(Jedis為例)
Jedis 連接池是生產環境中使用 Redis 的必備組件,它能有效管理連接資源,提升性能。由于Jedis的線程不安全,頻繁的銷毀和創建還容易導致性能的損耗,故使用連接池比非池化直連更高效。
①、連接池常見參數
參數名 | 說明 | 生產環境推薦值 |
---|---|---|
maxTotal | 連接池最大連接數 | 根據QPS調整(100-500) |
maxIdle | 最大空閑連接數 | maxTotal的1/4-1/2 |
minIdle | 最小空閑連接數(保持可用連接) | 5-20 |
maxWaitMillis | 獲取連接最大等待時間(ms) | 2000-5000 |
testOnBorrow | 獲取連接時是否測試有效性(true會降低性能但保證連接可用) | 根據業務需求(true/false) |
testWhileIdle | 空閑時是否測試連接有效性 | true |
timeBetweenEvictionRuns | 空閑連接檢測周期(ms) | 30000 |
numTestsPerEvictionRun | 每次檢測的空閑連接數 | 建議等于maxIdle |
②、實操演示
// 新建類中package org.example;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;// 創建一個連接池工具類public class RedisConnectionPool {// 創建一個連接池對象private static JedisPool jedisPool;?static {// 1. 創建連接池配置JedisPoolConfig poolConfig = new JedisPoolConfig();?// 關鍵參數配置poolConfig.setMaxTotal(8); ? ? ? ? ?// 最大連接數poolConfig.setMaxIdle(4); ? ? ? ? ? // 最大空閑連接poolConfig.setMinIdle(2); ? ? ? ? ? ?// 最小空閑連接poolConfig.setTestOnBorrow(true); ? ?// 獲取連接時測試連通性poolConfig.setTestWhileIdle(true); ? // 空閑時定期測試連接?// 2. 創建連接池 (根據實際情況選擇構造方法)jedisPool = new JedisPool(poolConfig,"localhost", ? ? // Redis服務器地址6379, ? ? ? ? ? // Redis端口2000, ? ? ? ? ? // 連接超時時間(ms)"123456" ? ? ? ?// 密碼(沒有則省略));}// 提供一個獲取連接的方法public static Jedis getResource() {return jedisPool.getResource();}}?// 測試類中package org.example;// 導入 Jedis 類import redis.clients.jedis.Jedis;public class Main {public static void main(String[] args) {// 從連接池獲取連接Jedis jedis = RedisConnectionPool.getResource();// 選擇數據庫jedis.select(0);// 插入一個鍵值對進行測試jedis.set("student:1", "hhh");System.out.println("student:1 = " + jedis.get("student:1")); ? ? ?// student:1 = hhh}// 提供一個釋放連接的方法public static void close(Jedis jedis) {if (jedis != null) {jedis.close();}}}
2.4、SpringDataRedis
Spring Data Redis 是 Spring 生態中用于訪問 Redis 的抽象框架,它提供了統一的操作接口,支持多種 Redis 客戶端(Lettuce、Jedis等)。
①、創建Maven工程
創建完成后,可選擇刪除多余文件,最終保留文件.idea、src、pom.xml,application可改為yaml文件
②、添加依賴
<dependencies><!-- ? ? ? 引入redis依賴 ? ? ? --><!-- ? ? ? 該依賴創建好工程自動含有 ? ? ? --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- ? ? ? 引入連接池依賴 ? ? ? --><!-- ? ? ? 該依賴需要我們自己手動加入 ? ? ? --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- ? 添加 Jackson Databind 依賴 ? --><!--Spring Boot 3.5.5 默認使用 Jackson 2.17+,所以不需要指定版本號,Spring Boot 會自動管理--><!-- ? ? ? 方便后續將Value進行JSON序列化 ? ? ? --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
③、配置文件
注意較新版本Java已經廢止 spring:redis ,改為 spring:data:redis
# 注意以下只是給出一個模板,具體情況具體分析spring:data:redis:# ? ? host: 127.0.0.1host: localhostport: 6379password: 123456database: 0lettuce:pool:max-active: 8 ? ? ? ? # 最大連接數max-idle: 4 ? ? ? ? ? # 最大空閑連接min-idle: 2 ? ? ? ? ? # 最小空閑連接max-wait: 2000ms ? ? ?# 獲取連接最大等待時間timeout: 1000ms ? ? ? ? ? # 連接超時時間
④、注入redisTemplate并測試
package org.example.springdataredisdemo;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.RedisTemplate;?@SpringBootTestclass SpringdataredisDemoApplicationTests {?@Autowiredprivate RedisTemplate redisTemplate;@Testvoid StringTest() {// ? ? ? 寫入一條字符串數據redisTemplate.opsForValue().set("name", "zhangsan");// ? ? ? 讀取一條字符串數據(默認是Object類型)Object name = redisTemplate.opsForValue().get("name");System.out.println(name);}?}
⑤、Java 默認序列化
如上圖,我們已經成功插入了一個name為zhangsan的鍵值對,同時看上圖可見我們插入的zhangsan的key有部分亂碼,按道理來說使用命令行查看應該也是可以取得結果,可事實是我們得到的是key 序列化后的二進制亂碼以及nil(二進制序列化和JDK序列化),如圖:
我們用的是默認的 RedisTemplate<Object, Object>
,它默認使用:
-
JdkSerializationRedisSerializer
對 key 和 value 進行序列化。 -
所以寫入 Redis 的 key 是二進制格式,不是純字符串 "name"
即 SpringDataRedis 可幫助我們將任何類型對象轉化成redis可識別的字節
Ⅰ、各數據類型默認序列化器
操作類型 | 默認序列化器 | 存儲示例 |
---|---|---|
Key | JdkSerializationRedisSerializer | \xac\xed\x00\x05t\x00\x03foo |
Value | JdkSerializationRedisSerializer | 二進制Java序列化格式 |
Hash Key | JdkSerializationRedisSerializer | 同Key |
Hash Value | JdkSerializationRedisSerializer | 同Value |
所有ZSet/TX/管道操作 | JdkSerializationRedisSerializer | 二進制格式 |
Ⅱ、常用redis序列化策略
序列化器 | 優點 | 缺點 | 適用場景 |
---|---|---|---|
JdkSerializationRedisSerializer | Java原生支持 | 兼容性差、體積大、可讀性差 | 不推薦使用 |
StringRedisSerializer | 簡單字符串、高效 | 只能處理String類型 | Key序列化、簡單Value |
Jackson2JsonRedisSerializer | 可讀性好、跨語言 | 需要類有無參構造、反射開銷 | 復雜對象存儲 |
GenericJackson2JsonRedisSerializer | 存儲類信息、支持多類型 | 占用稍多空間 | 需要類型轉換的場景 |
OxmSerializer | XML格式、可讀 | 效率低、體積大 | 需要XML格式的場景 |
Ⅲ、主要問題
-
可讀性差:Redis CLI中無法直接識別
-
兼容性問題:不同JVM版本可能不兼容
-
存儲膨脹:二進制格式比文本格式占用更多空間
-
跨語言障礙:其他語言無法直接讀取
Ⅳ、解決方案RedisSerializer
自定義RedisTemplate序列化方式
// 創建RedisConfig類package org.example.springdataredisdemo.redis.config;?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;?// 標記這是一個 Spring 配置類,會被 Spring 掃描并加載@Configurationpublic class RedisConfig {// 注冊一個名為 redisTemplate 的 Bean,類型是 RedisTemplate<String, Object>@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {// 創建一個 RedisTemplate 實例 templateRedisTemplate<String, Object> template = new RedisTemplate<>();// 把連接工廠注入進來,建立與 Redis 的連接template.setConnectionFactory(factory);?// 使用 String 序列化 Keytemplate.setKeySerializer(new StringRedisSerializer());// 使用 JSON 序列化 Valuetemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());?// Hash結構也使用 String 序列化 HashKey,JSON 序列化 HashValuetemplate.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());?return template;}}?// 在main文件中重新測試package org.example.springdataredisdemo;?import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.RedisTemplate;?@SpringBootTestclass SpringdataredisDemoApplicationTests {?@Autowiredprivate RedisTemplate<String, Object> redisTemplate;?@Testvoid StringTest() {// ? ? ? 寫入一條字符串數據redisTemplate.opsForValue().set("name", "zhangsan");// ? ? ? 讀取一條字符串數據(默認是Object類型)Object name = redisTemplate.opsForValue().get("name");System.out.println(name);}?}
結果如圖:
Ⅴ、可選優化
由于上方Ⅲ給出的解決方案自動化JSON會帶來內存占用問題,所以我們可以選擇只進行String序列化,但這也要求我們存入的 key 和 value 必須是字符串類型,而如果需要存入JSON格式的對象,則需要我們自己手動完成對象的序列化,如使用ObjectMapper等等工具。
package org.example.springdataredisdemo;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.RedisTemplate;?@SpringBootTestclass SpringdataredisDemoApplicationTests {?@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid StringTest() {// ? ? ? 寫入一條字符串數據stringRedisTemplate.opsForValue().set("name", "zhangsan");// ? ? ? 讀取一條字符串數據(默認是Object類型)String name = stringRedisTemplate.opsForValue().get("name");System.out.println(name);}@Testvoid test() throws JsonProcessingException {User user = new User("張三", 20);?// 手動序列化String json = objectMapper.writeValueAsString(user);redisTemplate.opsForValue().set("user:1", json);?// 手動反序列化String jsonBack = redisTemplate.opsForValue().get("user:1");User userBack = objectMapper.readValue(jsonBack, User.class);?System.out.println(userBack.getName()); // 張三?}