ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Redis基础篇:Jedis 入门到Jedis 连接池与 Spring Data Redis 实战全解析

Redis基础篇:Jedis 入门到Jedis 连接池与 Spring Data Redis 实战全解析 1. 引言在 Java 生态中操作 Redis 最常用的方式主要有两种一是直接使用 Jedis 客户端二是通过 Spring Data Redis 进行封装操作。Jedis 以其轻量、简单、灵活的特点深受开发者喜爱而 Spring Data Redis 则提供了更高层的抽象让开发者能够以更少的代码完成 Redis 的集成与使用。本文将从 Jedis 入门开始逐步深入到 Jedis 连接池的使用再过渡到 Spring Data Redis 的认识与实践帮助读者从零开始掌握 Java 操作 Redis 的核心技能。2. Jedis 入门2.1 什么是 JedisJedis 是 Redis 官方推荐的 Java 客户端之一它是一套简洁、轻量的 Redis Java 客户端库提供了对 Redis 各种数据类型String、Hash、List、Set、Sorted Set 等的完整操作支持。Jedis 的特点轻量级依赖少上手简单API 设计直观与 Redis 命令一一对应支持连接池、管道、事务等高级特性社区活跃文档丰富2.2 环境准备在开始使用 Jedis 之前需要先完成以下准备工作安装 Redis 服务本地或远程均可创建 Maven 项目引入 Jedis 依赖在pom.xml中添加 Jedis 依赖dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion5.1.0/version/dependency2.3 第一个 Jedis 程序下面通过一个简单的示例演示如何使用 Jedis 连接 Redis 并执行基本操作importredis.clients.jedis.Jedis;publicclassJedisDemo{publicstaticvoidmain(String[]args){// 1. 创建 Jedis 对象指定 Redis 地址和端口JedisjedisnewJedis(localhost,6379);// 2. 如果 Redis 设置了密码需要认证// jedis.auth(yourpassword);// 3. 测试连接System.out.println(连接成功jedis.ping());// 4. 执行基本操作jedis.set(name,张三);Stringnamejedis.get(name);System.out.println(获取到的值name);// 5. 关闭连接jedis.close();}}运行上述程序控制台输出连接成功PONG 获取到的值张三2.4 Jedis 常用数据类型操作Jedis 支持 Redis 的所有数据类型下面分别演示常用操作。2.4.1 String 类型// 设置与获取jedis.set(key,value);Stringvaluejedis.get(key);// 设置过期时间单位秒jedis.setex(code,60,123456);// 自增自减jedis.incr(counter);jedis.decr(counter);2.4.2 Hash 类型// 设置 Hash 字段jedis.hset(user:1,name,李四);jedis.hset(user:1,age,25);// 获取 Hash 字段Stringnamejedis.hget(user:1,name);MapString,Stringuserjedis.hgetAll(user:1);2.4.3 List 类型// 从左侧插入jedis.lpush(list,a,b,c);// 从右侧插入jedis.rpush(list,d);// 获取列表全部元素ListStringlistjedis.lrange(list,0,-1);2.4.4 Set 类型// 添加元素jedis.sadd(set,a,b,c);// 获取所有元素SetStringsetjedis.smembers(set);// 判断元素是否存在booleanexistsjedis.sismember(set,a);2.4.5 Sorted Set 类型// 添加元素并指定分数jedis.zadd(zset,90,张三);jedis.zadd(zset,85,李四);// 按分数升序获取SetStringzsetjedis.zrange(zset,0,-1);// 获取分数Doublescorejedis.zscore(zset,张三);3. Jedis 连接池3.1 为什么需要连接池在真实项目中如果每次操作 Redis 都创建一个新的 Jedis 连接会带来以下问题频繁创建和销毁连接消耗大量系统资源每次连接都需要经过 TCP 三次握手性能开销大高并发场景下连接数过多可能导致 Redis 服务端压力过大连接池的核心思想是预先创建一批连接并保存在池中使用时从池中获取用完后归还从而复用连接避免频繁创建销毁的开销。3.2 JedisPool 的使用Jedis 官方提供了JedisPool连接池实现使用步骤如下importredis.clients.jedis.Jedis;importredis.clients.jedis.JedisPool;importredis.clients.jedis.JedisPoolConfig;publicclassJedisPoolDemo{publicstaticvoidmain(String[]args){// 1. 创建连接池配置JedisPoolConfigconfignewJedisPoolConfig();config.setMaxTotal(50);// 最大连接数config.setMaxIdle(10);// 最大空闲连接数config.setMinIdle(5);// 最小空闲连接数config.setMaxWaitMillis(3000);// 获取连接最大等待时间毫秒// 2. 创建连接池JedisPoolpoolnewJedisPool(config,localhost,6379);// 3. 从连接池获取连接try(Jedisjedispool.getResource()){jedis.set(name,王五);System.out.println(jedis.get(name));}catch(Exceptione){e.printStackTrace();}// 4. 关闭连接池pool.close();}}3.3 连接池核心参数说明参数默认值说明maxTotal8最大连接数连接池中最多能创建的连接数量maxIdle8最大空闲连接数连接池中最多允许保持空闲的连接数量minIdle0最小空闲连接数连接池中至少保持的空闲连接数量maxWaitMillis-1获取连接时的最大等待时间-1 表示无限等待testOnBorrowfalse获取连接时是否校验连接有效性testOnReturnfalse归还连接时是否校验连接有效性3.4 连接池工具类封装在实际项目中通常会将连接池封装成工具类方便全局使用importredis.clients.jedis.Jedis;importredis.clients.jedis.JedisPool;importredis.clients.jedis.JedisPoolConfig;publicclassJedisUtil{privatestaticfinalJedisPoolPOOL;static{JedisPoolConfigconfignewJedisPoolConfig();config.setMaxTotal(50);config.setMaxIdle(10);config.setMinIdle(5);config.setMaxWaitMillis(3000);config.setTestOnBorrow(true);POOLnewJedisPool(config,localhost,6379);}publicstaticJedisgetJedis(){returnPOOL.getResource();}publicstaticvoidclose(Jedisjedis){if(jedis!null){jedis.close();}}publicstaticvoidclosePool(){if(POOL!null){POOL.close();}}}使用工具类JedisjedisJedisUtil.getJedis();try{jedis.set(city,北京);System.out.println(jedis.get(city));}finally{JedisUtil.close(jedis);}3.5 连接池使用注意事项从连接池获取的 Jedis 对象使用完毕后必须归还调用close()否则会耗尽连接池close()方法在连接池场景下是归还连接而非真正关闭连接建议使用 try-with-resources 或 try-finally 确保连接正确归还合理设置maxTotal过小会导致并发不足过大会浪费资源4. 认识 Spring Data Redis4.1 什么是 Spring Data RedisSpring Data Redis 是 Spring 官方提供的数据访问模块它基于 Spring 的抽象体系对 Redis 客户端Jedis、Lettuce 等进行了封装提供了统一的编程模型。Spring Data Redis 的核心价值提供RedisTemplate和StringRedisTemplate等高层 API自动管理连接的生命周期支持序列化策略的灵活配置与 Spring Boot 无缝集成零配置即可使用4.2 Spring Data Redis 与 Jedis 的关系Spring Data Redis 本身并不直接连接 Redis而是通过底层客户端Jedis 或 Lettuce实现连接。可以理解为Jedis 是底层驱动负责真正的网络通信Spring Data Redis 是上层封装提供更友好的 API在 Spring Boot 2.x 之后默认底层客户端由 Jedis 切换为 Lettuce但依然可以通过配置切换回 Jedis。4.3 Spring Boot 集成 Spring Data Redis4.3.1 引入依赖dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency4.3.2 配置文件在application.yml中配置 Redis 连接信息spring:data:redis:host:localhostport:6379password:database:0timeout:3000mslettuce:pool:max-active:50max-idle:10min-idle:5max-wait:3000ms4.3.3 使用 RedisTemplateimportorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Service;ServicepublicclassUserService{AutowiredprivateRedisTemplateString,ObjectredisTemplate;publicvoidsaveUser(Stringkey,Objectvalue){redisTemplate.opsForValue().set(key,value);}publicObjectgetUser(Stringkey){returnredisTemplate.opsForValue().get(key);}}4.4 StringRedisTemplate 与 RedisTemplate 的区别对比项StringRedisTemplateRedisTemplate默认序列化器StringRedisSerializerJdkSerializationRedisSerializer适用场景字符串类型操作对象类型操作可读性存储内容可读存储内容为二进制使用建议推荐用于简单场景需自定义序列化器4.5 自定义序列化配置为了避免 RedisTemplate 默认 JDK 序列化带来的可读性差、体积大等问题通常需要自定义序列化器importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;ConfigurationpublicclassRedisConfig{BeanpublicRedisTemplateString,ObjectredisTemplate(RedisConnectionFactoryfactory){RedisTemplateString,ObjecttemplatenewRedisTemplate();template.setConnectionFactory(factory);// key 使用 String 序列化StringRedisSerializerstringSerializernewStringRedisSerializer();template.setKeySerializer(stringSerializer);template.setHashKeySerializer(stringSerializer);// value 使用 JSON 序列化GenericJackson2JsonRedisSerializerjsonSerializernewGenericJackson2JsonRedisSerializer();template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();returntemplate;}}4.6 常用操作示例// String 操作redisTemplate.opsForValue().set(name,赵六);Stringname(String)redisTemplate.opsForValue().get(name);// Hash 操作redisTemplate.opsForHash().put(user:1,name,钱七);ObjectuserNameredisTemplate.opsForHash().get(user:1,name);// List 操作redisTemplate.opsForList().leftPush(list,a);ListObjectlistredisTemplate.opsForList().range(list,0,-1);// Set 操作redisTemplate.opsForSet().add(set,a,b);SetObjectsetredisTemplate.opsForSet().members(set);// ZSet 操作redisTemplate.opsForZSet().add(zset,张三,90);SetObjectzsetredisTemplate.opsForZSet().range(zset,0,-1);// 设置过期时间redisTemplate.expire(name,60,TimeUnit.SECONDS);5. 从入门到实战综合案例5.1 案例需求实现一个简单的用户缓存服务包含以下功能用户信息写入 Redis 缓存根据用户 ID 查询用户信息先查缓存缓存未命中则查数据库并回填用户信息更新后同步更新缓存用户删除时清除缓存5.2 实体类importlombok.Data;DatapublicclassUser{privateLongid;privateStringname;privateIntegerage;privateStringemail;}5.3 Service 实现importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Service;importjava.util.concurrent.TimeUnit;ServicepublicclassUserService{privatestaticfinalStringUSER_KEY_PREFIXuser:;AutowiredprivateRedisTemplateString,ObjectredisTemplate;// 模拟数据库privatefinalMapLong,UseruserDbnewHashMap();publicUsergetUserById(Longid){StringkeyUSER_KEY_PREFIXid;// 1. 先查缓存Useruser(User)redisTemplate.opsForValue().get(key);if(user!null){System.out.println(从缓存中获取用户user.getName());returnuser;}// 2. 缓存未命中查数据库useruserDb.get(id);if(user!null){// 3. 回填缓存设置过期时间 30 分钟redisTemplate.opsForValue().set(key,user,30,TimeUnit.MINUTES);System.out.println(从数据库获取用户并回填缓存user.getName());}returnuser;}publicvoidsaveUser(Useruser){// 保存到数据库userDb.put(user.getId(),user);// 同步更新缓存StringkeyUSER_KEY_PREFIXuser.getId();redisTemplate.opsForValue().set(key,user,30,TimeUnit.MINUTES);}publicvoiddeleteUser(Longid){// 删除数据库记录userDb.remove(id);// 清除缓存StringkeyUSER_KEY_PREFIXid;redisTemplate.delete(key);}}5.4 缓存策略总结缓存穿透查询不存在的数据缓存和数据库都没有。可通过缓存空值或布隆过滤器解决缓存击穿热点 key 过期瞬间大量请求打到数据库。可通过互斥锁或逻辑过期解决缓存雪崩大量 key 同时过期导致数据库压力骤增。可通过随机过期时间或集群部署解决6. 总结本文从 Jedis 入门开始介绍了 Jedis 的基本使用和常用数据类型操作随后深入讲解了 Jedis 连接池的原理与使用包括核心参数配置和工具类封装接着认识了 Spring Data Redis了解了它与 Jedis 的关系、Spring Boot 集成方式以及序列化配置最后通过一个综合案例演示了从入门到实战的完整流程。在实际项目中建议根据场景选择合适的方案简单项目或非 Spring 环境直接使用 Jedis 连接池Spring Boot 项目优先使用 Spring Data Redis默认底层为 Lettuce需要更高性能或响应式编程考虑 Lettuce 或 Redisson希望本文能帮助读者建立起 Java 操作 Redis 的完整知识体系在实际项目中灵活运用。
返回列表