Java連接并操作Redis超詳細教程
引言
在分布式系統(tǒng)和高并發(fā)場景中,Redis 作為高性能內(nèi)存數(shù)據(jù)庫的地位舉足輕重。對于 Java 開發(fā)者而言,掌握 Redis 的連接與操作是進階必備技能。然而,從基礎(chǔ)的 Jedis 原生客戶端到 Spring 封裝的 RedisTemplate,不同連接方式的原理與適用場景常讓初學者困惑。如何選擇合適的連接方式?序列化配置背后的邏輯是什么?生產(chǎn)環(huán)境中又該如何優(yōu)化?
本文從 Java 操作 Redis 的核心需求出發(fā),通過完整代碼示例與逐行解析,系統(tǒng)講解 Jedis 直接連接、連接池、RedisTemplate 及 StringRedisTemplate 的使用方法,深入剖析連接原理、序列化機制與性能優(yōu)化策略。無論你是剛接觸 Redis 的小白,還是需要規(guī)范項目實踐的開發(fā)者,都能從代碼細節(jié)與原理分析中獲得啟發(fā),掌握從基礎(chǔ)連接到高級應(yīng)用的全流程實戰(zhàn)技巧。
1. Redis 基礎(chǔ)概念與 Java 生態(tài)概覽
1.1 Redis 是什么?
Redis(Remote Dictionary Server)是一個基于內(nèi)存的高性能鍵值對存儲系統(tǒng),具有以下核心特性:
- 數(shù)據(jù)結(jié)構(gòu)豐富:支持 String、Hash、List、Set、Sorted Set 等 8 種數(shù)據(jù)結(jié)構(gòu)
- 內(nèi)存級性能:讀寫速度可達 10 萬 + 次 / 秒(String 類型)
- 持久化支持:提供 RDB(快照)和 AOF(日志)兩種持久化方式
- 集群能力:支持主從復制、哨兵模式、Cluster 集群
- 多語言支持:提供 Java、Python、Node.js 等多語言客戶端
在 Java 生態(tài)中,主流的 Redis 客戶端包括:
- Jedis:官方提供的原生 Java 客戶端,支持同步阻塞式 IO
- Lettuce:基于 Netty 的異步非阻塞客戶端,支持響應(yīng)式編程
- Spring Data Redis:Spring 封裝的高層抽象,支持 Jedis/Lettuce 作為底層連接
1.2 Java 操作 Redis 的核心場景
- 緩存系統(tǒng):降低數(shù)據(jù)庫壓力(如商品詳情頁緩存)
- 分布式會話:解決集群環(huán)境下的 Session 共享問題
- 計數(shù)器:實現(xiàn)點贊計數(shù)、接口限流等功能(利用 INCR 命令)
- 消息隊列:基于 List 的 LPUSH/RPOP 實現(xiàn)簡單隊列
- 分布式鎖:通過 SETNX 命令實現(xiàn)分布式鎖機制
2.Jedis 原生客戶端:從直接連接到連接池
2.0 Maven依賴
<!-- Jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
2.1 Jedis 直接連接(非池化方式)
2.1.1 核心代碼解析
@Slf4j
@SpringBootTest
public class JedisDirect {
private Jedis jedis;
@BeforeEach
public void setUp(){
//建立連接
jedis = new Jedis("x.x.x.x",6379);
//設(shè)置密碼
jedis.auth("xxxx");
//選擇庫
jedis.select(0);
}
@Test
public void testString(){
jedis.set("namePool","zhangsanPool");
String value = jedis.get("name");
log.info("value:"+value);
}
@Test
public void testHash(){
jedis.hset("user:2","name","lisiPool");
jedis.hset("user:2","age","21");
Map<String,String> map = jedis.hgetAll("user:1");
log.info("map:"+ map.toString());
}
@AfterEach
public void tearDown(){
if(jedis != null){
jedis.close();
}
}
}
代碼的執(zhí)行結(jié)果:
結(jié)果1:

結(jié)果2:

