共同点:都提供了基于 Redis 操作的 Java API,只是封装程度,具体实现稍有不同。
不同点:
1.1、Jedis
是 Redis 的 Java 实现的客户端。支持基本的数据类型如:String、Hash、List、Set、Sorted Set。
特点:使用阻塞的 I/O,方法调用同步,程序流需要等到 socket 处理完 I/O 才能执行,不支持异步操作。Jedis 客户端实例不是线程安全的,需要通过连接池来使用 Jedis。
1.1、Redisson
优点点:分布式锁,分布式集合,可通过 Redis 支持延迟队列。
1.3、 Lettuce
用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。
基于 Netty 框架的事件驱动的通信层,其方法调用是异步的。Lettuce 的 API 是线程安全的,所以可以操作单个 Lettuce 连接来完成各种操作。
maven 配置引入,(要加上版本号,我这里是因为 Parent 已声明)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application-dev.yml
spring:
redis:
host: 192.168.1.140
port: 6379
password:
database: 15 # 指定redis的分库(共16个0到15)
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public CustomersEntity findById(Integer id) {
// 需要缓存
// 所有涉及的缓存都需要删除,或者更新
try {
String toString = stringRedisTemplate.opsForHash().get(REDIS_CUSTOMERS_ONE, id + "").toString();
if (toString != null) {
return JSONUtil.toBean(toString, CustomersEntity.class);
}
} catch (Exception e) {
e.printStackTrace();
}
// 缓存为空的时候,先查,然后缓存redis
Optional<CustomersEntity> byId = customerRepo.findById(id);
if (byId.isPresent()) {
CustomersEntity customersEntity = byId.get();
try {
stringRedisTemplate.opsForHash().put(REDIS_CUSTOMERS_ONE, id + "", JSONUtil.toJsonStr(customersEntity));
} catch (Exception e) {
e.printStackTrace();
}
return customersEntity;
}
return null;
}
opsForHash --> hash 操作
opsForList --> list 操作
opsForSet --> set 操作
opsForValue --> string 操作
opsForZSet --> Zset 操作
参考 RedisTemplate 配置
另外,还需要额外的配置类
// todo 定义序列化,解决乱码问题
@EnableCaching
@Configuration
@ConfigurationProperties(prefix = "spring.cache.redis")
public class RedisCacheConfig {
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
@Transactional
@Service
public class ReImpl implements RedisService {
@Resource
private CustomerRepo customerRepo;
@Resource
private StringRedisTemplate stringRedisTemplate;
public static final String REDIS_CUSTOMERS_ONE = "Customers";
public static final String REDIS_CUSTOMERS_ALL = "allList";
// =====================================================================使用Spring cahce 注解方式实现缓存
// ==================================单个操作
@Override
@Cacheable(value = "cache:customer", unless = "null == #result",key = "#id")
public CustomersEntity cacheOne(Integer id) {
final Optional<CustomersEntity> byId = customerRepo.findById(id);
return byId.isPresent() ? byId.get() : null;
}
@Override
@Cacheable(value = "cache:customer", unless = "null == #result", key = "#id")
public CustomersEntity cacheOne2(Integer id) {
final Optional<CustomersEntity> byId = customerRepo.findById(id);
return byId.isPresent() ? byId.get() : null;
}
// todo 自定义redis缓存的key,
@Override
@Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")
public CustomersEntity cacheOne3(Integer id) {
final Optional<CustomersEntity> byId = customerRepo.findById(id);
return byId.isPresent() ? byId.get() : null;
}
// todo 这里缓存到redis,还有响应页面是String(加了很多转义符\,),不是Json格式
@Override
@Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")
public String cacheOne4(Integer id) {
final Optional<CustomersEntity> byId = customerRepo.findById(id);
return byId.map(JSONUtil::toJsonStr).orElse(null);
}
// todo 缓存json,不乱码已处理好,调整序列化和反序列化
@Override
@Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")
public CustomersEntity cacheOne5(Integer id) {
Optional<CustomersEntity> byId = customerRepo.findById(id);
return byId.filter(obj -> !StrUtil.isBlankIfStr(obj)).orElse(null);
}
// ==================================删除缓存
@Override
@CacheEvict(value = "cache:customer", key = "'cacheOne5' + '.' + #id")
public Object del(Integer id) {
// 删除缓存后的逻辑
return null;
}
@Override
@CacheEvict(value = "cache:customer",allEntries = true)
public void del() {
}
@CacheEvict(value = "cache:all",allEntries = true)
public void delall() {
}
// ==================List操作
@Override
@Cacheable(value = "cache:all")
public List<CustomersEntity> cacheList() {
List<CustomersEntity> all = customerRepo.findAll();
return all;
}
// todo 先查询缓存,再校验是否一致,然后更新操作,比较实用,要清楚缓存的数据格式(明确业务和缓存模型数据)
@Override
@CachePut(value = "cache:all",unless = "null == #result",key = "#root.methodName")
public List<CustomersEntity> cacheList2() {
List<CustomersEntity> all = customerRepo.findAll();
return all;
}
}
基于 spring 缓存实现