Redis 是目前業界使用最普遍的內存數據存儲。相比 Memcached,Redis 支持更豐富的數據結構,例如 hashes, lists, sets 等,同時支持數據持久化。除此以外,Redis 還提供一些類數據庫的特性,好比事務,HA,主從庫。能夠說 Redis 兼具了緩存系統和數據庫的一些特性,所以有着豐富的應用場景。本文介紹 Redis 在 Spring Boot 中兩個典型的應用場景。java
<!-- redis 緩存 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- session 緩存 --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!-- lettuce pool 緩存鏈接池 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
Spring Boot 提供了對 Redis 集成的組件包:spring-boot-starter-data-redis,spring-boot-starter-data-redis依賴於spring-data-redis 和 lettucegit
Lettuce 是一個可伸縮線程安全的 Redis 客戶端,多個線程能夠共享同一個 RedisConnection,它利用優秀 netty NIO 框架來高效地管理多個鏈接。github
spring: redis: host: 127.0.0.1 port: 6379 password: lettuce: pool: # 鏈接池最大鏈接數(使用負值表示沒有限制) max-active: 8 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) max-wait: 1000 # 鏈接池中的最大空閒鏈接 max-idle: 8 # 鏈接池中的最小空閒鏈接 min-idle: 0 # 關閉超時時間 shutdown-timeout: 100
@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { /** * redisTemplate 序列化使用的jdkSerializeable, 存儲二進制字節碼, 因此自定義序列化類,方便調試redis * * @param redisConnectionFactory * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); //使用StringRedisSerializer來序列化和反序列化redis的ke redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); //開啓事務 redisTemplate.setEnableTransactionSupport(true); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } /** * 自定義生成key的策略 * * @return */ @Bean @Override public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { return target.getClass().getSimpleName() + "_" + method.getName() + "_" + StringUtils.arrayToDelimitedString(params, "_"); } }; } }
當不指定緩存的key時,SpringBoot會使用SimpleKeyGenerator生成keyredis
問題:
若是2個方法,參數是同樣的,但執行邏輯不一樣,那麼將會致使執行第二個方法時命中第一個方法的緩存。
解決辦法
是在@Cacheable註解參數中指定key,或者本身實現一個KeyGenerator,在註解中指定KeyGenerator。spring
可是若是這樣的狀況不少,每個都要指定key、KeyGenerator很麻煩。Spring一樣提供了方案:繼承CachingConfigurerSupport並重寫keyGenerator()數據庫
@RunWith(SpringRunner.class) @SpringBootTest @Slf4j public class TestRedis1 { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private RedisTemplate redisTemplate; @Test public void test() throws Exception { stringRedisTemplate.opsForValue().set("aaa", "111"); log.info(String.format("aaa值是:%s", stringRedisTemplate.opsForValue().get("aaa"))); Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa")); } @Test public void testObj() throws Exception { User user = new User("aa@126.com", "aa", "aa123456", "aa", "123"); ValueOperations<String, User> operations = redisTemplate.opsForValue(); operations.set("easy.demo", user); User userRedis = (User) redisTemplate.opsForValue().get("easy.demo"); log.info(String.format("easy.demo值是:%s", userRedis.toString())); } }
分佈式系統中,Session 共享有不少的解決方案,其中託管到緩存中應該是最經常使用的方案之一。apache
Spring Session 提供了一套建立和管理 Servlet HttpSession 的方案。Spring Session 提供了集羣 Session(Clustered Sessions)功能,默認採用外置的 Redis 來存儲 Session 數據,以此來解決 Session 共享的問題。緩存
@Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400 * 30) public class SessionConfig { }
maxInactiveIntervalInSeconds: 設置 Session 失效時間,使用 Redis Session 以後,原 Spring Boot 的 server.session.timeout 屬性再也不生效。安全
@RequestMapping("/uid") public String uid(HttpSession session) { UUID uid = (UUID) session.getAttribute("uid"); if (uid == null) { uid = UUID.randomUUID(); } session.setAttribute("uid", uid); return session.getId(); }
調用以上方法後,打開redis查看,會發現已經把session存入redis了session