2.1.2 核心類與對象
Jedis:核心客戶端類,封裝了所有 Redis 命令
構(gòu)造方法:Jedis(String host, int port) 初始化連接
常用方法:
set(String key, String value):存儲字符串get(String key):獲取字符串hset(String key, String field, String value):存儲 Hash 字段hgetAll(String key):獲取 Hash 所有字段
@BeforeEach/@AfterEach:JUnit5 生命周期注解,分別用于初始化和銷毀資源
2.1.3 原理分析
連接過程:
- 創(chuàng)建 Jedis 實例時建立 TCP 連接(三次握手)
- 通過 auth 命令進行密碼驗證(如果配置了密碼)
- select 命令選擇操作的數(shù)據(jù)庫(默認 0 號庫)
命令執(zhí)行:
- 客戶端將命令序列化為字節(jié)流發(fā)送到 Redis 服務(wù)器
- 服務(wù)器執(zhí)行命令后返回結(jié)果,客戶端解析響應(yīng)
2.1.4 優(yōu)缺點
- 優(yōu)點:簡單直觀,適合學習和小規(guī)模測試
- 缺點:
- 每次測試都創(chuàng)建新連接,性能低下(TCP 連接創(chuàng)建開銷大)
- 并發(fā)場景下可能導致連接風暴
- 沒有連接復用機制,資源利用率低
2.2 Jedis 連接池(池化連接)
2.2.1 連接池配置類
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static{
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//最大連接
jedisPoolConfig.setMaxTotal(10);
//最大空閑連接
jedisPoolConfig.setMaxIdle(10);
//最小空閑連接
jedisPoolConfig.setMinIdle(5);
//設(shè)置最長等待時間
jedisPoolConfig.setMaxWaitMillis(200);
jedisPool = new JedisPool(jedisPoolConfig,"x.x.x.x",6379,
1000,"xxxx");
}
//獲取jedis對象
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
說明:
JedisPool:連接池核心類,管理連接的創(chuàng)建和回收
getResource():從連接池獲取可用連接(可能從空閑隊列獲取或新建)
JedisPoolConfig:連接池配置類,常用參數(shù):
maxTotal:最大連接數(shù)(控制并發(fā)量)maxIdle:最大空閑連接數(shù)(避免空閑連接過多)minIdle:最小空閑連接數(shù)(保證基礎(chǔ)可用連接)
maxWaitMillis:獲取連接超時時間(避免無限阻塞)
2.2.2 連接池工作原理
初始化階段:
- 啟動時創(chuàng)建
minIdle數(shù)量的空閑連接
獲取連接:
- 優(yōu)先從空閑隊列中獲取連接
- 若空閑隊列為空,且當前連接數(shù)小于
maxTotal,則新建連接 - 若連接數(shù)已達
maxTotal,則等待maxWaitMillis時間
歸還連接:
- 調(diào)用
close()方法時,連接不會真正關(guān)閉,而是放回空閑隊列 - 空閑連接數(shù)超過
maxIdle時,多余連接會被銷毀
2.2.3 使用示例
@Slf4j
@SpringBootTest
public class JedisPool {
private Jedis jedis;
@BeforeEach
public void setUp(){
//建立連接
jedis = JedisConnectionFactory.getJedis();
//設(shè)置密碼
jedis.auth("dhj20030916.");
//選擇庫
jedis.select(0);
}
@Test
public void testString(){
jedis.set("name","zhangsan");
String value = jedis.get("name");
log.info("value:"+value);
}
@Test
public void testHash(){
jedis.hset("user:1","name","lisi");
jedis.hset("user:1","age","21");
Map<String,String> map = jedis.hgetAll("user:1");
log.info("map:"+ map.toString());
}
@AfterEach
public void tearDown(){
if(jedis != null){
jedis.close();
}
}
}
運行結(jié)果:
結(jié)果1:

結(jié)果2:

2.2.4 優(yōu)勢對比
| 特性 | 直接連接 | 連接池方式 |
|---|---|---|
| 連接創(chuàng)建 | 每次新建 | 復用已有連接 |
| 并發(fā)支持 | 差 | 好(控制連接數(shù)) |
| 資源利用率 | 低 | 高 |
| 性能 | 差(連接開銷) | 好(減少握手) |
| 適用場景 | 單線程測試 | 高并發(fā)生產(chǎn)環(huán)境 |
3. Spring Data Redis:高層抽象與模板化操作
3.1 核心依賴與配置
3.1.1 Maven 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3.1.2 YAML 配置
spring:
redis:
host: x.x.x.x
port: 6379
password: xxxx
lettuce:
pool:
max-active: 10 #最大連接
max-idle: 10 #最大空閑連接
min-idle: 0 #最小空閑連接
max-wait: 100 #連接等待時間
3.2 RedisTemplate 核心類解析
3.2.1 基礎(chǔ)操作示例
@SpringBootTest
@Slf4j
public class RedisTem {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void test(){
//插入一條String類型的數(shù)據(jù)
redisTemplate.opsForValue().set("nameTem","趙六");
Object s = redisTemplate.opsForValue().get("nameTem");
log.info("nameTem:"+ s);
}
}
運行結(jié)果:

