能夠下載案例Chapter4-4-1,進行下面改造步驟。html
先來回顧一下在此案例中,咱們作了什麼內容:git
spring-data-jpa
和EhCache
User
實體,包含id
、name
、age
字段spring-data-jpa
實現了對User
對象的數據訪問接口UserRepository
Cache
相關注解配置了緩存刪除EhCache的配置文件src/main/resources/ehcache.xml
redis
pom.xml
中刪除EhCache的依賴,增長redis的依賴:spring
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency>
application.properties
中增長redis配置,以本地運行爲例,好比: spring.redis.host=localhost spring.redis.port=6379 spring.redis.pool.max-idle=8 spring.redis.pool.min-idle=0 spring.redis.pool.max-active=8 spring.redis.pool.max-wait=-1
咱們須要作的配置到這裏就已經完成了,Spring Boot會在偵測到存在Redis的依賴而且Redis的配置是可用的狀況下,使用RedisCacheManager
初始化CacheManager
。數據庫
爲此,咱們能夠單步運行咱們的單元測試,能夠觀察到此時CacheManager
的實例是org.springframework.data.redis.cache.RedisCacheManager
,並得到下面的執行結果:緩存
Hibernate: insert into user (age, name) values (?, ?) Hibernate: select user0_.id as id1_0_, user0_.age as age2_0_, user0_.name as name3_0_ from user user0_ where user0_.name=? 第一次查詢:10 第二次查詢:10 Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=? Hibernate: update user set age=?, name=? where id=? 第三次查詢:10
能夠觀察到,在第一次查詢的時候,執行了select語句;第二次查詢沒有執行select語句,說明是從緩存中得到告終果;而第三次查詢,咱們得到了一個錯誤的結果,根據咱們的測試邏輯,在查詢以前咱們已經將age更新爲20,可是咱們從緩存中獲取到的age仍是爲10。app
爲何一樣的邏輯在EhCache中沒有問題,可是到Redis中會出現這個問題呢?框架
在EhCache緩存時沒有問題,主要是因爲EhCache是進程內的緩存框架,第一次經過select查詢出的結果被加入到EhCache緩存中,第二次查詢從EhCache取出的對象與第一次查詢對象其實是同一個對象(能夠在使用Chapter4-4-1工程中,觀察u1==u2來看看是不是同一個對象),所以咱們在更新age的時候,實際已經更新了EhCache中的緩存對象。spring-boot
而Redis的緩存獨立存在於咱們的Spring應用以外,咱們對數據庫中數據作了更新操做以後,沒有通知Redis去更新相應的內容,所以咱們取到了緩存中未修改的數據,致使了數據庫與緩存中數據的不一致。單元測試
所以咱們在使用緩存的時候,要注意緩存的生命週期,利用好上一篇上提到的幾個註解來作好緩存的更新、刪除
針對上面的問題,咱們只須要在更新age的時候,經過@CachePut
來讓數據更新操做同步到緩存中,就像下面這樣:
@CacheConfig(cacheNames = "users") public interface UserRepository extends JpaRepository<User, Long> { @Cacheable(key = "#p0") User findByName(String name); @CachePut(key = "#p0.name") User save(User user); }
在redis-cli中flushdb,清空一下以前的緩存內容,再執行單元測試,能夠得到下面的結果:
Hibernate: insert into user (age, name) values (?, ?) 第一次查詢:10 第二次查詢:10 Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=? Hibernate: update user set age=?, name=? where id=? 第三次查詢:20
能夠看到,咱們的第三次查詢得到了正確的結果!同時,咱們的第一次查詢也不是經過select查詢得到的,由於在初始化數據的時候,調用save方法時,就已經將這條數據加入了redis緩存中,所以後續的查詢就直接從redis中獲取了。
本文內容到此爲止,主要介紹了爲何要使用Redis作緩存,以及如何在Spring Boot中使用Redis作緩存,而且經過一個小問題來幫助你們理解緩存機制,在使用過程當中,必定要注意緩存生命週期的控制,防止數據不一致的狀況出現。