The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Redisクライアントの使用

このガイドでは、QuarkusアプリケーションがRedisクライアントエクステンションを使用してRedisサーバーに接続する方法を説明します。

この技術は、previewと考えられています。

preview では、下位互換性やエコシステムでの存在は保証されていません。具体的な改善には設定や API の変更が必要になるかもしれませんが、 stable になるための計画は現在進行中です。フィードバックは メーリングリストGitHub の課題管理 で受け付けています。

とりうるステータスの完全なリストについては、 FAQの項目 を参照してください。

前提条件

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 17+がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.9.6

  • 使用したい場合は、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

  • Dockerが稼働している環境

アーキテクチャ

このガイドでは、 INCRBY コマンドを使用して、数値をインクリメントするシンプルな Rest API を公開します。また、 GETSET(文字列グループ)DELKEYS(キーグループ) のような他の Redis コマンドの使い方も見ていきましょう。

Quarkus Redisエクステンションを使用して、Redisと対話型で接続しましょう。

ソリューション

次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。

Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.gitアーカイブ をダウンロードします。

ソリューションは redis-quickstart ディレクトリ にあります。

Mavenプロジェクトの作成

まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します:

コマンドラインインタフェース
quarkus create app org.acme:redis-quickstart \
    --extension='redis-client,rest-jackson' \
    --no-code
cd redis-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストールと使用方法の詳細については、 Quarkus CLI ガイドを参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.9.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=redis-quickstart \
    -Dextensions='redis-client,rest-jackson' \
    -DnoCode
cd redis-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=redis-quickstart"

このコマンドは、Redisエクステンションをインポートして新しいプロジェクトを生成します。

すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、プロジェクトに redis-client エクステンションを追加することができます。

コマンドラインインタフェース
quarkus extension add redis-client
Maven
./mvnw quarkus:add-extension -Dextensions='redis-client'
Gradle
./gradlew addExtension --extensions='redis-client'

これにより、ビルドファイルに以下が追加されます:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-redis-client</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-redis-client")

インクリメントPOJOの作成

Increment POJO を使用してインクリメントをモデル化します。 src/main/java/org/acme/redis/Increment.java ファイルを作成し、以下の内容で作成します。

package org.acme.redis;

public class Increment {
    public String key; (1)
    public long value; (2)

    public Increment(String key, long value) {
        this.key = key;
        this.value = value;
    }

    public Increment() {
    }
}
1 Redisキーとして使用されるキー
2 Redisキーが保持する値

インクリメントサービスの作成

Redis クライアントの役割を果たす IncrementService クラスを作成します。このクラスで、 SETGETDELKEYSINCRBY Redis コマンドを実行できるようになります。

以下の内容の src/main/java/org/acme/redis/IncrementService.java ファイルを作成します:

package org.acme.redis;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import io.quarkus.redis.datasource.ReactiveRedisDataSource;
import io.quarkus.redis.datasource.RedisDataSource;
import io.quarkus.redis.datasource.keys.KeyCommands;
import io.quarkus.redis.datasource.keys.ReactiveKeyCommands;
import io.quarkus.redis.datasource.string.StringCommands;
import io.smallrye.mutiny.Uni;

@ApplicationScoped
public class IncrementService {

    // This quickstart demonstrates both the imperative
    // and reactive Redis data sources
    // Regular applications will pick one of them.

    private ReactiveKeyCommands<String> keyCommands; (1)
    private ValueCommands<String, Long> countCommands; (2)

    public IncrementService(RedisDataSource ds, ReactiveRedisDataSource reactive) { (3)
        countCommands = ds.value(Long.class); (4)
        keyCommands = reactive.key();  (5)

    }


    long get(String key) {
        Long value = countCommands.get(key); (6)
        if (value == null) {
            return 0L;
        }
        return value;
    }

    void set(String key, Long value) {
        countCommands.set(key, value); (7)
    }

    void increment(String key, Long incrementBy) {
        countCommands.incrby(key, incrementBy); (8)
    }

    Uni<Void> del(String key) {
        return keyCommands.del(key) (9)
            .replaceWithVoid();
    }

