Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库,具有以下特点:
1. Redis 与其他 key - value 缓存产品有以下特点:
2. 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-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>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
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);
}
}
提供缓存更新操作接口
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("
");
}
});
}else {
result.append("not found.");
}
return result.toString().replaceAll("
$", "");
}
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
重新查看缓存记录
正确删除了第二条商品记录。
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("
");
});
}else {
result.append("not found.");
}
return result.toString().replaceAll("
$", "");
}
测试验证
增加三条缓存记录
用户: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 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接口功能, 有兴趣可以再做深入研究。
附: 所有源码都已上传, 如有需要, 可在博主的资源中下载。