Spring Boot——缓存支持2(Redis)

来源:互联网 发布:大数据采集软件 编辑:程序博客网 时间:2024/05/16 10:53

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=localhostspring.redis.port=6379spring.redis.pool.max-idle=8spring.redis.pool.min-idle=0spring.redis.pool.max-active=8spring.redis.pool.max-wait=-1spring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.jpa.hibernate.ddl-auto=createspring.jpa.show-sql=true
redis的port根据自己的进行修改。

新建User类:

@Entitypublic 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> {@CacheableUser findByName(String name);    User save(User user);}
这里我们的findByName方法标记上缓存,@Cacheable的key属性缺省,所以默认使用参数name作为key。

在main主类中添加@EnableCaching注解。

@EnableCaching@SpringBootApplicationpublic class SpringcloudRedis2Application {public static void main(String[] args) {SpringApplication.run(SpringcloudRedis2Application.class, args);}}
最后编写测试类:

public class SpringcloudRedis2ApplicationTests {@Autowiredprivate UserRepository userRepository;@Beforepublic void before() {userRepository.save(new User("张三", 10));}@Testpublic 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
缓存成功了。

如果我们在其中进行修改会怎么样呢?

@Testpublic 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第二次查询:10Hibernate: 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第二次查询:10Hibernate: 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缓存中的数据,否则会出现数据不一致的情况。

1 0