1. 概要

RedissonはJava用のRedisクライアントです。 この記事では、その機能のいくつかを調査し、分散型ビジネスアプリケーションの構築を容易にする方法を示します。

Redissonは、Redisに裏打ちされた分散Javaオブジェクトとサービスを提供するインメモリデータグリッドを構成します。分散インメモリデータモデルにより、アプリケーションとサーバー間でドメインオブジェクトとサービスを共有できます。

この記事では、Redissonのセットアップ、その動作方法の理解、およびRedissonのオブジェクトとサービスのいくつかについて説明します。

2. Mavenの依存関係

以下のセクションをpom.xml:に追加して、Redissonをプロジェクトにインポートすることから始めましょう。

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.1</version>
</dependency>

この依存関係の最新バージョンは、ここにあります。

3. 構成

開始する前に、Redisの最新バージョンがセットアップされて実行されていることを確認する必要があります。 Redisがなく、LinuxまたはMacintoshを使用している場合は、こちらの情報に従ってセットアップを行うことができます。 Windowsユーザーの場合は、この非公式のポートを使用してRedisをセットアップできます。

Redisに接続するようにRedissonを設定する必要があります。 Redissonは、次のRedis構成への接続をサポートしています。

  • シングルノード
  • スレーブノードでマスター
  • センチネルリンパ節
  • クラスター化されたノード
  • 複製されたノード

Redissonは、クラスター化されたノードと複製されたノードに対して、Amazon Web Services(AWS)ElastiCacheClusterとAzureRedisCacheをサポートします。

Redisのシングルノードインスタンスに接続してみましょう。 このインスタンスは、デフォルトのポート6379でローカルに実行されています。

RedissonClient client = Redisson.create();

Redissonオブジェクトのcreateメソッドにさまざまな構成を渡すことができます。 これは、別のポートに接続するための構成、またはRedisクラスターに接続するための構成である可能性があります。 この構成は、Javaコードであるか、外部構成ファイルからロードできます。

3.1. Java構成

JavaコードでRedissonを設定しましょう:

Config config = new Config();
config.useSingleServer()
  .setAddress("redis://127.0.0.1:6379");

RedissonClient client = Redisson.create(config);

ConfigオブジェクトのインスタンスでRedisson構成を指定し、それをcreateメソッドに渡します。 上記では、Redisの単一ノードインスタンスに接続することをRedissonに指定しました。 これを行うために、ConfigオブジェクトのuseSingleServerメソッドを使用しました。 これにより、SingleServerConfigオブジェクトへの参照が返されます。

SingleServerConfig オブジェクトには、RedissonがRedisの単一ノードインスタンスに接続するために使用する設定があります。 ここでは、 setAddress メソッドを使用して、アドレス設定を構成します。 これにより、接続しているノードのアドレスが設定されます。 その他の設定には、 restartAttempts connectionTimeout 、およびclientNameが含まれます。 これらの設定は、対応するセッターメソッドを使用して構成されます。

Config オブジェクトの次のメソッドを使用して、同様の方法でさまざまなRedis構成用にRedissonを構成できます。

  • useSingleServer –シングルノードインスタンスの場合。 単一ノード設定を取得ここ
  • useMasterSlaveServers –スレーブノードを持つマスター用。 マスタースレーブノードの設定を取得するここ
  • useSentinelServers –センチネルノード用。 番兵ノードの設定を取得するここ
  • useClusterServers –クラスター化されたノード用。 クラスタ化されたノードの設定を取得するここ
  • useReplicatedServers –レプリケートされたノード用。 複製されたノード設定を取得するここ

3.2. ファイル構成

Redissonは、外部JSONまたはYAMLファイルから構成を読み込むことができます。

Config config = Config.fromJSON(new File("singleNodeConfig.json"));  
RedissonClient client = Redisson.create(config);

ConfigオブジェクトのfromJSONメソッドは、文字列、ファイル、入力ストリーム、またはURLから構成をロードできます。

singleNodeConfig.jsonファイルの構成例は次のとおりです。

{
    "singleServerConfig": {
        "idleConnectionTimeout": 10000,
        "connectTimeout": 10000,
        "timeout": 3000,
        "retryAttempts": 3,
        "retryInterval": 1500,
        "password": null,
        "subscriptionsPerConnection": 5,
        "clientName": null,
        "address": "redis://127.0.0.1:6379",
        "subscriptionConnectionMinimumIdleSize": 1,
        "subscriptionConnectionPoolSize": 50,
        "connectionMinimumIdleSize": 10,
        "connectionPoolSize": 64,
        "database": 0,
        "dnsMonitoringInterval": 5000
    },
    "threads": 0,
    "nettyThreads": 0,
    "codec": null
}

対応するYAML構成ファイルは次のとおりです。

