Lettuce

JavaキャッシュライブラリRedis非同期リアクティブNoSQL

GitHub概要

redis/lettuce

Advanced Java Redis client for thread-safe sync, async, and reactive usage. Supports Cluster, Sentinel, Pipelining, and codecs.

ホームページ:https://lettuce.io
スター5,663
ウォッチ204
フォーク1,056
作成日:2014年5月10日
言語:Java
ライセンス:MIT License

トピックス

asynchronousaws-elasticacheazure-redis-cachejavareactiveredisredis-clientredis-clusterredis-sentinel

スター履歴

redis/lettuce Star History
データ取得日時: 2025/10/22 10:05

キャッシュライブラリ

Lettuce

概要

Lettuceは、Javaアプリケーション向けの高度なRedisクライアントライブラリです。

詳細

Lettuce(レタス)は、RedisのオフィシャルクライアントファミリーとしてRedis社が公式サポートするJava向けRedisクライアントです。2024年にRedisのオフィシャルクライアントファミリーに加わり、MITライセンスの下でオープンソースとして提供されています。スレッドセーフな設計により、複数のスレッドが単一の接続を安全に共有でき、同期、非同期、リアクティブ、Kotlinコルーチンの4つのプログラミングモデルをサポートしています。NettyをベースとしたノンブロッキングI/Oアーキテクチャにより、高いパフォーマンスと低レイテンシを実現し、Redis Sentinel、Redis Cluster、パイプライン処理、自動再接続、SSL/TLS、Pub/Sub等の豊富な機能を提供します。Java 8のCompletionStageインターフェースを活用し、アプリケーションがデータの受信方法を細かく制御できる仕組みを提供しています。

メリット・デメリット

メリット

  • スレッドセーフ: 単一接続を複数スレッドで安全に共有可能
  • 高性能: NettyベースのノンブロッキングI/Oによる高スループット
  • 豊富なAPIモデル: 同期、非同期、リアクティブ、コルーチンに対応
  • 堅牢な接続管理: 自動再接続とコマンドバッファリング機能
  • Redis機能完全サポート: 全コマンドセットとデプロイメントモデル対応
  • 公式サポート: Redis社による公式サポートと継続的な開発
  • Springとの統合: Spring Data Redisとの優れた統合性

デメリット

  • 学習コスト: 多様なAPIモデルと高度な機能の習得が必要
  • ブロッキング操作の制約: BLPOPやMULTI/EXECは専用接続が必要
  • メモリ使用量: 豊富な機能による若干のメモリオーバーヘッド
  • 設定の複雑さ: 高度な機能使用時の設定が複雑になる場合がある

主要リンク

書き方の例

基本的な接続と操作

import io.lettuce.core.*;

// Redis クライアントの作成
RedisClient client = RedisClient.create("redis://localhost:6379");

// 接続の確立
StatefulRedisConnection<String, String> connection = client.connect();

// 同期コマンドの取得
RedisCommands<String, String> commands = connection.sync();

// 基本操作
commands.set("key", "Hello, Lettuce!");
String value = commands.get("key");
System.out.println(value); // "Hello, Lettuce!"

// リソースの解放
connection.close();
client.shutdown();

非同期API

import io.lettuce.core.api.async.RedisAsyncCommands;
import java.util.concurrent.CompletableFuture;

RedisClient client = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = client.connect();
RedisAsyncCommands<String, String> async = connection.async();

// 非同期でSET操作
RedisFuture<String> setResult = async.set("async-key", "async-value");

// 非同期でGET操作
RedisFuture<String> getValue = async.get("async-key");

// 結果の取得
setResult.thenAccept(result -> System.out.println("SET result: " + result));
getValue.thenAccept(value -> System.out.println("GET result: " + value));

// 複数の操作を並行実行
List<RedisFuture<String>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    futures.add(async.set("key-" + i, "value-" + i));
}

// 全ての操作完了を待機
LettuceFutures.awaitAll(1, TimeUnit.MINUTES, 
    futures.toArray(new RedisFuture[0]));

リアクティブAPI

import io.lettuce.core.api.reactive.RedisReactiveCommands;
import reactor.core.publisher.Mono;

RedisClient client = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = client.connect();
RedisReactiveCommands<String, String> reactive = connection.reactive();

// リアクティブストリーム
Mono<String> setMono = reactive.set("reactive-key", "reactive-value");
Mono<String> getMono = reactive.get("reactive-key");

// チェーン処理
setMono
    .then(getMono)
    .doOnNext(value -> System.out.println("Value: " + value))
    .subscribe();

// 複数の値を処理
reactive.mget("key1", "key2", "key3")
    .flatMapIterable(values -> values)
    .filter(value -> value.hasValue())
    .map(value -> value.getValue())
    .doOnNext(System.out::println)
    .subscribe();

Redis Cluster接続

import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;

// クラスターノードの設定
RedisURI node1 = RedisURI.create("redis://localhost:7000");
RedisURI node2 = RedisURI.create("redis://localhost:7001");
RedisURI node3 = RedisURI.create("redis://localhost:7002");

// クラスタークライアントの作成
RedisClusterClient clusterClient = RedisClusterClient
    .create(Arrays.asList(node1, node2, node3));

// クラスター接続
StatefulRedisClusterConnection<String, String> connection = 
    clusterClient.connect();

RedisAdvancedClusterCommands<String, String> commands = 
    connection.sync();

// クラスター操作
commands.set("cluster-key", "cluster-value");
String value = commands.get("cluster-key");

// 読み取り設定(レプリカから読み取り)
connection.setReadFrom(ReadFrom.REPLICA);

connection.close();
clusterClient.shutdown();

SSL/TLS接続

// SSL/TLS接続設定
RedisURI redisUri = RedisURI.Builder.redis("secure.redis.com")
    .withPort(6380)
    .withSsl(true)
    .withPassword("secure-password")
    .withDatabase(0)
    .build();

RedisClient client = RedisClient.create(redisUri);
StatefulRedisConnection<String, String> connection = client.connect();

// SSL接続でのコマンド実行
RedisCommands<String, String> commands = connection.sync();
commands.set("secure-key", "secure-value");

Pub/Sub機能

import io.lettuce.core.pubsub.RedisPubSubListener;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;

// Pub/Sub接続
StatefulRedisPubSubConnection<String, String> pubsubConnection = 
    client.connectPubSub();

// リスナーの設定
pubsubConnection.addListener(new RedisPubSubListener<String, String>() {
    @Override
    public void message(String channel, String message) {
        System.out.println("Received: " + message + " from " + channel);
    }

    @Override
    public void subscribed(String channel, long count) {
        System.out.println("Subscribed to " + channel);
    }

    @Override
    public void unsubscribed(String channel, long count) {
        System.out.println("Unsubscribed from " + channel);
    }
});

// チャンネル購読
RedisPubSubCommands<String, String> pubsub = pubsubConnection.sync();
pubsub.subscribe("news", "updates");

// メッセージ送信(別の接続から)
RedisCommands<String, String> publisher = client.connect().sync();
publisher.publish("news", "Breaking news!");