Spring Boot Redis缓存

时间:2020-02-23 14:35:49  来源:igfitidea点击:

Spring Boot Redis缓存

在本文中,我们将设置一个示例Spring引导应用程序并将其与Redis Cache集成。
虽然Redis是一个开源的内存中数据结构存储,用作数据库,缓存和消息代理,但本课将仅演示缓存集成。

我们将使用Spring Initializr工具快速设置项目。

Spring Boot Redis项目设置

我们将使用Spring Initializr工具快速设置项目。
我们将使用3个依赖项,如下所示:下载项目并解压缩。
我们使用了H2数据库依赖性,因为我们将使用嵌入式数据库,一旦应用程序停止,该数据库将丢失所有数据。

Spring Boot Redis缓存Maven依赖关系

尽管我们已经使用该工具完成了设置,但是如果您想手动设置,我们将使用Maven构建系统用于该项目,这是我们使用的依赖项:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

<!-- for JPA support -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- for embedded database support -->
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>runtime</scope>
</dependency>

</dependencies>

<build>
<plugins>
   <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
</plugins>
</build>

确保从Maven Central使用稳定版本的Spring Boot。

定义模型

要将对象保存到Redis数据库中,我们定义一个具有基本字段的Person模型对象:

package com.theitroad.rediscachedemo;

import javax.persistence.*;
import java.io.Serializable;

@Entity
public class User implements Serializable {

  private static final long serialVersionUID = 7156526077883281623L;

  @Id
  @SequenceGenerator(name = "SEQ_GEN", sequenceName = "SEQ_USER", allocationSize = 1)
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
  private Long id;
  private String name;
  private long followers;

  public User() {
  }

  public User(String name, long followers) {
      this.name = name;
      this.followers = followers;
  }

  //standard getters and setters

  @Override
  public String toString() {
      return String.format("User{id=%d, name='%s', followers=%d}", id, name, followers);
  }
}

这是带有getter和setter的标准POJO。

配置Redis缓存

有了Spring Boot并已在Maven中使用了必需的依赖关系,我们可以在application.properties文件中仅用三行配置本地Redis实例:

# Redis Config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379

另外,在Spring Boot主类上使用@EnableCaching批说明:

package com.theitroad.rediscachedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Application implements CommandLineRunner {

private final Logger LOG = LoggerFactory.getLogger(getClass());
private final UserRepository userRepository;

@Autowired
public Application(UserRepository userRepository) {
  this.userRepository = userRepository;
}

public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
}

@Override
public void run(String... strings) {
  //Populating embedded database here
  LOG.info("Saving users. Current user count is {}.", userRepository.count());
  User shubham = new User("Shubham", 2000);
  User hyman = new User("hyman", 29000);
  User lewis = new User("Lewis", 550);

  userRepository.save(shubham);
  userRepository.save(hyman);
  userRepository.save(lewis);
  LOG.info("Done saving users. Data: {}.", userRepository.findAll());
}
}

我们想添加一些CommandLineRunner来填充嵌入式H2数据库中的一些示例数据。

定义存储库

在展示Redis的工作原理之前,我们将为JPA相关功能定义一个存储库:

package com.theitroad.rediscachedemo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository { }

到目前为止,它没有方法调用,因为我们不需要任何方法调用。

定义控制器

控制器是调用Redis缓存进行操作的地方。
实际上,这是最好的选择,因为与缓存直接相关联,因此请求甚至不必输入服务代码即可等待缓存的结果。

这是控制器框架:

package com.theitroad.rediscachedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {

private final Logger LOG = LoggerFactory.getLogger(getClass());

private final UserRepository userRepository;

@Autowired
public UserController(UserRepository userRepository) {
  this.userRepository = userRepository;
}
 ...
}

现在,将某些东西放入缓存中,我们使用@Cacheable注解:

@Cacheable(value = "users", key = "#userId", unless = "#result.followers < 12000")
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
LOG.info("Getting user with ID {}.", userId);
return userRepository.findOne(Long.valueOf(userId));
}

在上面的映射中,getUser方法会将人员放入名为"用户"的缓存中,通过键将其标识为" userId",并且仅存储关注者大于12000的用户。
这确保了缓存为填充了非常受欢迎且经常被查询的用户。

另外,我们有意在API调用中添加了一条log语句。
现在,让我们通过Postman进行一些API调用。
这些是我们拨打的电话:

localhost:8090/1
localhost:8090/1
localhost:8090/2
localhost:8090/2

如果我们注意到日志,将是:

... : Getting user with ID 1.
... : Getting user with ID 1.
... : Getting user with ID 2.

有事吗我们进行了四个API调用,但仅存在三个日志语句。
这是因为ID为2的用户拥有29000个关注者,因此其数据已缓存。
这意味着,当对其进行API调用时,数据是从缓存中返回的,因此没有进行DB调用!

更新缓存

每当更新其实际对象值时,缓存值也应更新。
这可以使用@CachePut批注完成:

@CachePut(value = "users", key = "#user.id")
@PutMapping("/update")
public User updatePersonByID(@RequestBody User user) {
userRepository.save(user);
return user;
}

这样,一个人再次通过其ID进行标识,并使用结果进行更新。

清除缓存

如果要从实际的数据库中删除一些数据,就没有必要再将其保留在缓存中了。
我们可以使用@CacheEvict注释来清除缓存数据:

@CacheEvict(value = "users", allEntries=true)
@DeleteMapping("/{id}")
public void deleteUserByID(@PathVariable Long id) {
LOG.info("deleting person with id {}", id);
userRepository.delete(id);
}

在上一个映射中,我们只是逐出了缓存条目,而没有执行其他操作。

运行Spring Boot Redis缓存应用程序

我们只需使用一个命令即可运行此应用程序:

mvn spring-boot:run

Redis缓存限制

尽管Redis的速度非常快,但是在64位系统上存储任何数量的数据仍然没有限制。
它只能在32位系统上存储3GB数据。
更多的可用内存可以导致更高的命中率,但是一旦Redis占用了过多的内存,这种情况将趋于停止。
当高速缓存大小达到内存限制时,旧数据将被删除以放置新数据。