Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

06-02 1182阅读

引言

在分布式系统和高并发场景中,Redis 作为高性能内存数据库的地位举足轻重。对于 Java 开发者而言,掌握 Redis 的连接与操作是进阶必备技能。然而,从基础的 Jedis 原生客户端到 Spring 封装的 RedisTemplate,不同连接方式的原理与适用场景常让初学者困惑。如何选择合适的连接方式?序列化配置背后的逻辑是什么?生产环境中又该如何优化?

本文从 Java 操作 Redis 的核心需求出发,通过完整代码示例与逐行解析,系统讲解 Jedis 直接连接、连接池、RedisTemplate 及 StringRedisTemplate 的使用方法,深入剖析连接原理、序列化机制与性能优化策略。无论你是刚接触 Redis 的小白,还是需要规范项目实践的开发者,都能从代码细节与原理分析中获得启发,掌握从基础连接到高级应用的全流程实战技巧。

1. Redis 基础概念与 Java 生态概览

1.1 Redis 是什么?

Redis(Remote Dictionary Server)是一个基于内存的高性能键值对存储系统,具有以下核心特性:

  • 数据结构丰富:支持 String、Hash、List、Set、Sorted Set 等 8 种数据结构

  • 内存级性能:读写速度可达 10 万 + 次 / 秒(String 类型)

  • 持久化支持:提供 RDB(快照)和 AOF(日志)两种持久化方式

  • 集群能力:支持主从复制、哨兵模式、Cluster 集群

  • 多语言支持:提供 Java、Python、Node.js 等多语言客户端

    在 Java 生态中,主流的 Redis 客户端包括:

    1. Jedis:官方提供的原生 Java 客户端,支持同步阻塞式 IO

    2. Lettuce:基于 Netty 的异步非阻塞客户端,支持响应式编程

    3. Spring Data Redis:Spring 封装的高层抽象,支持 Jedis/Lettuce 作为底层连接

    1.2 Java 操作 Redis 的核心场景

    • 缓存系统:降低数据库压力(如商品详情页缓存)

    • 分布式会话:解决集群环境下的 Session 共享问题

    • 计数器:实现点赞计数、接口限流等功能(利用 INCR 命令)

    • 消息队列:基于 List 的 LPUSH/RPOP 实现简单队列

    • 分布式锁:通过 SETNX 命令实现分布式锁机制

      2.Jedis 原生客户端:从直接连接到连接池

      2.0 Maven依赖

              
                  redis.clients
                  jedis
                  3.7.0
              
      

      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);
              //设置密码
              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 map = jedis.hgetAll("user:1");
               log.info("map:"+ map.toString());
          }
          @AfterEach
          public void tearDown(){
              if(jedis != null){
                  jedis.close();
              }
          }
      }
      

      代码的执行结果:

      结果1:

      Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

      结果2:

      Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

      2.1.2 核心类与对象

      • Jedis:核心客户端类,封装了所有 Redis 命令

        • 构造方法: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 原理分析

            1. 连接过程:
            • 创建 Jedis 实例时建立 TCP 连接(三次握手)

            • 通过 auth 命令进行密码验证(如果配置了密码)

            • select 命令选择操作的数据库(默认 0 号库)

              1. 命令执行:
              • 客户端将命令序列化为字节流发送到 Redis 服务器

              • 服务器执行命令后返回结果,客户端解析响应

                2.1.4 优缺点

                • 优点:简单直观,适合学习和小规模测试

                • 缺点:

                  • 每次测试都创建新连接,性能低下(TCP 连接创建开销大)

                  • 并发场景下可能导致连接风暴

                  • 没有连接复用机制,资源利用率低

                    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);
                            //设置最长等待时间
                            jedisPoolConfig.setMaxWaitMillis(200);
                            jedisPool = new JedisPool(jedisPoolConfig,"x.x.x.x",6379,
                                    1000,"xxxx");
                        }
                        //获取jedis对象
                        public static Jedis getJedis(){
                            return jedisPool.getResource();
                        }
                    }
                    

                    说明:

                    • JedisPool:连接池核心类,管理连接的创建和回收

                      • getResource():从连接池获取可用连接(可能从空闲队列获取或新建)
                      • JedisPoolConfig:连接池配置类,常用参数:

                        • maxTotal:最大连接数(控制并发量)

                        • maxIdle:最大空闲连接数(避免空闲连接过多)

                        • minIdle:最小空闲连接数(保证基础可用连接)

                        • maxWaitMillis:获取连接超时时间(避免无限阻塞)

                          2.2.2 连接池工作原理

                          1. 初始化阶段:
                          • 启动时创建minIdle数量的空闲连接
                            1. 获取连接:
                            • 优先从空闲队列中获取连接

                            • 若空闲队列为空,且当前连接数小于maxTotal,则新建连接

                            • 若连接数已达maxTotal,则等待maxWaitMillis时间

                              1. 归还连接:
                              • 调用close()方法时,连接不会真正关闭,而是放回空闲队列

                              • 空闲连接数超过maxIdle时,多余连接会被销毁

                                2.2.3 使用示例

                                @Slf4j
                                @SpringBootTest
                                public class JedisPool {
                                    private Jedis jedis;
                                    @BeforeEach
                                    public void setUp(){
                                        //建立连接
                                        jedis = JedisConnectionFactory.getJedis();
                                        //设置密码
                                        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 map = jedis.hgetAll("user:1");
                                        log.info("map:"+ map.toString());
                                    }
                                    @AfterEach
                                    public void tearDown(){
                                        if(jedis != null){
                                            jedis.close();
                                        }
                                    }
                                }
                                

                                运行结果:

                                结果1:

                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                结果2:

                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                2.2.5 优势对比

                                特性 直接连接 连接池方式
                                连接创建 每次新建 复用已有连接
                                并发支持 好(控制连接数)
                                资源利用率
                                性能 差(连接开销) 好(减少握手)
                                适用场景 单线程测试 高并发生产环境

                                3. Spring Data Redis:高层抽象与模板化操作

                                3.1 核心依赖与配置

                                3.1.1 Maven 依赖

                                        
                                            org.springframework.boot
                                            spring-boot-starter-data-redis
                                        
                                

                                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 基础操作示例

                                @SpringBootTest
                                @Slf4j
                                public class RedisTem {
                                    @Autowired
                                    private RedisTemplate redisTemplate;
                                    @Test
                                    public void test(){
                                        //插入一条String类型的数据
                                        redisTemplate.opsForValue().set("nameTem","赵六");
                                        Object s = redisTemplate.opsForValue().get("nameTem");
                                        log.info("nameTem:"+ s);
                                    }
                                }
                                

                                运行结果:

                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                3.2.2 核心类结构

                                • RedisTemplate:

                                  • 泛型参数: 分别表示键和值的类型

                                  • 核心方法:

                                    • opsForValue():获取字符串操作对象(对应 String 类型)

                                    • opsForHash():获取 Hash 操作对象(对应 Hash 类型)

                                    • opsForList():获取列表操作对象(对应 List 类型)

                                    • opsForSet():获取集合操作对象(对应 Set 类型)

                                    • opsForZSet():获取有序集合操作对象(对应 Sorted Set 类型)

                                    • RedisConnectionFactory:

                                      • 连接工厂接口,支持 Jedis/Lettuce 等多种实现

                                      • Spring 自动根据依赖加载对应的实现(如引入 jedis 依赖则使用 JedisConnectionFactory)

                                        3.3 序列化机制详解

                                        3.3.1 默认序列化问题

                                        • Spring Data Redis 默认使用JdkSerializationRedisSerializer:

                                          • 序列化后数据冗余(包含类名、版本号等信息)
                                          • 依赖类必须实现Serializable接口
                                          • 跨语言不兼容(如 Python 无法解析 JDK 序列化数据)

                                            3.3.2 JSON 序列化配置

                                            @Configuration
                                            public class RedisConfig {
                                                @Bean
                                                public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
                                                    // 创建redisTemplate对象
                                                    RedisTemplate redisTemplate = new RedisTemplate();
                                                    //设置连接工厂
                                                    redisTemplate.setConnectionFactory(connectionFactory);
                                                    // 创建json序列化工具
                                                    GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
                                                    //设置Key的序列化
                                                    redisTemplate.setKeySerializer(RedisSerializer.string());
                                                    redisTemplate.setHashKeySerializer(RedisSerializer.string());
                                                    //设置value的序列化
                                                    redisTemplate.setValueSerializer(jsonRedisSerializer);
                                                    redisTemplate.setHashValueSerializer(jsonRedisSerializer);
                                                    return redisTemplate;
                                                }
                                            }
                                            

                                            3.3.3 序列化流程

                                            1. 存储数据:
                                            • 值对象(如 User 对象)通过 JSON 序列化工具转为 JSON 字符串

                                            • 键和 Hash 键通过 String 序列化转为字节数组

                                              1. 读取数据:
                                              • 从 Redis 获取字节数组后,键反序列化为 String

                                              • 值反序列化为对应的对象(通过 Jackson 的类型推断)

                                                3.4 对象存储实战(序列化配置后)

                                                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 map = (Map)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);
                                                    }
                                                }
                                                

                                                运行结果:

                                                结果1:

                                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                                结果2:

                                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                                结果3:

                                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                                3.4.3 关键细节

                                                • 类型转换:

                                                  • opsForValue().set(key, value) 支持任意对象,内部自动序列化
                                                  • opsForValue().get(key) 返回 Object 类型,需手动强转(依赖序列化配置)
                                                  • Hash 操作:

                                                    • opsForHash().put(key, field, value) 存储 Hash 字段,value 自动序列化
                                                    • entries() 方法返回 Map,字段值已反序列化

                                                      4. StringRedisTemplate:专注字符串场景

                                                      4.1 基本概念

                                                      • StringRedisTemplate 是 RedisTemplate 的子类

                                                      • 默认配置:

                                                        • 键序列化:StringRedisSerializer(等同于RedisSerializer.string())

                                                        • 值序列化:StringRedisSerializer(直接存储字符串)

                                                          4.2 对象操作实战

                                                          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);
                                                                  // 获取数据
                                                                  String val = stringRedisTemplate.opsForValue().get("UserRedis");
                                                                  // 手动反序列化
                                                                  User userValue = mapper.readValue(val,User.class);
                                                                  log.info(userValue.toString());
                                                              }
                                                          }
                                                          

                                                          运行结果:

                                                          Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                                          4.2.2 核心步骤解析

                                                          1. 序列化:
                                                          • 使用 Jackson 的ObjectMapper将 User 对象转为 JSON 字符串

                                                          • 解决StringRedisTemplate只能存储字符串的限制

                                                            1. 存储与获取:
                                                            • opsForValue().set(key, value) 直接存储字符串

                                                            • opsForValue().get(key) 直接获取字符串

                                                              1. 反序列化:
                                                              • 将获取的 JSON 字符串转为 User 对象

                                                              • 需要处理可能的JsonProcessingException异常

                                                                4.3 与 RedisTemplate 的对比

                                                                特性 RedisTemplate StringRedisTemplate
                                                                泛型参数 任意类型
                                                                序列化 支持自定义序列化 固定 String 序列化
                                                                对象操作 自动序列化 / 反序列化 需手动序列化 / 反序列化
                                                                键类型 任意类型(需序列化) 只能是 String 类型
                                                                适用场景 复杂数据类型(对象、Hash 等) 纯字符串场景(如缓存文本)

                                                                5. 连接方式深度对比与选型建议

                                                                5.1 技术维度对比

                                                                维度 Jedis 直接连接 Jedis 连接池 RedisTemplate StringRedisTemplate
                                                                连接管理 手动创建 连接池管理 框架管理 框架管理
                                                                序列化支持 无(需手动) 支持自定义 仅 String 序列化
                                                                Spring 集成 强(自动装配) 强(自动装配)
                                                                学习成本
                                                                并发性能

                                                                5.2 场景化选型建议

                                                                5.2.1 学习阶段

                                                                • 推荐使用 Jedis 直接连接:

                                                                  • 代码简单,便于理解 Redis 基本操作

                                                                  • 适合单个命令测试(如 GET/SET/HSET 等)

                                                                    5.2.2 小型项目(非 Spring)

                                                                    • 推荐 Jedis 连接池:

                                                                      • 避免频繁创建连接,提升性能

                                                                      • 手动管理连接,适合轻量级项目

                                                                        5.2.3 Spring Boot 项目

                                                                        • 优先使用 RedisTemplate:

                                                                          • 与 Spring 生态无缝集成(依赖注入、配置管理)

                                                                          • 支持复杂数据类型和自定义序列化

                                                                          • 推荐配置 JSON 序列化,兼容对象存储

                                                                            5.2.4 纯字符串场景

                                                                            • 使用 StringRedisTemplate:

                                                                              • 简化字符串操作(避免泛型转换)
                                                                              • 性能略优(减少序列化层开销)

                                                                                5.3 生产环境最佳实践

                                                                                1. 连接池配置:
                                                                                • maxTotal设置为系统并发量的 1.5-2 倍

                                                                                • maxWaitMillis不超过 200ms(避免过长阻塞)

                                                                                • minIdle设置为 5-10(保证基础连接可用性)

                                                                                  1. 序列化选择:
                                                                                  • 统一使用 JSON 序列化(GenericJackson2JsonRedisSerializer)

                                                                                  • 键使用 String 序列化(保证可读性和可维护性)

                                                                                    1. 异常处理:
                                                                                    • 添加try-catch-finally块,确保连接归还

                                                                                    • 处理JedisConnectionException等网络异常

                                                                                      1. 监控与调优:
                                                                                      • 监控连接池的空闲连接数、活跃连接数

                                                                                      • 使用 Redis 的INFO connection命令查看服务器连接状态

                                                                                        6. 常见问题与解决方案

                                                                                        6.1 连接失败问题

                                                                                        现象:

                                                                                        • 抛出JedisConnectionException: ``java.net``.ConnectException: Connection refused

                                                                                          可能原因:

                                                                                          1. Redis 服务器未启动

                                                                                          2. IP 地址或端口错误(检查配置中的 host 和 port)

                                                                                          3. 防火墙阻止连接(需开放 6379 端口)

                                                                                          4. Redis 密码错误(auth 命令失败)

                                                                                            解决方案:

                                                                                          5. 确保 Redis 服务器正常运行(redis-cli ping检查连通性)

                                                                                          6. 核对配置中的连接参数(IP、端口、密码)

                                                                                          7. 检查服务器防火墙设置(如 Linux 的firewall-cmd)

                                                                                          6.2 数据乱码问题

                                                                                          现象:

                                                                                          • Redis 存储的字符串在 Java 中获取时出现乱码

                                                                                            可能原因:

                                                                                            1. 未正确设置字符编码(Jedis 默认使用 UTF-8)

                                                                                            2. 序列化方式不匹配(如 RedisTemplate 使用 JDK 序列化,手动使用字符串读取)

                                                                                            解决方案:

                                                                                            1. Jedis 中指定编码:
                                                                                            jedis.get("key", StandardCharsets.UTF\_8); // 显式指定编码
                                                                                            
                                                                                            1. RedisTemplate 统一使用 String 序列化:
                                                                                            template.setKeySerializer(RedisSerializer.string());
                                                                                            

                                                                                            6.3 对象反序列化失败

                                                                                            现象:

                                                                                            • 从 Redis 获取对象时抛出ClassNotFoundException

                                                                                              可能原因:

                                                                                              1. 使用 JDK 序列化时,类路径不一致(如部署环境类缺失)

                                                                                              2. JSON 序列化时,对象缺少无参构造函数(Jackson 需要)

                                                                                              解决方案:

                                                                                              1. 改用 JSON 序列化(避免类路径问题)
                                                                                              2. 确保实体类包含无参构造函数(Lombok 的@Data默认生成)

                                                                                              7. 扩展知识:异步客户端 Lettuce

                                                                                              7.1 Lettuce 简介

                                                                                              • 基于 Netty 的异步非阻塞客户端

                                                                                              • 支持响应式编程(Reactor 模式)

                                                                                              • 适合高并发、高吞吐量场景

                                                                                                7.2 核心差异

                                                                                                特性 Jedis Lettuce
                                                                                                IO 模型 同步阻塞 异步非阻塞
                                                                                                连接方式 每个线程一个连接 单个连接处理多个请求
                                                                                                线程安全 非线程安全 线程安全
                                                                                                适用场景 简单同步场景 异步 / 反应式场景

                                                                                                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. 总结:从入门到实战的成长路径

                                                                                                8.1 学习阶段建议

                                                                                                1. 基础操作:掌握 Jedis 直接连接,理解 Redis 基本命令(SET/GET/HSET 等)

                                                                                                2. 性能优化:学习连接池原理,掌握 JedisPool 配置与使用

                                                                                                3. 框架集成:深入 Spring Data Redis,学会配置 RedisTemplate 和序列化

                                                                                                4. 实战提升:在项目中应用缓存、分布式锁等场景,处理实际问题

                                                                                                8.2 核心知识图谱

                                                                                                Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

                                                                                                8.3 结语

                                                                                                通过本文的系统学习,读者应能熟练掌握 Java 操作 Redis 的主流方式,理解不同连接方式的适用场景和底层原理,并能够在实际项目中根据需求选择合适的技术方案。记住,实践是最好的老师,建议通过实际项目练习加深理解,遇到问题时结合官方文档和源码进行分析,逐步提升 Redis 开发与运维能力。

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码