Spring Boot——缓存支持2(Redis)
2017-04-18 00:22
549 查看
EhCache能够适用很多应用场景,但是由于EhCache是进程内的缓存框架,在集群模式下时,各应用服务器之间的缓存都是独立的,因此在不同服务器的进程间会存在缓存不一致的情况。即使EhCache提供了集群环境下的缓存同步策略,但是同步依然需要一定的时间,短暂的缓存不一致依然存在。
在高一致性数据库中,使用redis作为缓存数据库是一个不错的选择。
EhCache和Redis的区别:
Redis:属于独立的运行程序,需要单独安装后,使用JAVA中的Jedis来操纵。因为它是独立,所以如果你写个单元测试程序,放一些数据在Redis中,然后又写一个程序去拿数据,那么是可以拿到这个数据的。,
EhCache:与Redis明显不同,它与java程序是绑在一起的,java程序活着,它就活着。譬如,写一个独立程序放数据,再写一个独立程序拿数据,那么是拿不到数据的。只能在独立程序中才能拿到数据。
这篇讨论一下redis数据库的简单使用,redis数据库的集群将放到后面再讨论。
首先当然是安装redis了。如何安装这里就不赘述了。
运行得到以下界面redis就安装成功了。
最好将redis配置成一个服务,如果不配置成服务的话,手动运行也是可以的。
然后我们创建一个新的项目:
首先增加依赖关系:
<!-- spring data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>jpa和mysql是数据库需要的。
在application.properties中增加如下配置:
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.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=trueredis的port根据自己的进行修改。
新建User类:
@Entity
public class User implements Serializable {
private static final long serialVersionUID = -8566566269336931609L;
@Id
@GeneratedValue
private int id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer age;
//getter setter
}这里User需要实现可序列化接口,进程之间的交换数据,我们的程序和redis数据库进行数据交换嘛,实现序列化才能进行传输。我们的程序中将User序列化,在reids中反序列化,达到进程通信的目的。
在实现UserRepository继承JpaRepository:
@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Integer> {
@Cacheable
User findByName(String name);
User save(User user);
}这里我们的findByName方法标记上缓存,@Cacheable的key属性缺省,所以默认使用参数name作为key。
在main主类中添加@EnableCaching注解。
@EnableCaching
@SpringBootApplication
public class SpringcloudRedis2Application {
public static void main(String[] args) {
SpringApplication.run(SpringcloudRedis2Application.class, args);
}
}
最后编写测试类:
public class SpringcloudRedis2ApplicationTests {
@Autowired
private UserRepository userRepository;
@Before
public void before() {
userRepository.save(new User("张三", 10));
}
@Test
public void test() throws Exception {
User u1 = userRepository.findByName("张三");
System.out.println("第一次查询:" + u1.getAge());
User u2 = userRepository.findByName("张三");
System.out.println("第二次查询:" + u2.getAge());
}
}结果:
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缓存成功了。
如果我们在其中进行修改会怎么样呢?
@Test
public void test() throws Exception {
User u1 = userRepository.findByName("张三");
System.out.println("第一次查询:" + u1.getAge());
User u2 = userRepository.findByName("张三");
System.out.println("第二次查询:" + u2.getAge());
u1.setAge(999);
userRepository.save(u1);
User u3 = userRepository.findByName("张三");
System.out.println("第二次查询:" + u3.getAge());
}结果如下:
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=?
第二次查询:10为什么要这样呢?我们不是修改了u1的值吗?
原因是这样的:我们对u1进行修改,并且调用save方法。首先对u1修改,修改了内存中的u1的age。调用save方法,执行了sql语句update更新了数据库。但是,我们没有对redis数据库发起修改的申请,也就是缓存并没有被修改,所以我们调用findByName返回的是缓存中的数据,得到未修改的数据。
那么我们如何对redis数据库发起修改呢?
我们仔细想想,由于redis数据库中缓存的是<key,value>键值对,而使用redis缓存的是findByName方法,执行这个方法得到的缓存的key是根据参数得到的,也就是关于name的key。而save方法中标注的@CachePut注解,key属性缺省,使用的是关于User的key。两个key并不相同,所以无法更新。所以我们需要做以下修改:
@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Integer> {
@Cacheable(key="'USER_NAME_'+#p0")
User findByName(String name);
@CachePut(key="'USER_NAME_'+#p0.name")
User save(User user);
}这样,@Cacheable和@CachePut的key就对应起来了,redis就能够正确的更新缓存。结果:
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=?
第二次查询:999
使用Redis数据库,由于不是这个缓存不像ehcache一样,是在程序内存当中的,而是在另外一个程序当中的,修改数据的时候,不单单要更新mysql数据库的数据,而且也要注意更新redis缓存中的数据,否则会出现数据不一致的情况。
在高一致性数据库中,使用redis作为缓存数据库是一个不错的选择。
EhCache和Redis的区别:
Redis:属于独立的运行程序,需要单独安装后,使用JAVA中的Jedis来操纵。因为它是独立,所以如果你写个单元测试程序,放一些数据在Redis中,然后又写一个程序去拿数据,那么是可以拿到这个数据的。,
EhCache:与Redis明显不同,它与java程序是绑在一起的,java程序活着,它就活着。譬如,写一个独立程序放数据,再写一个独立程序拿数据,那么是拿不到数据的。只能在独立程序中才能拿到数据。
这篇讨论一下redis数据库的简单使用,redis数据库的集群将放到后面再讨论。
首先当然是安装redis了。如何安装这里就不赘述了。
运行得到以下界面redis就安装成功了。
最好将redis配置成一个服务,如果不配置成服务的话,手动运行也是可以的。
然后我们创建一个新的项目:
首先增加依赖关系:
<!-- spring data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>jpa和mysql是数据库需要的。
在application.properties中增加如下配置:
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.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=trueredis的port根据自己的进行修改。
新建User类:
@Entity
public class User implements Serializable {
private static final long serialVersionUID = -8566566269336931609L;
@Id
@GeneratedValue
private int id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer age;
//getter setter
}这里User需要实现可序列化接口,进程之间的交换数据,我们的程序和redis数据库进行数据交换嘛,实现序列化才能进行传输。我们的程序中将User序列化,在reids中反序列化,达到进程通信的目的。
在实现UserRepository继承JpaRepository:
@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Integer> {
@Cacheable
User findByName(String name);
User save(User user);
}这里我们的findByName方法标记上缓存,@Cacheable的key属性缺省,所以默认使用参数name作为key。
在main主类中添加@EnableCaching注解。
@EnableCaching
@SpringBootApplication
public class SpringcloudRedis2Application {
public static void main(String[] args) {
SpringApplication.run(SpringcloudRedis2Application.class, args);
}
}
最后编写测试类:
public class SpringcloudRedis2ApplicationTests {
@Autowired
private UserRepository userRepository;
@Before
public void before() {
userRepository.save(new User("张三", 10));
}
@Test
public void test() throws Exception {
User u1 = userRepository.findByName("张三");
System.out.println("第一次查询:" + u1.getAge());
User u2 = userRepository.findByName("张三");
System.out.println("第二次查询:" + u2.getAge());
}
}结果:
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缓存成功了。
如果我们在其中进行修改会怎么样呢?
@Test
public void test() throws Exception {
User u1 = userRepository.findByName("张三");
System.out.println("第一次查询:" + u1.getAge());
User u2 = userRepository.findByName("张三");
System.out.println("第二次查询:" + u2.getAge());
u1.setAge(999);
userRepository.save(u1);
User u3 = userRepository.findByName("张三");
System.out.println("第二次查询:" + u3.getAge());
}结果如下:
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=?
第二次查询:10为什么要这样呢?我们不是修改了u1的值吗?
原因是这样的:我们对u1进行修改,并且调用save方法。首先对u1修改,修改了内存中的u1的age。调用save方法,执行了sql语句update更新了数据库。但是,我们没有对redis数据库发起修改的申请,也就是缓存并没有被修改,所以我们调用findByName返回的是缓存中的数据,得到未修改的数据。
那么我们如何对redis数据库发起修改呢?
我们仔细想想,由于redis数据库中缓存的是<key,value>键值对,而使用redis缓存的是findByName方法,执行这个方法得到的缓存的key是根据参数得到的,也就是关于name的key。而save方法中标注的@CachePut注解,key属性缺省,使用的是关于User的key。两个key并不相同,所以无法更新。所以我们需要做以下修改:
@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Integer> {
@Cacheable(key="'USER_NAME_'+#p0")
User findByName(String name);
@CachePut(key="'USER_NAME_'+#p0.name")
User save(User user);
}这样,@Cacheable和@CachePut的key就对应起来了,redis就能够正确的更新缓存。结果:
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=?
第二次查询:999
使用Redis数据库,由于不是这个缓存不像ehcache一样,是在程序内存当中的,而是在另外一个程序当中的,修改数据的时候,不单单要更新mysql数据库的数据,而且也要注意更新redis缓存中的数据,否则会出现数据不一致的情况。
相关文章推荐
- Spring Boot中的缓存支持(二)使用Redis做集中式缓存
- Spring Boot中的缓存支持(二)使用Redis做集中式缓存
- Spring Boot中的缓存支持(二)使用Redis做集中式缓存
- Spring Boot中的缓存支持(二)使用Redis做集中式缓存
- Spring Boot Cache + redis 设置有效时间和自动刷新缓存,时间支持在配置文件中配置
- (35)Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】
- redis 在spring boot工程中的应用(四) 图片的读取与缓存 byte string
- spring-boot整合redis作为缓存(1)——redis的设置
- Spring Boot 整合 Redis 实现缓存操作
- spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战
- Spring Boot 基于注解的 Redis 缓存使用详解
- (35)Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】
- REDIS学习(3.2)spring boot 使用redis作为缓存
- spring-boot整合redis作为缓存(3)——自定义key
- Spring Boot 整合 Redis 实现缓存操作
- springboot 从redis取缓存的时候java.lang.ClassCastException:异常
- SpringBoot中搭建Redis缓存功能
- Spring客户端对Redis 缓存的使用(Java客户端等Redis3.X RedisCluster模式的支持)
- 35. Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】
- Spring Boot中的缓存支持(一)注解配置与EhCache使用