3月
05
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); } }
Address: https://zhengjianfeng.cn/?p=520
no comment untill now