Spring Boot Redis 缓存
Spring Boot Redis 缓存
在本文中,我们将设置一个示例 Spring Boot 应用程序并将其与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.journaldev.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
另外,@EnableCaching
在 Spring Boot 主类上使用注释:
package com.journaldev.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 pankaj = new User("Pankaj", 29000);
User lewis = new User("Lewis", 550);
userRepository.save(shubham);
userRepository.save(pankaj);
userRepository.save(lewis);
LOG.info("Done saving users. Data: {}.", userRepository.findAll());
}
}
我们添加了一个 CommandLineRunner,因为我们想要在嵌入式 H2 数据库中填充一些示例数据。
定义存储库
在展示 Redis 如何工作之前,我们将定义一个用于 JPA 相关功能的存储库:
package com.journaldev.rediscachedemo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository { }
到目前为止它还没有方法调用,因为我们不需要任何方法调用。
定义控制器
控制器是调用 Redis 缓存执行操作的地方。实际上,这是执行此操作的最佳位置,因为缓存直接与其关联,请求甚至不必进入服务代码来等待缓存结果。以下是控制器骨架:
package com.journaldev.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 调用中添加了一条日志语句。现在让我们从 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;
}
这样,就可以再次通过身份识别一个人,并更新结果。
清除缓存
如果要从实际数据库中删除某些数据,则没有必要再将其保留在缓存中。我们可以使用@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 占用了太多内存,这种情况就会停止。当缓存大小达到内存限制时,旧数据将被删除以腾出空间放置新数据。
概括
在本课中,我们了解了 Redis Cache 为我们提供快速数据交互的功能,以及如何以最少但功能强大的配置将其与 Spring Boot 集成。欢迎在下面发表评论。
下载 Spring Boot Redis 缓存项目