3.2.2 核心類結(jié)構(gòu)
RedisTemplate:
泛型參數(shù):<K, V> 分別表示鍵和值的類型
核心方法:
opsForValue():獲取字符串操作對象(對應(yīng) String 類型)opsForHash():獲取 Hash 操作對象(對應(yīng) Hash 類型)opsForList():獲取列表操作對象(對應(yīng) List 類型)opsForSet():獲取集合操作對象(對應(yīng) Set 類型)opsForZSet():獲取有序集合操作對象(對應(yīng) Sorted Set 類型)
RedisConnectionFactory:
- 連接工廠接口,支持 Jedis/Lettuce 等多種實現(xiàn)
- Spring 自動根據(jù)依賴加載對應(yīng)的實現(xiàn)(如引入 jedis 依賴則使用 JedisConnectionFactory)
3.3 序列化機制詳解
3.3.1 默認序列化問題
Spring Data Redis 默認使用JdkSerializationRedisSerializer:
- 序列化后數(shù)據(jù)冗余(包含類名、版本號等信息)
- 依賴類必須實現(xiàn)
Serializable接口 - 跨語言不兼容(如 Python 無法解析 JDK 序列化數(shù)據(jù))
3.3.2 JSON 序列化配置
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
// 創(chuàng)建redisTemplate對象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//設(shè)置連接工廠
redisTemplate.setConnectionFactory(connectionFactory);
// 創(chuàng)建json序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//設(shè)置Key的序列化
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
//設(shè)置value的序列化
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
return redisTemplate;
}
}
3.3.3 序列化流程
存儲數(shù)據(jù):
- 值對象(如 User 對象)通過 JSON 序列化工具轉(zhuǎn)為 JSON 字符串
- 鍵和 Hash 鍵通過 String 序列化轉(zhuǎn)為字節(jié)數(shù)組
讀取數(shù)據(jù):
- 從 Redis 獲取字節(jié)數(shù)組后,鍵反序列化為 String
- 值反序列化為對應(yīng)的對象(通過 Jackson 的類型推斷)
3.4 對象存儲實戰(zhàn)(序列化配置后)
3.4.1 User 實體類
@Data
public class User {
private Integer id;
private String name;
private Integer age;
}
3.4.2 測試代碼
@SpringBootTest
@Slf4j
public class RedisTemSer {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testString(){
redisTemplate.opsForValue().set("nameTemSer","test");
String value = (String)redisTemplate.opsForValue().get("nameTemSer");
log.info("value"+ value);
}
@Test
public void testHash(){
redisTemplate.opsForHash().put("user:3","name","hash");
redisTemplate.opsForHash().put("user:3","age","22");
Map<String,Object> map = (Map<String,Object>)redisTemplate.opsForHash().entries("user:3");
log.info("map"+ map);
}
@Test
public void testObject(){
User user = new User();
user.setId(1);
user.setName("object");
user.setAge(20);
redisTemplate.opsForValue().set("User",user);
Object object = redisTemplate.opsForValue().get("User");
log.info("object"+ object);
}
}
運行結(jié)果:
結(jié)果1:

結(jié)果2:

結(jié)果3:

3.4.3 關(guān)鍵細節(jié)
類型轉(zhuǎn)換:
opsForValue().set(key, value)支持任意對象,內(nèi)部自動序列化opsForValue().get(key)返回 Object 類型,需手動強轉(zhuǎn)(依賴序列化配置)
Hash 操作:
opsForHash().put(key, field, value)存儲 Hash 字段,value 自動序列化entries()方法返回 Map<String, Object>,字段值已反序列化
4. StringRedisTemplate:專注字符串場景
4.1 基本概念
StringRedisTemplate 是 RedisTemplate<String, String> 的子類
默認配置:
- 鍵序列化:
StringRedisSerializer(等同于RedisSerializer.string()) - 值序列化:
StringRedisSerializer(直接存儲字符串)
4.2 對象操作實戰(zhàn)
4.2.1 測試代碼
@Slf4j
@SpringBootTest
public class StringRedisTem {
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
@Test
public void testObject() throws JsonProcessingException {
User user = new User();
user.setId(2);
user.setName("StringRedisTem");
user.setAge(20);
// 手動序列化value
String json = mapper.writeValueAsString(user);
stringRedisTemplate.opsForValue().set("UserRedis", json);
// 獲取數(shù)據(jù)
String val = stringRedisTemplate.opsForValue().get("UserRedis");
// 手動反序列化
User userValue = mapper.readValue(val,User.class);
log.info(userValue.toString());
}
}
運行結(jié)果:

