Spring Boot 8:Redis使用
阿新 • • 發佈:2018-11-25
Redis有兩個模板:RedisTemplate 和 StringRedisTemplate。不推薦使用 RedisTemplate,因為 RedisTemplate 提供的是操作物件,而我們通常以 JSON 格式儲存該物件,儲存時會使用 Redis 預設的內部序列化器,容易導致儲存內容出現亂碼。此時需要我們自定義序列化。
StringRedisTemplate 為我們提供了字串操作,將實體類轉換成 JSON 字串進行儲存,等取出來後,再將其轉換成相應的物件
pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
application.yml
spring redis: # open: false # 是否開啟redis快取 true開啟 false關閉 database: 0 host: 127.0.0.1 port: 6379 password: timeout: 6000 # 連線超時時長(毫秒) pool: max-active: 1000 # 連線池最大連線數(使用負值表示沒有限制) max-wait: -1 # 連線池最大阻塞等待時間(使用負值表示沒有限制) max-idle: 10 # 連線池中的最大空閒連線 min-idle: 5 # 連線池中的最小空閒連線
RedisConfig
使用StringRedisTemplate
可以不重寫keyGenerator
方法
/** * Redis 配置 * * @Author YangXuyue * @Date 2018/08/02 21:57 */ @Configuration @EnableCaching @AutoConfigureAfter(RedisAutoConfiguration.class) public class RedisConfig extendsCachingConfigurerSupport { /* 快取命中率 即從快取中讀取資料的次數 與 總讀取次數的比率,命中率越高越好: 命中率 = 從快取中讀取次數 / (總讀取次數[從快取中讀取次數 + 從慢速裝置上讀取的次數]) Miss率 = 沒有從快取中讀取的次數 / (總讀取次數[從快取中讀取次數 + 從慢速裝置上讀取的次數]) 這是一個非常重要的監控指標,如果做快取一定要健康這個指標來看快取是否工作良好 */ /* 快取策略 Eviction policy 移除策略,即如果快取滿了,從快取中移除資料的策略;常見的有LFU、LRU、FIFO: FIFO(First In First Out):先進先出演算法,即先放入快取的先被移除; LRU(Least Recently Used):最久未使用演算法,使用時間距離現在最久的那個被移除; LFU(Least Frequently Used):最近最少使用演算法,一定時間段內使用次數(頻率)最少的那個被移除; TTL(Time To Live ) 存活期,即從快取中建立時間點開始直到它到期的一個時間段(不管在這個時間段內有沒有訪問都將過期) TTI(Time To Idle) 空閒期,即一個數據多久沒被訪問將從快取中移除的時間 */ /* Spring提供了Cache:org.springframework.cache;該Cache提供了快取操作的讀取/寫入/移除方法 因為應用並不是只有一個Cache,所以Spring提供了CacheManager抽象,用於快取管理 Cache和CacheManager都有其預設實現(GuavaXXX,EhCacheXXX...) GuavaCacheManager之外,其他Cache都支援Spring事務的,即如果事務回滾了,Cache的資料也會移除掉。 */ /* 繼承CachingConfigurerSupport,實現後注入需要的cacheManager和keyGenerator */ // 設定RedisCacheManager。在配置 CacheManager 的方法中,也可以配置快取預設的過期時間。 @Bean public CacheManager cacheManager(RedisTemplate redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); // 設定快取過期時間,單位秒 Map<String, Long> expiresMap = new HashMap<>(); expiresMap.put(CacheNames.MASTER, 600L); expiresMap.put(CacheNames.SECOND, 600L); // 設定超時 cacheManager.setExpires(expiresMap); // TODO 沒有設定的快取預設過期時間 //cacheManager.setDefaultExpiration(60 * 60L); return cacheManager; } @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); 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); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } /** * Redis 設定一些全域性配置,比如配置主鍵的生產策略 KeyGenerator,如不配置會預設使用引數名作為主鍵。 * * @return */ @Override @Bean public KeyGenerator keyGenerator() { return new BaseKeyGenerator(); } /** * Redis主鍵生成策略 */ private class BaseKeyGenerator implements KeyGenerator { @Override public Object generate(Object target, Method method, Object... params) { // 目標Object的名稱+方法名+Params各個元素名稱 StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getSimpleName()); sb.append(".").append(method.getName()); for (Object obj : params) { if (null != obj) { sb.append(obj.toString()); } } return sb.toString(); } } }
註解使用例子
@Service @CacheConfig(cacheNames = {CacheNames.MASTER}) public class UserServiceImpl implements UserService { /* @CacheConfig:主要用於配置該類中會用到的一些共用的快取配置。在這裡@CacheConfig(cacheNames = {CacheNames.MASTER}): 配置了該資料訪問物件中返回的內容將儲存於名為users的快取物件中,我們也可以不使用該註解,直接通過@Cacheable自己配置快取集的名字來定義。 */ @Autowired private UserRepository repository; /* 儲存的值為返回值,註解方面再研究研究。合理使用快取的key,不然會沒有效果 */ /* @CachePut效果與@Cacheable一樣 因為@CachePut是方法執行完才生效,所以當新增一個user的時候,user的id是有值的 這裡只針對user的id做了user的快取,如果findByUsername也做快取,那麼資料將會出現不一致的情況 因為key值不一樣,會更新不到以username為key資訊的快取 */ /* 快取註解詳解 @Cacheable:配置了findByName函式的返回值將被加入快取。同時在查詢時,會先從快取中獲取,若不存在才再發起對資料庫的訪問。該註解主要有下面幾個引數: value、cacheNames:兩個等同的引數(cacheNames為Spring 4新增,作為value的別名), 用於指定快取儲存的集合名。由於Spring 4中新增了@CacheConfig,因此在Spring 3中原本必須有的value屬性,也成為非必需項了 key:快取物件儲存在Map集合中的key值,非必需,預設按照函式的所有引數組合作為key值,若自己配置需使用SpEL表示式,比如:@Cacheable(key = "#p0"): 使用函式第一個引數作為快取的key值,更多關於SpEL表示式的詳細內容可參考官方文件 condition:快取物件的條件,非必需,也需使用SpEL表示式,只有滿足表示式條件的內容才會被快取, 比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有當第一個引數的長度小於3的時候才會被快取, 若做此配置上面的AAA使用者就不會被快取,讀者可自行實驗嘗試。 unless:另外一個快取條件引數,非必需,需使用SpEL表示式。它不同於condition引數的地方在於它的判斷時機, 該條件是在函式被呼叫之後才做判斷的,所以它可以通過對result進行判斷。 keyGenerator:用於指定key生成器,非必需。若需要指定一個自定義的key生成器, 我們需要去實現org.springframework.cache.interceptor.KeyGenerator介面,並使用該引數來指定。需要注意的是:該引數與key是互斥的 cacheManager:用於指定使用哪個快取管理器,非必需。只有當有多個時才需要使用 cacheResolver:用於指定使用那個快取解析器,非必需。需通過org.springframework.cache.interceptor.CacheResolver介面來實現自己的快取解析器,並用該引數指定。 @CachePut:配置於函式上,能夠根據引數定義條件來進行快取,它與@Cacheable不同的是,它每次都會真是呼叫函式,所以主要用於資料新增和修改操作上。 它的引數與@Cacheable類似,具體功能可參考上面對@Cacheable引數的解析 @CacheEvict:配置於函式上,通常用在刪除方法上,用來從快取中移除相應資料。除了同@Cacheable一樣的引數之外,它還有下面兩個引數: allEntries:非必需,預設為false。當為true時,會移除所有資料 beforeInvocation:非必需,預設為false,會在呼叫方法之後移除資料。當為true時,會在呼叫方法之前移除資料。 */ @Override @Transactional(rollbackFor = Exception.class) @CachePut(key = "'UserService_UserId_'+#user.id") public User save(User user) { return repository.save(user); } @Override @Cacheable(key = "'UserService_UserId_'+#id") public User findById(Long id) { return repository.findById(id); } @Override @Transactional(rollbackFor = Exception.class) @CacheEvict(key = "'UserService_UserId_'+#id") public void deleteById(Long id) { repository.delete(id); } }
public interface CacheNames { /** * 主快取名稱 */ String MASTER = "master"; String SECOND = "second"; }