スプリングブートのRedisキャッシュ
春に使用されるRedis CacheのSpring Boot
Spring Boot Redisプロジェクトのセットアップ
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>
マベンセントラルからSpring Bootの安定版を使用するようにしてください。
モデルの定義を明確にする。
Redisデータベースにオブジェクトを保存するために、基本的なフィールドを持つPersonモデルオブジェクトを定義します。
package com.scdev.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);
}
}
ゲッターとセッターを持つ標準的なPOJOです。
Redisキャッシュの設定
Spring BootとMavenで必要な依存関係がすでに設定されている場合、application.propertiesファイルでわずか3行でローカルのRedisインスタンスを設定することができます。
# Redis Config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
また、Spring Bootのメインクラスに@EnableCachingアノテーションを使用してください。
package com.scdev.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 scdev = new User("Pankaj", 29000);
User lewis = new User("Lewis", 550);
userRepository.save(shubham);
userRepository.save(scdev);
userRepository.save(lewis);
LOG.info("Done saving users. Data: {}.", userRepository.findAll());
}
}
私たちは、埋め込みH2データベースにいくつかのサンプルデータを追加したいため、CommandLineRunnerを追加しました。
リポジトリを定義する
Redisの動作を説明する前に、JPA関連の機能に関するリポジトリを定義します。
package com.scdev.rediscachedemo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository { }
今のところ、必要性がないので、メソッドの呼び出しはありません。
コントローラの定義
コントローラーはRedisキャッシュを呼び出す場所です。実際には、キャッシュが直接関連付けられているため、リクエストはサービスコードに入ることなく、キャッシュの結果を待つ必要もありません。以下はコントローラーのスケルトンです。
package com.scdev.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.
気づきましたか?私たちは4回のAPI呼び出しを行いましたが、ログのステートメントは3つしかありませんでした。これは、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は非常に速いですが、64ビットシステムではデータの保存量に制限がありません。32ビットシステムでは、データの保存量は最大3GBまでです。より利用可能なメモリは、ヒットの割合を向上させる可能性がありますが、Redisが占有するメモリがあまりにも多い場合は停止する傾向があります。キャッシュサイズがメモリ制限に達すると、古いデータは新しいデータのために削除されます。
要約
このレッスンでは、Redis Cacheが高速なデータのやり取りを可能にするパワーと、最小限でありながら強力な設定でSpring Bootとどのように統合できるかを学びました。ご意見はお気軽に下にコメントを残してください。
Spring Boot Redis Cache プロジェクトをダウンロードしてください。