    Uni<List<String>> keys() {
        return keyCommands.keys("*"); (10)
    }
}
1 キー操作のために使用するフィールド
2 カウンター操作のために使用するフィールド
3 命令型と反応型の両方のデータソースをインジェクトします
4 カウンターを操作するためのコマンドを取得します
5 キーを操作するコマンドを取得します
6 与えられたキーに関連する値を取得します  null の場合は、 0 を返します
7 与えられたキーに関連する値を設定します
8 キーが与えられた値をインクリメントします
9 キー(とそれに付随する値)を削除します
10 すべてのキーをリストアップします

インクリメントリソースの作成

以下の内容の src/main/java/org/acme/redis/IncrementResource.java ファイルを作成します:

package org.acme.redis;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.DELETE;
import java.util.List;

import io.smallrye.mutiny.Uni;

@Path("/increments")
public class IncrementResource {

    @Inject
    IncrementService service;

    @GET
    public Uni<List<String>> keys() {
        return service.keys();
    }

    @POST
    public Increment create(Increment increment) {
        service.set(increment.key, increment.value);
        return increment;
    }

    @GET
    @Path("/{key}")
    public Increment get(String key) {
        return new Increment(key, service.get(key));
    }

    @PUT
    @Path("/{key}")
    public void increment(String key, long value) {
        service.increment(key, value);
    }

    @DELETE
    @Path("/{key}")
    public Uni<Void> delete(String key) {
        return service.del(key);
    }
}

テストクラスの作成

pom.xml ファイルを編集し、以下の依存関係を追加します:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <scope>test</scope>
</dependency>

src/test/java/org/acme/redis/IncrementResourceTest.java ファイルを以下の内容で作成してください:

package org.acme.redis;

import static org.hamcrest.Matchers.is;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

import static io.restassured.RestAssured.given;

import io.restassured.http.ContentType;

@QuarkusTest
public class IncrementResourceTest {

    @Test
    public void testRedisOperations() {
        // verify that we have nothing
        given()
                .accept(ContentType.JSON)
                .when()
                .get("/increments")
                .then()
                .statusCode(200)
                .body("size()", is(0));

        // create a first increment key with an initial value of 0
        given()
                .contentType(ContentType.JSON)
                .accept(ContentType.JSON)
                .body("{\"key\":\"first-key\",\"value\":0}")
                .when()
                .post("/increments")
                .then()
                .statusCode(200)
                .body("key", is("first-key"))
                .body("value", is(0));

        // create a second increment key with an initial value of 10
        given()
                .contentType(ContentType.JSON)
                .accept(ContentType.JSON)
                .body("{\"key\":\"second-key\",\"value\":10}")
                .when()
                .post("/increments")
                .then()
                .statusCode(200)
                .body("key", is("second-key"))
                .body("value", is(10));

        // increment first key by 1
        given()
                .contentType(ContentType.JSON)
                .body("1")
                .when()
                .put("/increments/first-key")
                .then()
                .statusCode(204);

        // verify that key has been incremented
        given()
                .accept(ContentType.JSON)
                .when()
                .get("/increments/first-key")
                .then()
                .statusCode(200)
                .body("key", is("first-key"))
                .body("value", is(1));

        // increment second key by 1000
        given()
                .contentType(ContentType.JSON)
                .body("1000")
                .when()
                .put("/increments/second-key")
                .then()
                .statusCode(204);

        // verify that key has been incremented
        given()
                .accept(ContentType.JSON)
                .when()
                .get("/increments/second-key")
                .then()
                .statusCode(200)
                .body("key", is("second-key"))
                .body("value", is(1010));

        // verify that we have two keys in registered
        given()
                .accept(ContentType.JSON)
                .when()
                .get("/increments")
                .then()
                .statusCode(200)
                .body("size()", is(2));

        // delete first key
        given()
                .accept(ContentType.JSON)
                .when()
                .delete("/increments/first-key")
                .then()
                .statusCode(204);

        // verify that we have one key left after deletion
        given()
                .accept(ContentType.JSON)
                .when()
                .get("/increments")
                .then()
                .statusCode(200)
                .body("size()", is(1));

        // delete second key
        given()
                .accept(ContentType.JSON)
                .when()
                .delete("/increments/second-key")
                .then()
                .statusCode(204);

        // verify that there is no key left
        given()
                .accept(ContentType.JSON)
                .when()
                .get("/increments")
                .then()
                .statusCode(200)
                .body("size()", is(0));
    }
}