singleServerConfig:
    idleConnectionTimeout: 10000
    connectTimeout: 10000
    timeout: 3000
    retryAttempts: 3
    retryInterval: 1500
    password: null
    subscriptionsPerConnection: 5
    clientName: null
    address: "redis://127.0.0.1:6379"
    subscriptionConnectionMinimumIdleSize: 1
    subscriptionConnectionPoolSize: 50
    connectionMinimumIdleSize: 10
    connectionPoolSize: 64
    database: 0
    dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}

その構成に固有の設定を使用して、同様の方法でファイルから他のRedis構成を構成できます。 参考までに、JSONおよびYAMLファイル形式は次のとおりです。

Java構成をJSONまたはYAML形式で保存するには、ConfigオブジェクトのtoJSONまたはtoYAMLメソッドを使用できます。

Config config = new Config();
// ... we configure multiple settings here in Java
String jsonFormat = config.toJSON();
String yamlFormat = config.toYAML();

Redissonの構成方法がわかったので、Redissonが操作を実行する方法を見てみましょう。

4. 手術

Redissonは、同期、非同期、およびリアクティブインターフェイスをサポートします。 これらのインターフェースを介した操作はスレッドセーフです。

RedissonClient によって生成されるすべてのエンティティ(オブジェクト、コレクション、ロック、およびサービス)には、同期メソッドと非同期メソッドがあります。 同期メソッドには非同期バリアントがあります。 これらのメソッドには通常、「非同期」が追加された同期バリアントと同じメソッド名が付けられています。 RAtomicLongオブジェクトの同期メソッドを見てみましょう。

RedissonClient client = Redisson.create();
RAtomicLong myLong = client.getAtomicLong('myLong');

同期compareAndSetメソッドの非同期バリアントは次のようになります。

RFuture<Boolean> isSet = myLong.compareAndSetAsync(6, 27);

メソッドの非同期バリアントは、RFutureオブジェクトを返します。 このオブジェクトにリスナーを設定して、使用可能になったときに結果を返すことができます。

isSet.handle((result, exception) -> {
    // handle the result or exception here.
});

リアクティブオブジェクトを生成するには、RedissonReactiveClientを使用する必要があります。

RedissonReactiveClient client = Redisson.createReactive();
RAtomicLongReactive myLong = client.getAtomicLong("myLong");

Publisher<Boolean> isSetPublisher = myLong.compareAndSet(5, 28);

このメソッドは、Java9のReactiveStreams標準に基づいてリアクティブオブジェクトを返します。

Redissonが提供する分散オブジェクトのいくつかを調べてみましょう。

5. オブジェクト

Redissonオブジェクトの個々のインスタンスはシリアル化され、Redissonをサポートする使用可能なRedisノードのいずれかに格納されます。 これらのオブジェクトは、クラスター内で複数のノードに分散でき、単一のアプリケーションまたは複数のアプリケーション/サーバーからアクセスできます。

これらの分散オブジェクトは、 java.util.concurrent.atomicパッケージ。 これらは、Redisに保存されているオブジェクトに対するロックフリー、スレッドセーフ、およびアトミック操作をサポートします 。 別のアプリケーションがオブジェクトを読み取っている間は値が更新されないため、アプリケーション/サーバー間のデータの一貫性が保証されます。

RedissonオブジェクトはRedisキーにバインドされています。 これらのキーは、RKeysインターフェイスを介して管理できます。 次に、これらのキーを使用してRedissonオブジェクトにアクセスします。

Redisキーを取得するために使用できるオプションがいくつかあります。

すべてのキーを簡単に取得できます。

RKeys keys = client.getKeys();

または、名前のみを抽出することもできます。

Iterable<String> allKeys = keys.getKeys();

そして最後に、パターンに準拠したキーを取得できます。

Iterable<String> keysByPattern = keys.getKeysByPattern('key*')

RKeysインターフェースでは、キーの削除、パターンによるキーの削除、およびキーとオブジェクトの管理に使用できるその他の便利なキーベースの操作も可能です。

Redissonが提供する分散オブジェクトには次のものがあります。

  • ObjectHolder
  • BinaryStreamHolder
  • GeospatialHolder
  • BitSet
  • AtomicLong
  • AtomicDouble
  • トピック
  • BloomFilter
  • HyperLogLog

これらのオブジェクトのうち、 ObjectHolder、AtomicLong、、およびTopic。の3つを見てみましょう。

5.1. オブジェクトホルダー

RBucket クラスで表されるこのオブジェクトは、任意のタイプのオブジェクトを保持できます。 このオブジェクトの最大サイズは512MBです。

RBucket<Ledger> bucket = client.getBucket("ledger");
bucket.set(new Ledger());
Ledger ledger = bucket.get();

RBucket オブジェクトは、保持しているオブジェクトに対してcompareAndSetやgetAndSetなどのアトミック操作を実行できます。

