一、 Redis介绍
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库,具有以下特点:
1. Redis 与其他 key - value 缓存产品有以下特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
2. Redis特性优势:
- 性能极高 – Redis单机能读的速度是110000次/s, 写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
二、 Spring Boot Redis 集成说明
Java 封装的常用Redis框架有Jedis、Redisson和Lettuce等,这些框架帮我们解决了Redis的连接管理、API操作问题, Spring Boot 在 Lettuce基础上做了进一步封装, 提供了spring-boot-starter-data-redis组件, 帮助我们更为简化方便的使用Redis功能。 之所以选择Lettuce, 相比其他Redis框架,Lettuce是基于Netty框架的事件驱动实现,方法调用为异步处理。Lettuce的API操作是线程安全的, 三个框架对比:
-
Jedis:是老牌的Redis的Java实现客户端,提供了比较全面的Redis命令的支持, 但是对分布式锁、集群等功能支持不够完善。
-
Redisson:实现了分布式和可扩展的Java数据结构,但对于Redis的命令支持不够完善。
-
Lettuce:在线程安全同步,异步和响应使用上有较好的支持, 同时支持集群,Sentinel,管道和编码器。
Spring-boot-data-redis 提供了几个Redis操作模板, 例如: RedisTemplate、StringRedisTemplate、ReactiveRedisTemplate、 ReactiveStringRedisTemplate、RedisKeyValueTemplate等。下面对各模板的使用进行详细讲解。
三、 Spring Boot 与Redis集成
-
创建工程spring-boot-nosql-redis
启动类:
com.mirson.spring.boot.nosql.redis.startup.NosqlRedisApplication
@SpringBootApplication @ComponentScan(basePackages = {"com.mirson"}) public class NosqlRedisApplication { public static void main(String[] args) { SpringApplication.run(NosqlRedisApplication.class, args); } }
-
MAVEN依赖
pom.xml
<dependencies> <!-- Spring boot data redis 组件依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies>
默认采用父依赖的2.1.6.RELEASE版本。
-
配置文件
application.yml
server: port: 11612 spring: application: name: nosql-redis # Redis 缓存配置 redis: host: 127.0.0.1 password: port: 6379 jedis: pool: # 最大连接数 max-active: 16 # 空闲最大连接数 max-idle: 4 # 空闲最小连接数 min-idle: 2 # 连接分配最长等待时间 max-wait: 500
配置Redis主机连接信息, 配置连接池信息, 包含最大连接数、空闲最大连接数、空闲最小连接数和连接分配最长等待时间, 根据项目实际需要进行配置。
-
Java Config 配置
com.mirson.spring.boot.nosql.redis.config.RedisConfiguration
@Configuration @EnableCaching public class RedisConfiguration { /** * Redis 缓存配置 * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); /// 配置KEY序列化方式 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // 配置VALUE的序列化方式 redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer()); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } /** * 设置默认超时时间 * @param redisConnectionFactory * @return */ @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { // 超时时间默认设为24小时 Duration expiration = Duration.ofSeconds(3600 * 24); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(expiration)).build(); } /** * 设置Redis 响应式操作模板 * @param factory * @return */ @Bean ReactiveStringRedisTemplate reactiveStringRedisTemplate(ReactiveRedisConnectionFactory factory) { return new ReactiveStringRedisTemplate(factory); } }
- 要开启@EnableCaching注解, 否则redisTemplate配置不能正在生效。
- 配置RedisTemplate, 主要是key和value的序列化方式,key采用string序列化, 便于查询。
- CacheManager配置, 指定超时时间为24小时。CacheManager是Spring Cache的接口, 可以基于不同缓存实现, 如Redis、Memcached等。不作配置, Spring data Redis 启动器也会自动加载。
- ReactiveStringRedisTemplate是响应式操作模板, 接下来要使用, 需要先作配置。
四、 Spring Boot 集成Redis之CacheManager使用
-
提供缓存更新操作接口
com.mirson.spring.boot.nosql.redis.controller.RedisController
/** * cache manager 缓存更新操作 * @param key * @param value * @return */ @GetMapping("/cache/put") public String cachePut(String key, String value) { cacheManager.getCache(CACHE_NAME).put(key, value); return "cacheManager, put redis key: " + key + ", value: " + value; } /** * cache manager 缓存删除操作 * @param key * @param value * @return */ @GetMapping("/cache/evict") public String cacheEvict(String key) { cacheManager.getCache(CACHE_NAME).evict(key); return "cacheManager, evict redis key: " + key ; }
提供缓存的更新与删除操作接口, CacheManager缓存使用, 需先指定一个Cache名称,其实也就是Redis的Key前缀, 该Cache所有缓存key都会放在其下面。
-
提供缓存查找接口
com.mirson.spring.boot.nosql.redis.controller.RedisController
/** * cache manager 缓存查找 * @param key * @return */ @GetMapping("/cache/find") public String cacheFind(String key) { Set<String> keys = redisTemplate.keys(CACHE_NAME + "::" + key + "*"); StringBuffer result = new StringBuffer(); if (null != keys && !keys.isEmpty()) { Cache cache = cacheManager.getCache(CACHE_NAME); keys.forEach( k -> { // 获取缓存 Cache.ValueWrapper valueWrapper = cache.get(k.replaceAll(CACHE_NAME + "::", "")); if (cache != null && valueWrapper != null) { String value = (String)valueWrapper.get(); result.append("key: ").append(k).append(", value: ").append(value).append("<br>"); } }); }else { result.append("not found."); } return result.toString().replaceAll("<br>$", ""); }
CacheManager自身没有提供比较完善的Key查询接口, 如果需要查询Cache下面的所有key, 可以通过redisTemplate的keys接口来帮助实现。
-
测试验证
-
增加三条缓存记录
商品: goods1, 价格: 10.11
http://127.0.0.1:11612/cache/put?key=goods1&value=10.11
商品: goods2, 价格: 10.12
http://127.0.0.1:11612/cache/put?key=goods2&value=10.12
商品: goods3, 价格: 10.13
http://127.0.0.1:11612/cache/put?key=goods3&value=10.13
-
查看缓存记录
http://127.0.0.1:11612/cache/find?key=goods
能够正常获取刚才设置的三条缓存数据。
-
删除缓存记录
将第二条商品记录删除
http://127.0.0.1:11612/cache/evict?key=goods2
重新查看缓存记录
正确删除了第二条商品记录。
-
五、 Spring Boot 集成Redis之模板使用
RedisTemplate有多种, 每个模板的key和value的序列化方式存在不同, 其他接口功能基本类似, 这里就以常用的stringRedisTemplate作为讲解。
-
提供缓存更新操作接口
com.mirson.spring.boot.nosql.redis.controller.RedisController
/** * string template 缓存更新操作 * @param key * @param value * @return */ @GetMapping("/template/put") public String stringPut(String key, String value) { stringRedisTemplate.opsForValue().set(key, value); return "stringTemplate, put redis key: " + key + ", value: " + value; } /** * string template 缓存更新操作 * @param key * @param value * @return */ @GetMapping("/template/del") public String stringDel(String key, String value) { stringRedisTemplate.delete(key); return "stringTemplate, delete redis key: " + key; }
-
提供缓存查找接口
/** * template 缓存查找 * @param key * @return */ @GetMapping("/template/find") public String templateFind(String key) { Set<String> keys = stringRedisTemplate.keys( key + "*"); StringBuffer result = new StringBuffer(); if (null != keys && !keys.isEmpty()) { keys.forEach( k -> { String value = stringRedisTemplate.opsForValue().get(k); result.append("key: ").append(k).append(", value: ").append(value).append("<br>"); }); }else { result.append("not found."); } return result.toString().replaceAll("<br>$", ""); }
-
测试验证
-
增加三条缓存记录
用户:user1,年龄:25
http://127.0.0.1:11612/template/put?key=user1&value=25
用户:user2,年龄:26
http://127.0.0.1:11612/template/put?key=user2&value=26
用户:user3,年龄:27
http://127.0.0.1:11612/template/put?key=user3&value=27
-
查看缓存记录
http://127.0.0.1:11612/template/find?key=user
正常获取设置的三条缓存记录。
-
删除缓存记录
将第二条用户记录删除
http://127.0.0.1:11612/template/del?key=user2
重新查询缓存记录
正确删除第二条用户记录。
-
六、 Spring Boot 集成Redis之响应式使用
Spring Data Redis 是可以支持响应式编程, 通过Reactive模式, 设置回调方法, 能够让线程处理其他事务, 不会因为Redis操作阻塞程序运行。
-
提供缓存更新操作接口
com.mirson.spring.boot.nosql.redis.controller.RedisController
/** * redis reactive 更新缓存 * @param key * @param value * @return */ @GetMapping("/reactive/put") public String reactivePut(String key, String value) { Mono result = reactiveStringRedisTemplate.opsForValue().set(key, value); String message = "reactive, put redis key: " + key + ", value: " + value; result.subscribe(log::info); log.info(message); return message ; } /** * redis reactive 删除缓存 * @param key * @param value * @return */ @GetMapping("/reactive/del") public String reactiveDel(String key, String value) { Mono result = reactiveStringRedisTemplate.delete(key); String message = "reactive, delete redis key: " + key + ", value: " + value; result.subscribe(log::info); log.info(message); return message ; }
提供了reactive模式的更新与删除缓存接口, 查询接口仍采用template模板方式查询。
reactive为异步模式, 通过回调方法处理结果, 注意日志打印位置, 验证时, 通过控制台日志输出,可以看到为异步处理方式。
-
测试验证
-
增加三条缓存记录
省份:province1, 名称: 广东省
http://127.0.0.1:11612/reactive/put?key=province1&value=%E5%B9%BF%E4%B8%9C%E7%9C%81省份:province2,名称: 广西省
http://127.0.0.1:11612/reactive/put?key=province2&value=%E5%B9%BF%E8%A5%BF%E7%9C%81
省份:province3,名称: 江西省
http://127.0.0.1:11612/reactive/put?key=province3&value=%E6%B1%9F%E8%A5%BF%E7%9C%81 -
查看控制台日志
可以看到, 日志输出顺序已经发生变化,
-
查看缓存记录
http://127.0.0.1:11612/template/find?key=province
从缓存里面正常获取三条记录。
-
七、总结
Spring Boot Starter Data Redis 对Redis作了比较完善的封装,功能支持比较丰富, 通过Template模板, 可以定制所需的各种数据结构与序列化方式, Reactive封装对响应式编程提供良好支持, 底层基于Lettuce实现, 性能也有较好的保障,本章基于Spring Data Redis所提供的不同使用模式作了讲解,里面还有很多丰富的API接口功能, 有兴趣可以再做深入研究。
附: 所有源码都已上传, 如有需要, 可在博主的资源中下载。