コンテンツにスキップ

Redis

Redisは、キャッシュやメッセージブローカーとして一般的に使用される、最も人気のあるインメモリデータ構造ストアの1つです。

このライブラリは、VaporとRedisとの通信を行う基盤ドライバーであるRediStackとの統合です。

Note

Redisの機能のほとんどはRediStackによって提供されています。 そのドキュメントに精通することを強くお勧めします。

適切な箇所にリンクを提供しています。

パッケージ

Redisを使用する最初のステップは、Swiftパッケージマニフェストでプロジェクトの依存関係として追加することです。

この例は既存のパッケージ用です。新しいプロジェクトの開始に関するヘルプについては、メインのGetting Startedガイドを参照してください。

dependencies: [
    // ...
    .package(url: "https://github.com/vapor/redis.git", from: "4.0.0")
]
// ...
targets: [
    .target(name: "App", dependencies: [
        // ...
        .product(name: "Redis", package: "redis")
    ])
]

設定

VaporはRedisConnectionインスタンスのプーリング戦略を採用しており、個々の接続とプール自体を設定するためのいくつかのオプションがあります。

Redisを設定するために必要な最小限の要件は、接続するURLを提供することです:

let app = Application()

app.redis.configuration = try RedisConfiguration(hostname: "localhost")

Redis設定

APIドキュメント:RedisConfiguration

serverAddresses

Redisインスタンスのクラスターなど、複数のRedisエンドポイントがある場合は、代わりにイニシャライザに渡す[SocketAddress]コレクションを作成する必要があります。

SocketAddressを作成する最も一般的な方法は、makeAddressResolvingHost(_:port:)静的メソッドを使用することです。

let serverAddresses: [SocketAddress] = [
  try .makeAddressResolvingHost("localhost", port: RedisConnection.Configuration.defaultPort)
]

単一のRedisエンドポイントの場合、SocketAddressの作成を処理してくれるため、便利なイニシャライザを使用する方が簡単です:

password

Redisインスタンスがパスワードで保護されている場合は、password引数として渡す必要があります。

各接続は作成時にパスワードを使用して認証されます。

database

これは、各接続が作成されるときに選択したいデータベースインデックスです。

これにより、自分でRedisにSELECTコマンドを送信する必要がなくなります。

Warning

データベースの選択は維持されません。自分でSELECTコマンドを送信する際は注意してください。

接続プールオプション

APIドキュメント:RedisConfiguration.PoolOptions

Note

ここでは最も一般的に変更されるオプションのみを強調しています。すべてのオプションについては、APIドキュメントを参照してください。

minimumConnectionCount

これは、各プールが常に維持したい接続数を設定する値です。

値が0の場合、何らかの理由で接続が失われても、プールは必要になるまで再作成しません。

これは「コールドスタート」接続として知られており、最小接続数を維持するよりもオーバーヘッドがあります。

maximumConnectionCount

このオプションは、最大接続数がどのように維持されるかの動作を決定します。

Seealso

どのようなオプションが利用可能かについては、RedisConnectionPoolSize APIを参照してください。

コマンドの送信

ApplicationまたはRequestインスタンスの.redisプロパティを使用してコマンドを送信できます。これにより、RedisClientにアクセスできます。

すべてのRedisClientには、さまざまなRedisコマンド用の拡張機能があります。

let value = try app.redis.get("my_key", as: String.self).wait()
print(value)
// Optional("my_value")

// または

let value = try await app.redis.get("my_key", as: String.self)
print(value)
// Optional("my_value")

サポートされていないコマンド

RediStackが拡張メソッドでコマンドをサポートしていない場合でも、手動で送信できます。

// コマンドの後の各値は、Redisが期待する位置引数です
try app.redis.send(command: "PING", with: ["hello"])
    .map {
        print($0)
    }
    .wait()
// "hello"

// または

let res = try await app.redis.send(command: "PING", with: ["hello"])
print(res)
// "hello"

Pub/Subモード

Redisは、接続が特定の「チャンネル」をリッスンし、購読したチャンネルが「メッセージ」(何らかのデータ値)をパブリッシュしたときに特定のクロージャを実行できる「Pub/Sub」モードをサポートしています。

サブスクリプションには定義されたライフサイクルがあります:

  1. subscribe:サブスクリプションが最初に開始されたときに1回呼び出されます
  2. message:購読したチャンネルにメッセージがパブリッシュされるたびに0回以上呼び出されます
  3. unsubscribe:リクエストによるか接続が失われたかにより、サブスクリプションが終了したときに1回呼び出されます

サブスクリプションを作成するときは、購読したチャンネルによってパブリッシュされたすべてのメッセージを処理するために、少なくともmessageReceiverを提供する必要があります。

オプションで、それぞれのライフサイクルイベントを処理するために、onSubscribeonUnsubscribe用のRedisSubscriptionChangeHandlerを提供できます。

// 指定された各チャンネルに対して1つずつ、2つのサブスクリプションを作成します
app.redis.subscribe
  to: "channel_1", "channel_2",
  messageReceiver: { channel, message in
    switch channel {
    case "channel_1": // メッセージで何か処理を行う
    default: break
    }
  },
  onUnsubscribe: { channel, subscriptionCount in
    print("unsubscribed from \(channel)")
    print("subscriptions remaining: \(subscriptionCount)")
  }