共计 6176 个字符,预计需要花费 16 分钟才能阅读完成。
Redis 装置
Redis 的装置网上文档很多,官网也有十分具体的装置文档,这里就不再赘述,如果是集体开发,倡议应用 Docker 进行装置,只需以下一行命令即可实现残缺
docker run -itd --name redis -p 6379:6379 redis
执行以下命令查看是否运行胜利
➜ docker exec -it redis redis-cli
127.0.0.1:6379> ping
PONG
Spring boot 集成 Redis
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
- 配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
#客户端超时
spring.redis.timeout=10000
#最大连接数
spring.redis.lettuce.pool.max-active=20
#最小闲暇
spring.redis.lettuce.pool.min-idle=5
#连贯超时
spring.redis.lettuce.pool.max-wait=5000ms
#最大闲暇
spring.redis.lettuce.pool.max-idle=20
- 启动类增加注解
@EnableCaching
@SpringBootApplication
@EnableCaching
public class RedisApplication {public static void main(String[] args) {SpringApplication.run(RedisApplication.class, args);
}
}
- 编写配置类,能够参考以下代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* @Description:
* @author: jianfeng.zheng
* @since: 2021/3/3 10:53 下午
* @history: 1.2021/3/3 created by jianfeng.zheng
*/
@Configuration
public class RedisConfig {
@Bean
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
redisCacheConfiguration.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
Map<String, RedisCacheConfiguration> redisExpireConfig = new HashMap<>();
// 这里设置了一个一分钟的超时配置,如果须要减少更多超时配置参考这个新增即可
redisExpireConfig.put("1min", RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.entryTtl(Duration.ofMinutes(1)).disableCachingNullValues());
RedisCacheManager redisCacheManager = RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration)
.withInitialCacheConfigurations(redisExpireConfig)
.transactionAware()
.build();
return redisCacheManager;
}
}
Spring boot 1.x 的 redis 配置和 Spring boot 2.x 的 redis 配置有很大差异,次要是 2.x 应用了 lettuce 客户端,所以网上看到的一些 1.x 的参考代码在 2.x 无奈应用
- 一个简略的示例
@RestController
@RequestMapping(value = "/user")
public class UserController {@GetMapping(value = "/info")
@Cacheable(value = "user", key = "#uid")
public User getUser(@RequestParam(value = "uid") String uid) {System.out.println("getUser====>" + uid);
User user = new User();
user.setUid(uid);
user.setEmail(uid + "@definesys.com");
user.setName(uid + ":" + System.currentTimeMillis());
return user;
}
}
@Cacheable(value = "user", key = "#uid")
注解将开启缓存,接口返回的数据将会被缓存,value
是缓存的名称,key
是缓存的健,能够应用 SpEL 表达式。
用 curl 调用接口
➜ curl http://localhost:8089/user/info\?uid\=jianfeng
{"uid":"jianfeng","name":"jianfeng:1614870102913","email":"jianfeng@definesys.com"}%
用 redis-cli
登录 redis 查看
➜ skywalking git:(master) ✗ docker exec -it redis redis-cli
127.0.0.1:6379> keys *
1) "user::jianfeng"
127.0.0.1:6379> get user::jianfeng
{
"@class": "com.poc.redis.User",
"uid": "jianfeng",
"name": "jianfeng:1614870102913",
"email": "jianfeng@definesys.com"
}
127.0.0.1:6379> ttl user::jianfeng
(integer) -1
能够看到,redis 创立了一个名称为 user::jianfeng
的键,值为 java 对象的 JSON 字符串,并且减少了一个 @class
的字段示意序列化的类,该缓存过期工夫为 - 1 也就是永不过期。这时候再用 curl 测试会发现后果还是一样的
➜ curl http://localhost:8089/user/info\?uid\=jianfeng
{"uid":"jianfeng","name":"jianfeng:1614870102913","email":"jianfeng@definesys.com"}%
如果没有缓存,因为咱们 name 字段的代码是 user.setName(uid + ":" + System.currentTimeMillis());
所以实践上每次调用都应该不一样,因为有了缓存所以办法逻辑不会被执行,间接从缓存中取出数据。
缓存过期工夫
咱们在缓存配置类外面设置了一个 1min
的配置
redisExpireConfig.put("1min", RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
咱们批改下代码
@Cacheable(value = "1min", key = "#uid")
public User getUser(@RequestParam(value = "uid") String uid) {...}
调用接口后查看 redis 缓存数据
➜ docker exec -it redis redis-cli
127.0.0.1:6379> keys *
1) "1min::jianfeng"
127.0.0.1:6379> ttl 1min::jianfeng
(integer) 45
这时候你一直的执行 ttl 1min::jianfeng
命令会发现工夫在缩小,当缩小到 0 时,redis 就会革除掉缓存
Cacheable 能够指定多个名称
@Cacheable(value = {"1min", "2min"}, key = "#uid")
这样只有其中任何一个缓存无效都能失去数据
缓存相干注解
除了 Cacheable 还有其余跟缓存相干的注解
- CachePut
CachePut
能够将数据放入缓存,个别 insert 操作和 update 操作能够应用该注解,如果指定的 key 数据存在就更新数据
- CacheEvict
CacheEvict
能够删除缓存数据,个别 delete 操作的接口能够应用该注解
- Caching
Caching
是三个的汇合,定义如下
public @interface Caching {Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};}
一个残缺的增删改查缓存例子
@RestController
@RequestMapping("user")
public class RedisController {
@Autowired
private UserMapper userMapper;
@PostMapping("/add")
@CachePut(value = "neverExpire", key = "#user.uid")
public User add(@RequestBody User user) {userMapper.insert(user);
return user;
}
@PostMapping("/update")
@CachePut(value = "neverExpire", key = "#user.uid")
public User update(@RequestBody User user) {return user;}
@GetMapping("/delete")
@CacheEvict(value = "neverExpire", key = "#uid")
public String delete(@RequestParam(value = "uid") String uid) {return uid;}
@GetMapping("/detail")
@Cacheable(value = "neverExpire", key = "#result")
public User deteail(@RequestParam(value = "uid") String uid) {QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("uid", uid);
return userMapper.selectOne(queryWrapper);
}
}