起動

指示に従えば、Redisサーバーが起動しているはずです。あとは、アプリケーションを使って実行するだけです。

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

別のターミナルを開いて curl http://localhost:8080/increments コマンドを実行します。

アプリケーションとの相互作用

上で見たように、APIは5つのRestエンドポイントを公開しています。このセクションでは、インクリメントを初期化する方法、現在のインクリメントのリストを見る方法、キーを指定して値をインクリメントする方法、インクリメントの現在の値を取得する方法、そして最後にキーを削除する方法を見ていきます。

新しいインクリメントの作成

curl -X POST -H "Content-Type: application/json" -d '{"key":"first","value":10}' http://localhost:8080/increments (1)
1 最初のインクリメントを作成し、キーは first 、初期値は 10 とします

上記のコマンドを実行すると、以下のような結果が返ってくるはずです:

{
  "key": "first",
  "value": 10
}

現在のインクリメントキーの確認

現在のインクリメントキーのリストを表示するには、以下のコマンドを実行します:

curl http://localhost:8080/increments

上記のコマンドは ["first"] を返し、これまでのところインクリメントが 1 つしかないことを示しているはずです。

新しいインクリメントの取得

キーを使ってインクリメントを取得するには、以下のコマンドを実行する必要があります:

curl http://localhost:8080/increments/first (1)
1 このコマンドを実行すると、以下のような結果が返ってくるはずです:
{
  "key": "first",
  "value": 10
}

キーが与えられた値をインクリメントします

値をインクリメントするには、以下のコマンドを実行します:

curl -X PUT -H "Content-Type: application/json" -d '27' http://localhost:8080/increments/first (1)
1 first の値を 27 増やします。

さて、コマンドを実行すると curl http://localhost:8080/increments/first は次のような結果を返します:

{
  "key": "first",
  "value": 37 (1)
}
1 first キーの値が 37 になっていることがわかりますが、これはまさに簡単な計算である 10 + 27 の結果と同じです。

キーの削除

インクリメントのキーを指定して削除するには、以下のコマンドを使用します。

curl -X DELETE  http://localhost:8080/increments/first (1)
1 first のインクリメントを削除します。

さて、コマンドを実行すると curl http://localhost:8080/increments は空のリスト [] を返します

本番環境での設定

この時点で、QuarkusはRedis Dev Serviceを使用して、Redisサーバーを実行し、アプリケーションを構成しています。 しかし、本番環境では、独自のRedisを実行することになります(または、クラウドサービスを使用します)。

以下の形で6379番ポートでRedisサーバを起動してみましょう:

docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name redis_quarkus_test -p 6379:6379 redis:5.0.6

次に、 src/main/resources/application.properties ファイルを開き追加します:

%prod.quarkus.redis.hosts=redis://localhost:6379

JVMモードでのパッケージ化と実行

従来の jar ファイルとしてアプリケーションを実行することができます。

まず、パッケージ化します:

コマンドラインインタフェース
quarkus build
Maven
./mvnw install
Gradle
./gradlew build
このコマンドはテストを実行するためのRedisインスタンスを起動します。

次に、以下を実行してください:

java -jar target/quarkus-app/quarkus-run.jar

ネイティブ実行

ソースコードを変更することなく、このアプリケーションからネイティブ実行可能ファイルを作成することもできます。ネイティブ実行可能ファイルは、JVMへの依存を取り除きます。ターゲットプラットフォーム上でアプリケーションを実行するために必要なすべてのものが実行ファイルに含まれているため、アプリケーションを最小限のリソースオーバーヘッドで実行することができます。

GraalVMは、不要なコードパスを削除するために追加のステップを実行するため、ネイティブ実行可能ファイルのコンパイルには少し時間がかかります。 native プロファイルを使用して、ネイティブ実行可能ファイルをコンパイルしてください。

コマンドラインインタフェース
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native

ビルドが完了したら、実行可能ファイルを次のように実行することが出来ます:

./target/redis-quickstart-1.0.0-SNAPSHOT-runner

さらに詳しく

Quarkus Redisエクステンションの詳細については、 Redis エクステンションリファレンスガイド を参照してください。

関連コンテンツ