5.2. AtomicLong

RAtomicLong クラスで表されるこのオブジェクトは、 java.util.concurrent.atomic.AtomicLong クラスによく似ており、アトミックに更新できるlong値を表します。

RAtomicLong atomicLong = client.getAtomicLong("myAtomicLong");
atomicLong.set(5);
atomicLong.incrementAndGet();

5.3. トピック

Topic オブジェクトは、Redisの「パブリッシュおよびサブスクライブ」メカニズムをサポートします。 公開されたメッセージをリッスンするには:

RTopic subscribeTopic = client.getTopic("baeldung");
subscribeTopic.addListener(CustomMessage.class,
  (channel, customMessage) -> future.complete(customMessage.getMessage()));

上記のトピックは、「baeldung」チャネルからのメッセージを聞くために登録されています。 次に、トピックにリスナーを追加して、そのチャネルからの着信メッセージを処理します。 1つのチャネルに複数のリスナーを追加できます。

「baeldung」チャネルにメッセージを公開しましょう。

RTopic publishTopic = client.getTopic("baeldung");
long clientsReceivedMessage
  = publishTopic.publish(new CustomMessage("This is a message"));

これは、別のアプリケーションまたはサーバーから公開される可能性があります。 CustomMessage オブジェクトはリスナーによって受信され、onMessageメソッドで定義されたとおりに処理されます。

他のRedissonオブジェクトここについて詳しく知ることができます。

6. コレクション

Redissonコレクションは、オブジェクトを処理するのと同じ方法で処理します。

Redissonが提供する分散コレクションには次のものがあります。

  • 地図
  • マルチマップ
  • 設定
  • SortedSet
  • ScoredSortedSet
  • Lex SortedSet
  • リスト
  • Deque
  • BlockingQueue
  • BoundedBlockingQueue
  • BlockingDeque
  • BlockingFairQueue
  • DelayedQueue
  • PriorityQueue
  • PriorityDeque

これらのコレクションのうち、 Map、Set、List。の3つを見てみましょう。

6.1. マップ

Redissonベースのマップは、java.util.concurrent.ConcurrentMapおよびjava.util.Mapインターフェースを実装します。 Redissonには4つのマップ実装があります。 これらは、 RMap RMapCache RLocalCachedMap 、およびRClusteredMapです。

Redissonでマップを作成しましょう:

RMap<String, Ledger> map = client.getMap("ledger");
Ledger newLedger = map.put("123", new Ledger());map

RMapCache は、マップエントリの削除をサポートします。 RLocalCachedMap マップエントリのローカルキャッシュを許可します 。 RClusteredMap 単一のマップからのデータをRedisクラスターマスターノード間で分割できるようにします。

Redissonマップの詳細についてはこちらをご覧ください。

6.2. セット

RedissonベースのSetは、java.util.Setインターフェースを実装します。

Redissonには、3つの Set 実装、 RSet RSetCache 、および RClusteredSet があり、対応するマップと同様の機能を備えています。

RedissonでSetを作成しましょう。

RSet<Ledger> ledgerSet = client.getSet("ledgerSet");
ledgerSet.add(new Ledger());

Redissonセットの詳細についてはこちらをご覧ください。

6.3. リスト

RedissonベースのListsは、java.util.Listインターフェースを実装します。

Redissonでリストを作成しましょう。

RList<Ledger> ledgerList = client.getList("ledgerList");
ledgerList.add(new Ledger());

他のRedissonコレクションの詳細についてはこちらをご覧ください。

7. ロックとシンクロナイザー

Redissonの分散ロックにより、アプリケーション/サーバー間でのスレッド同期が可能になります。 Redissonのロックとシンクロナイザーのリストは次のとおりです。

  • ロック
  • FairLock
  • マルチロック
  • ReadWriteLock
  • セマフォ
  • PermitExpirableSemaphore
  • CountDownLatch

ロックマルチロックを見てみましょう。

7.1. ロック

RedissonのLockは、 java.util.concurrent.locks.Lockインターフェースを実装します。

RLockクラスで表されるロックを実装しましょう。

RLock lock = client.getLock("lock");
lock.lock();
// perform some long operations...
lock.unlock();

7.2. マルチロック

RedissonのRedissonMultiLockは、複数の RLock オブジェクトをグループ化し、それらを単一のロックとして扱います。

RLock lock1 = clientInstance1.getLock("lock1");
RLock lock2 = clientInstance2.getLock("lock2");
RLock lock3 = clientInstance3.getLock("lock3");

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
// perform long running operation...
lock.unlock();

他のロックについて詳しくは、こちらをご覧ください。

8. サービス

Redissonは、4種類の分散サービスを公開しています。 これらは、リモートサービスライブオブジェクトサービスエグゼキューターサービスおよびスケジュールされたエグゼキューターサービスです。 リモートサービスとライブオブジェクトサービスを見てみましょう。