4.2.2 核心步驟解析
序列化:
- 使用 Jackson 的
ObjectMapper將 User 對象轉(zhuǎn)為 JSON 字符串 - 解決
StringRedisTemplate只能存儲字符串的限制
存儲與獲取:
opsForValue().set(key, value)直接存儲字符串opsForValue().get(key)直接獲取字符串
反序列化:
- 將獲取的 JSON 字符串轉(zhuǎn)為 User 對象
- 需要處理可能的
JsonProcessingException異常
4.3 與 RedisTemplate 的對比
| 特性 | RedisTemplate | StringRedisTemplate |
|---|---|---|
| 泛型參數(shù) | <K, V> 任意類型 | <String, String> |
| 序列化 | 支持自定義序列化 | 固定 String 序列化 |
| 對象操作 | 自動序列化 / 反序列化 | 需手動序列化 / 反序列化 |
| 鍵類型 | 任意類型(需序列化) | 只能是 String 類型 |
| 適用場景 | 復雜數(shù)據(jù)類型(對象、Hash 等) | 純字符串場景(如緩存文本) |
5. 連接方式深度對比與選型建議
5.1 技術(shù)維度對比
| 維度 | Jedis 直接連接 | Jedis 連接池 | RedisTemplate | StringRedisTemplate |
|---|---|---|---|---|
| 連接管理 | 手動創(chuàng)建 | 連接池管理 | 框架管理 | 框架管理 |
| 序列化支持 | 無(需手動) | 無 | 支持自定義 | 僅 String 序列化 |
| Spring 集成 | 弱 | 弱 | 強(自動裝配) | 強(自動裝配) |
| 學習成本 | 低 | 中 | 中 | 低 |
| 并發(fā)性能 | 差 | 優(yōu) | 優(yōu) | 優(yōu) |
5.2 場景化選型建議
5.2.1 學習階段
推薦使用 Jedis 直接連接:
- 代碼簡單,便于理解 Redis 基本操作
- 適合單個命令測試(如 GET/SET/HSET 等)
5.2.2 小型項目(非 Spring)
推薦 Jedis 連接池:
- 避免頻繁創(chuàng)建連接,提升性能
- 手動管理連接,適合輕量級項目
5.2.3 Spring Boot 項目
優(yōu)先使用 RedisTemplate:
- 與 Spring 生態(tài)無縫集成(依賴注入、配置管理)
- 支持復雜數(shù)據(jù)類型和自定義序列化
- 推薦配置 JSON 序列化,兼容對象存儲
5.2.4 純字符串場景
使用 StringRedisTemplate:
- 簡化字符串操作(避免泛型轉(zhuǎn)換)
- 性能略優(yōu)(減少序列化層開銷)
5.3 生產(chǎn)環(huán)境最佳實踐
連接池配置:
maxTotal設(shè)置為系統(tǒng)并發(fā)量的 1.5-2 倍maxWaitMillis不超過 200ms(避免過長阻塞)minIdle設(shè)置為 5-10(保證基礎(chǔ)連接可用性)
序列化選擇:
- 統(tǒng)一使用 JSON 序列化(
GenericJackson2JsonRedisSerializer) - 鍵使用 String 序列化(保證可讀性和可維護性)
異常處理:
- 添加
try-catch-finally塊,確保連接歸還 - 處理
JedisConnectionException等網(wǎng)絡(luò)異常
監(jiān)控與調(diào)優(yōu):
- 監(jiān)控連接池的空閑連接數(shù)、活躍連接數(shù)
- 使用 Redis 的
INFO connection命令查看服務(wù)器連接狀態(tài)
6. 常見問題與解決方案
6.1 連接失敗問題
現(xiàn)象:
- 拋出
JedisConnectionException: ``java.net``.ConnectException: Connection refused
可能原因:
- Redis 服務(wù)器未啟動
- IP 地址或端口錯誤(檢查配置中的 host 和 port)
- 防火墻阻止連接(需開放 6379 端口)
- Redis 密碼錯誤(auth 命令失敗)
解決方案:
- 確保 Redis 服務(wù)器正常運行(
redis-cli ping檢查連通性) - 核對配置中的連接參數(shù)(IP、端口、密碼)
- 檢查服務(wù)器防火墻設(shè)置(如 Linux 的
firewall-cmd)
6.2 數(shù)據(jù)亂碼問題
現(xiàn)象:
Redis 存儲的字符串在 Java 中獲取時出現(xiàn)亂碼
可能原因:
- 未正確設(shè)置字符編碼(Jedis 默認使用 UTF-8)
- 序列化方式不匹配(如 RedisTemplate 使用 JDK 序列化,手動使用字符串讀取)
解決方案:
Jedis 中指定編碼:
jedis.get("key", StandardCharsets.UTF\_8); // 顯式指定編碼RedisTemplate 統(tǒng)一使用 String 序列化:
template.setKeySerializer(RedisSerializer.string());
6.3 對象反序列化失敗
現(xiàn)象:
- 從 Redis 獲取對象時拋出
ClassNotFoundException
可能原因:
- 使用 JDK 序列化時,類路徑不一致(如部署環(huán)境類缺失)
- JSON 序列化時,對象缺少無參構(gòu)造函數(shù)(Jackson 需要)
解決方案:
- 改用 JSON 序列化(避免類路徑問題)
- 確保實體類包含無參構(gòu)造函數(shù)(Lombok 的
@Data默認生成)
7. 擴展知識:異步客戶端 Lettuce
7.1 Lettuce 簡介
- 基于 Netty 的異步非阻塞客戶端
- 支持響應(yīng)式編程(Reactor 模式)
- 適合高并發(fā)、高吞吐量場景
7.2 核心差異
| 特性 | Jedis | Lettuce |
|---|---|---|
| IO 模型 | 同步阻塞 | 異步非阻塞 |
| 連接方式 | 每個線程一個連接 | 單個連接處理多個請求 |
| 線程安全 | 非線程安全 | 線程安全 |
| 適用場景 | 簡單同步場景 | 異步 / 反應(yīng)式場景 |
7.3 配置示例
spring:
redis:
host: 1.94.22.150
port: 6379
password: dhj20030916.
lettuce:
pool:
max-active: 10 #最大連接
max-idle: 10 #最大空閑連接
min-idle: 0 #最小空閑連接
max-wait: 100 #連接等待時間
8. 總結(jié):從入門到實戰(zhàn)的成長路徑
8.1 學習階段建議
- 基礎(chǔ)操作:掌握 Jedis 直接連接,理解 Redis 基本命令(SET/GET/HSET 等)
- 性能優(yōu)化:學習連接池原理,掌握 JedisPool 配置與使用
- 框架集成:深入 Spring Data Redis,學會配置 RedisTemplate 和序列化
- 實戰(zhàn)提升:在項目中應(yīng)用緩存、分布式鎖等場景,處理實際問題
8.2 核心知識圖譜

