能够下载案例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作缓存,而且经过一个小问题来帮助你们理解缓存机制,在使用过程当中,必定要注意缓存生命周期的控制,防止数据不一致的状况出现。