8.1. リモートサービス

このサービスは、Redisによって促進されるJavaリモートメソッド呼び出しを提供します。 Redissonリモートサービスは、サーバー側(ワーカーインスタンス)とクライアント側の実装で構成されます。 サーバー側の実装は、クライアントによって呼び出されたリモートメソッドを実行します。 リモートサービスからの呼び出しは、同期または非同期にすることができます。

サーバー側は、リモート呼び出し用のインターフェースを登録します。

RRemoteService remoteService = client.getRemoteService();
LedgerServiceImpl ledgerServiceImpl = new LedgerServiceImpl();

remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);

クライアント側は、登録されたリモートインターフェイスのメソッドを呼び出します。

RRemoteService remoteService = client.getRemoteService();
LedgerServiceInterface ledgerService
  = remoteService.get(LedgerServiceInterface.class);

List<String> entries = ledgerService.getEntries(10);

リモートサービスの詳細については、こちらをご覧ください。

8.2. ライブオブジェクトサービス

Redisson Live Objectsは、単一のJVMからのみアクセスできる標準のJavaオブジェクトの概念を、異なるマシンの異なるJVM間で共有できる拡張Javaオブジェクトに拡張します。 これは、オブジェクトのフィールドをRedisハッシュにマッピングすることで実現されます。 このマッピングは、ランタイムで構築されたプロキシクラスを介して行われます。 フィールドゲッターとセッターは、Redis hget/hsetコマンドにマップされます。

Redisson Live Objectsは、Redisのシングルスレッドの性質の結果として、アトミックフィールドアクセスをサポートします。

ライブオブジェクトの作成は簡単です。

@REntity
public class LedgerLiveObject {
    @RId
    private String name;

    // getters and setters...
}

クラスに@REntityで注釈を付け、一意のフィールドまたは識別フィールドに@RIdで注釈を付けます。 これを実行したら、アプリケーションでライブオブジェクトを使用できます。

RLiveObjectService service = client.getLiveObjectService();

LedgerLiveObject ledger = new LedgerLiveObject();
ledger.setName("ledger1");

ledger = service.persist(ledger);

新しいキーワードを使用して、標準のJavaオブジェクトのようにライブオブジェクトを作成します。 次に、 RLiveObjectService のインスタンスを使用して、persistメソッドを使用してオブジェクトをRedisに保存します。

オブジェクトが以前にRedisに永続化されている場合は、オブジェクトを取得できます。

LedgerLiveObject returnLedger
  = service.get(LedgerLiveObject.class, "ledger1");

RLiveObjectService を使用して、@RIdで注釈が付けられたフィールドを使用してライブオブジェクトを取得します。

ここRedissonLive Objectsの詳細を確認できます。また、他のRedissonサービスについてはここで説明しています。

9. パイプライン

Redissonはパイプラインをサポートしています。 複数の操作を単一のアトミック操作としてバッチ処理できます。 これは、RBatchクラスによって容易になります。 複数のコマンドは、実行される前にRBatchオブジェクトインスタンスに対して集約されます。

RBatch batch = client.createBatch();
batch.getMap("ledgerMap").fastPutAsync("1", "2");
batch.getMap("ledgerMap").putAsync("2", "5");

BatchResult<?> batchResult = batch.execute();

10. スクリプティング

RedissonはLUAスクリプトをサポートしています。 Redisに対してLUAスクリプトを実行できます

client.getBucket("foo").set("bar");
String result = client.getScript().eval(Mode.READ_ONLY,
  "return redis.call('get', 'foo')", RScript.ReturnType.VALUE);

11. 低レベルのクライアント

RedissonでまだサポートされていないRedis操作を実行したい場合があります。 Redissonは、ネイティブRedisコマンドの実行を可能にする低レベルのクライアントを提供します

RedisClientConfig redisClientConfig = new RedisClientConfig();
redisClientConfig.setAddress("localhost", 6379);

RedisClient client = RedisClient.create(redisClientConfig);

RedisConnection conn = client.connect();
conn.sync(StringCodec.INSTANCE, RedisCommands.SET, "test", 0);

conn.closeAsync();
client.shutdown();

低レベルのクライアントは、非同期操作もサポートします。

12. 結論

この記事では、Redissonと、分散アプリケーションの開発に理想的なRedissonのいくつかの機能を紹介しました。 分散オブジェクト、コレクション、ロック、およびサービスについて調査しました。 また、パイプライン、スクリプト、低レベルのクライアントなど、その他の機能についても説明しました。

Redissonは、JCache API、Spring Cache、Hibernate Cache、SpringSessionsなどの他のフレームワークとの統合も提供します。 他のフレームワークとの統合について詳しくは、こちらをご覧ください。

コードサンプルはGitHubプロジェクトにあります。