8.3 結(jié)語
通過本文的系統(tǒng)學習,讀者應(yīng)能熟練掌握 Java 操作 Redis 的主流方式,理解不同連接方式的適用場景和底層原理,并能夠在實際項目中根據(jù)需求選擇合適的技術(shù)方案。記住,實踐是最好的老師,建議通過實際項目練習加深理解,遇到問題時結(jié)合官方文檔和源碼進行分析,逐步提升 Redis 開發(fā)與運維能力。
以上就是Java連接并操作Redis超詳細教程的詳細內(nèi)容,更多關(guān)于Java連接并操作Redis的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實現(xiàn)轉(zhuǎn)跳不同系統(tǒng)使用枚舉加switch的方式示例
今天小編就為大家分享一篇關(guān)于Java實現(xiàn)轉(zhuǎn)跳不同系統(tǒng)使用枚舉加switch的方式示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
SpringBoot中的JPA(Java?Persistence?API)詳解
這篇文章主要介紹了SpringBoot中的JPA(Java?Persistence?API)詳解,JPA用于將?Java?對象映射到關(guān)系型數(shù)據(jù)庫中,它提供了一種面向?qū)ο蟮姆绞絹聿僮鲾?shù)據(jù)庫,使得開發(fā)者可以更加方便地進行數(shù)據(jù)持久化操作,需要的朋友可以參考下2023-07-07
使用mybatisPlus的queryWrapper做左聯(lián)接,內(nèi)聯(lián)接方式
本文介紹了如何使用Mybatis-Plus的QueryWrapper進行SQL查詢,包括左連接、內(nèi)連接等操作,通過示例代碼展示了如何構(gòu)建復雜的SQL查詢,并將結(jié)果存儲在List對象中返回,希望給讀者提供參考2025-03-03
關(guān)于MyBatis中映射對象關(guān)系的舉例
這篇文章主要介紹了關(guān)于MyBatis中映射對象關(guān)系的舉例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
spring boot整合Shiro實現(xiàn)單點登錄的示例代碼
本篇文章主要介紹了spring boot整合Shiro實現(xiàn)單點登錄的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01

