SpringDataRedisReactiveの概要
1. 序章
このチュートリアルでは、
ReactiveRedisTemplate の基本的な使用法(Redisでオブジェクトを保存および取得する方法など)について説明します。 そして、ReactiveRedisConnectionを使用してRedisコマンドを実行する方法を見ていきます。
基本をカバーするために、 SpringDataRedisの紹介をチェックしてください。
2. 設定
コードでReactiveRedisTemplateを使用するには、まず、Spring BootのRedisReactiveモジュールの依存関係を追加する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
3. 構成
次に、、Redisサーバーとの接続を確立する必要があります。 localhost:6379 のRedisサーバーに接続する場合は、構成用のコードを追加する必要はありません。
ただし、サーバーがリモートであるか、別のポートにある場合は、LettuceConnectionFactoryコンストラクターでホスト名とポートを指定できます:
@Bean
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
4. リスト操作
Redisリストは、挿入順序でソートされた文字列のリストです。 要素を左または右からプッシュまたはポップすることで、リストに要素を追加またはリストから削除できます。
4.1. 文字列テンプレート
リストを操作するには、ReactiveStringRedisTemplateのインスタンスを使用してRedisListOperationsへの参照を取得する必要があります。
@Autowired
private ReactiveStringRedisTemplate redisTemplate;
private ReactiveListOperations<String, String> reactiveListOps;
@Before
public void setup() {
reactiveListOps = redisTemplate.opsForList();
}
4.2. LPUSHとLPOP
ReactiveListOperationsのインスタンスができたので、リストの識別子としてdemo_listを使用してリストに対してLPUSH操作を実行してみましょう。
その後、リストでLPOPを実行し、ポップされた要素を確認します。
@Test
public void givenListAndValues_whenLeftPushAndLeftPop_thenLeftPushAndLeftPop() {
Mono<Long> lPush = reactiveListOps.leftPushAll(LIST_NAME, "first", "second")
.log("Pushed");
StepVerifier.create(lPush)
.expectNext(2L)
.verifyComplete();
Mono<String> lPop = reactiveListOps.leftPop(LIST_NAME)
.log("Popped");
StepVerifier.create(lPop)
.expectNext("second")
.verifyComplete();
}
リアクティブコンポーネントをテストする場合、 StepVerifier を使用して、タスクの完了をブロックできることに注意してください。
5. バリューオペレーション
文字列だけでなく、カスタムオブジェクトも使用したい場合があります。
それでは、POJOでの操作を示すために、Employeeオブジェクトで同様の操作をいくつか実行してみましょう。
public class Employee implements Serializable {
private String id;
private String name;
private String department;
// ... getters and setters
// ... hashCode and equals
}
5.1. 従業員テンプレート
次の2番目のインスタンスを作成する必要があります
@Bean
public ReactiveRedisTemplate<String, Employee> reactiveRedisTemplate(
ReactiveRedisConnectionFactory factory) {
StringRedisSerializer keySerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Employee> valueSerializer =
new Jackson2JsonRedisSerializer<>(Employee.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, Employee> builder =
RedisSerializationContext.newSerializationContext(keySerializer);
RedisSerializationContext<String, Employee> context =
builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
カスタムオブジェクトを正しくシリアル化するには、Springにその方法を指示する必要があります。 ここでは、値の Jackson2JsonRedisSerializer を構成して、Jacksonライブラリを使用するようにテンプレートに指示しました。 キーは単なる文字列なので、StringRedisSerializerを使用できます。
次に、このシリアル化コンテキストと接続ファクトリを使用して、前と同じようにテンプレートを作成します。
次に、 ReactiveListOperations で以前に行ったのと同じように、ReactiveValueOperationsのインスタンスを作成します。
@Autowired
private ReactiveRedisTemplate<String, Employee> redisTemplate;
private ReactiveValueOperations<String, Employee> reactiveValueOps;
@Before
public void setup() {
reactiveValueOps = redisTemplate.opsForValue();
}
5.2. 保存および取得操作
ReactiveValueOperationsのインスタンスができたので、それを使用してEmployeeのインスタンスを格納しましょう。
@Test
public void givenEmployee_whenSet_thenSet() {
Mono<Boolean> result = reactiveValueOps.set("123",
new Employee("123", "Bill", "Accounts"));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
}
そして、Redisから同じオブジェクトを取り戻すことができます。
@Test
public void givenEmployeeId_whenGet_thenReturnsEmployee() {
Mono<Employee> fetchedEmployee = reactiveValueOps.get("123");
StepVerifier.create(fetchedEmployee)
.expectNext(new Employee("123", "Bill", "Accounts"))
.verifyComplete();
}
5.3. 有効期限のある操作
多くの場合、値をキャッシュに入れて、自然に期限切れになるようにします。これは、同じset操作で実行できます。
@Test
public void givenEmployee_whenSetWithExpiry_thenSetsWithExpiryTime()
throws InterruptedException {
Mono<Boolean> result = reactiveValueOps.set("129",
new Employee("129", "John", "Programming"),
Duration.ofSeconds(1));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
Thread.sleep(2000L);
Mono<Employee> fetchedEmployee = reactiveValueOps.get("129");
StepVerifier.create(fetchedEmployee)
.expectNextCount(0L)
.verifyComplete();
}
このテストは、キャッシュキーの有効期限が切れるのを待つために、独自のブロッキングを行うことに注意してください。
6. Redisコマンド
Redisコマンドは基本的に、Redisクライアントがサーバー上で呼び出すことができるメソッドです。 また、Redisは数十のコマンドをサポートしており、LPUSHやLPOPなど、すでにいくつかのコマンドを確認しています。
Operations APIは、Redisの一連のコマンドに関する高レベルの抽象化です。
ただし、 Redisコマンドプリミティブをより直接的に使用したい場合は、Spring DataRedisReactiveもコマンドAPIを提供します。
それでは、コマンドAPIのレンズを通して文字列コマンドとキーコマンドを見てみましょう。
6.1. 文字列とキーコマンド
Redisコマンド操作を実行するために、ReactionKeyCommandsおよびReactiveStringCommandsのインスタンスを取得します。
両方をReactiveRedisConnectionFactoryインスタンスから取得できます。
@Bean
public ReactiveKeyCommands keyCommands(ReactiveRedisConnectionFactory
reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection().keyCommands();
}
@Bean
public ReactiveStringCommands stringCommands(ReactiveRedisConnectionFactory
reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection().stringCommands();
}
6.2. 操作の設定と取得
ReactiveStringCommands を使用して、1回の呼び出しで複数のキーを格納できます。基本的にSETコマンドを複数回呼び出します。
次に、 ReactiveKeyCommands 、 KEYSコマンドを呼び出して、これらのキーを取得できます。
@Test
public void givenFluxOfKeys_whenPerformOperations_thenPerformOperations() {
Flux<SetCommand> keys = Flux.just("key1", "key2", "key3", "key4");
.map(String::getBytes)
.map(ByteBuffer::wrap)
.map(key -> SetCommand.set(key).value(key));
StepVerifier.create(stringCommands.set(keys))
.expectNextCount(4L)
.verifyComplete();
Mono<Long> keyCount = keyCommands.keys(ByteBuffer.wrap("key*".getBytes()))
.flatMapMany(Flux::fromIterable)
.count();
StepVerifier.create(keyCount)
.expectNext(4L)
.verifyComplete();
}
前述のように、このAPIははるかに低レベルであることに注意してください。 たとえば、は、高レベルのオブジェクトを処理する代わりに、ByteBufferを使用してバイトのストリームを送信しています。 また、SETやSCANなどのRedisプリミティブをより多く使用しています。
最後に、文字列コマンドとキーコマンドは、SpringDataRedisがリアクティブに公開する多くのコマンドインターフェイスの2つにすぎません。
7. 結論
このチュートリアルでは、Spring DataのReactive Redisテンプレートの使用の基本と、それをアプリケーションと統合するためのさまざまな方法について説明しました。
例の完全なソースコードは、GitHubでから入手できます。