序章

Redis は、柔軟性、パフォーマンス、幅広い言語サポート、レプリケーションなどの組み込み機能で知られるインメモリのKey-Valueデータストアです。 レプリケーションとは、プライマリインスタンスの正確な複製を常に維持するレプリカを作成するために、あるデータベースから別のデータベースにデータを定期的にコピーする方法です。 Redisレプリケーションの一般的な使用法の1つは、パフォーマンスを向上させるためにインフラストラクチャをスケールアップする場合と同様に、既存のRedisデータストアを新しいサーバーに移行することです。

このチュートリアルでは、Redisの組み込みレプリケーション機能を使用して、あるUbuntu 18.04サーバー(「ソース」)から別のサーバー(「ターゲット」)にデータを移行するプロセスの概要を説明します。 これには、各サーバーにいくつかの構成変更を加え、ソースのレプリカとして機能するようにターゲットサーバーを設定し、移行の完了後にレプリカをプライマリに昇格させることが含まれます。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • Ubuntu18.04を実行している2台のサーバー。 各サーバーには、管理者権限で構成されたユーザーと、ufwで設定されたファイアウォールが必要です。 この環境をセットアップするには、両方のサーバーの Ubuntu18.04の初期サーバーセットアップガイドに従ってください。
  • 各サーバーにインストールされているRedisの最新バージョン。 これを設定するには、 Ubuntu18.04にソースからRedisをインストールする方法に関するガイドに従ってください。

ステップ1—(オプション)サンプルデータを使用してソースRedisインスタンスをロードする

このオプションの手順では、ソースRedisインスタンスにサンプルデータをロードして、データをターゲットインスタンスに移行してみることができます。 ターゲットに移行するデータがすでにある場合は、ステップ2 に進んで、データのバックアップ方法を確認できます。

まず、root以外のユーザーとしてソースRedisインスタンスとして使用するUbuntuサーバーに接続します。

  1. ssh sammy@source_server_ip

次に、次のコマンドを実行してRedisサーバーにアクセスします。

  1. redis-cli

パスワード認証を要求するようにRedisサーバーを構成した場合は、authコマンドを実行してからRedisパスワードを実行します。

  1. auth source_redis_password

次に、次のコマンドを実行します。 これらは、いくつかの文字列、ハッシュ、リスト、およびセットを保持するいくつかのキーを作成します。

  1. mset string1 "Redis" string2 "is" string3 "fun!"
  2. hmset hash1 field1 "Redis" field2 "is" field3 "fast!"
  3. rpush list1 "Redis" "is" "feature-rich!"
  4. sadd set1 "Redis" "is" "free!"

さらに、次のexpireコマンドを実行して、これらのキーのいくつかにタイムアウトを提供します。 これにより、それらは volatile になります。つまり、Redisは指定された時間(この場合は7500秒)後にそれらを削除します。

  1. expire string2 7500
  2. expire hash1 7500
  3. expire set1 7500

これで、ターゲットのRedisインスタンスにエクスポートできるサンプルデータがいくつかあります。 redis-cliプロンプトは今のところ開いたままにしておきます。これは、このデータをバックアップするために次のステップでさらにいくつかのコマンドを実行するためです。

ステップ2—ソースRedisインスタンスをバックアップする

あるサーバーから別のサーバーにデータを移動することを計画しているときはいつでも、何かがうまくいかず、結果としてデータを失う可能性があるというリスクがあります。 このリスクはわずかですが、レプリケーションプロセス中にエラーが発生した場合に備えて、Redisのbgsaveコマンドを使用してソースRedisデータベースのバックアップを作成します。

まだ開いていない場合は、Redisコマンドラインインターフェイスを開くことから始めます。

  1. redis-cli

また、パスワード認証を要求するようにRedisサーバーを構成した場合は、authコマンドを実行してからRedisパスワードを実行します。

  1. auth password

次に、bgsaveコマンドを実行します。 これにより、現在のデータセットのスナップショットが作成され、Redisの作業ディレクトリに保持されているダンプファイルにエクスポートされます。

  1. bgsave

注: saveまたはbgsaveコマンドを使用して、Redisデータベースのスナップショットを作成できます。 ただし、ここでbgsaveコマンドを使用する理由は、saveコマンドが同期を実行するためです。つまり、データベースに接続されている他のクライアントはすべてブロックされます。 このため、 saveコマンドのドキュメントでは、実稼働環境で実行することはほとんどないことを推奨しています。

代わりに、非同期を実行するbgsaveコマンドを使用することをお勧めします。 これにより、Redisはデータベースを2つのプロセスにフォークします。子が終了する前にデータベースを保存している間、親プロセスは引き続きクライアントにサービスを提供します。

bgsave操作の実行中にクライアントがデータを追加または変更した場合、これらの変更はスナップショットにキャプチャされないことに注意してください。

その後、exitコマンドを実行して、Redisインスタンスへの接続を閉じることができます。

  1. exit

将来必要になった場合は、Redisインスタンスの作業ディレクトリにあるデータダンプファイルを見つけることができます。 前提条件のRedisインストールチュートリアルで、作業ディレクトリとして/var/lib/redisを使用するようにRedisインスタンスを設定した方法を思い出してください。

Redis作業ディレクトリの内容を一覧表示して、データダンプファイルが保持されていることを確認します。

  1. sudo ls /var/lib/redis

ダンプファイルが正しくエクスポートされた場合は、このコマンドの出力に表示されます。 デフォルトでは、このファイルの名前はdump.rdbです。

Output
dump.rdb

データが正しくバックアップされたことを確認したら、外部接続を受け入れてレプリケーションを許可するようにソースRedisサーバーを構成する準備が整います。

ステップ3—ソースRedisインスタンスを設定する

デフォルトでは、Redisは外部接続をリッスンするように構成されていません。つまり、構成を更新しない限り、構成したレプリカはソースインスタンスと同期できません。 ここでは、ソースインスタンスの構成ファイルを更新して外部接続を許可し、レプリケーションの開始後にターゲットインスタンスが認証に使用するパスワードも設定します。 その後、ファイアウォールルールを追加して、Redisが実行されているポートへの接続を許可します。

好みのテキストエディタでソースRedisインスタンスの設定ファイルを開きます。 ここでは、nanoを使用します。

  1. sudo nano /etc/redis/redis.conf

bindディレクティブで始まる行に移動します。 デフォルトでは次のようになります。

/etc/redis/redis.conf
. . .
bind 127.0.0.1
. . .

このディレクティブは、Redisをlocalhostを表すIPv4ループバックアドレスである127.0.0.1にバインドします。 これは、このRedisインスタンスが、インストールされているサーバーと同じサーバーから発信された接続のみをリッスンするように構成されていることを意味します。 ソースインスタンスが、ターゲットインスタンスからの接続など、パブリックIPアドレスへの接続を受け入れることができるようにするには、127.0.0.1の後にソースRedisサーバーのIPアドレスを追加します。 127.0.0.1の後にコンマを含めないでください。

/etc/redis/redis.conf
. . .
bind 127.0.0.1 source_server_IP
. . .

次に、まだ行っていない場合は、requirepassディレクティブを使用して、ユーザーがソースインスタンスのデータを操作する前に入力する必要のあるパスワードを構成します。 これを行うには、ディレクティブのコメントを解除し、複雑なパスワードまたはパスフレーズに設定します。

/etc/redis/redis.conf
. . .
requirepass source_redis_password
. . .

ここで設定したパスワードは、ターゲットサーバーを構成するときに必要になるため、必ずメモしてください。

その変更に続いて、Redis構成ファイルを保存して閉じることができます。 nanoで編集した場合は、CTRL+XYENTERの順に押して編集してください。

次に、Redisサービスを再起動して、次の変更を有効にします。

  1. sudo systemctl restart redis

Redisの構成に関して行う必要があるのはこれだけですが、サーバーにファイアウォールを構成した場合は、ターゲットサーバーがソースに接続しようとする試みを引き続きブロックします。 ファイアウォールをufwで構成したとすると、次のコマンドを使用して、Redisが実行されているポートへの接続を許可するようにファイアウォールを更新できます。 Redisは、デフォルトでポート6379を使用するように構成されていることに注意してください。

  1. sudo ufw allow 6379

最終的な変更を行った後、ソースRedisサーバーの構成はすべて完了です。 ソースのレプリカとして機能するようにターゲットRedisインスタンスを構成し続けます。

ステップ4—ターゲットRedisインスタンスを設定する

この時点で、外部接続を受け入れるようにソースRedisインスタンスを構成しました。 ただし、requirepassディレクティブのコメントを解除してソースへのアクセスをロックダウンしているため、ターゲットインスタンスはソースに保持されているデータを複製できません。 ここでは、ソースへの接続を認証できるようにターゲットRedisインスタンスを構成し、それによってレプリケーションを許可します。

root以外のユーザーとしてターゲットのRedisサーバーに接続することから始めます。

  1. ssh sammy@target_server_ip

次に、ターゲットサーバーのRedis構成ファイルを開きます。

  1. sudo nano /etc/redis/redis.conf

まだ行っていない場合は、requirepassディレクティブを使用してターゲットRedisインスタンスのパスワードを構成する必要があります。

/etc/redis/redis.conf
. . .
requirepass target_redis_password
. . .

次に、masterauthディレクティブのコメントを解除し、ソースRedisインスタンスの認証パスワードに設定します。 これにより、レプリケーションを有効にした後、ターゲットサーバーがソースインスタンスに対して認証できるようになります。

/etc/redis/redis.conf
. . .
masterauth source_redis_password
. . .

最後に、ソースインスタンスに情報を書き込むクライアントがある場合は、ターゲットインスタンスにもデータを書き込むようにクライアントを構成する必要があります。 このように、ターゲットをプライマリインスタンスにプロモートした後にクライアントがデータを書き込んだ場合でも、データが失われることはありません。

ただし、これを行うには、replica-read-onlyディレクティブを調整する必要があります。 これはデフォルトでyesに設定されています。これは、クライアントが書き込みできない「読み取り専用」レプリカになるように構成されていることを意味します。 このディレクティブをnoに設定して、クライアントがそれに書き込むことができるようにします。

/etc/redis/redis.conf
. . .
replica-read-only no
. . .

これらは、ターゲットの構成ファイルに加える必要のあるすべての変更であるため、保存して閉じることができます。

次に、Redisサービスを再起動して、次の変更を有効にします。

  1. sudo systemctl restart redis

Redisサービスを再起動すると、ターゲットサーバーがソースのレプリカになる準備が整います。 これを1つに変換するために必要なのは、1つのコマンドを実行することだけです。これについては、後ほど説明します。

注:ソースRedisインスタンスにデータを書き込むクライアントがある場合は、ターゲットにもデータを書き込むようにクライアントを構成するのがよいでしょう。

ステップ5—レプリケーションの開始と検証

この時点で、ターゲットサーバーからの接続を受け入れるようにソースRedisインスタンスを構成し、レプリカとしてソースに対して認証できるようにターゲットRedisインスタンスを構成しました。 これらの要素を配置すると、ターゲットインスタンスをソースのレプリカに変える準備が整います。

ターゲットのRedisサーバーでRedisコマンドラインインターフェイスを開くことから始めます。

  1. redis-cli

authコマンドを実行して、接続を認証します。

  1. auth password

次に、replicaofコマンドを使用して、ターゲットインスタンスをソースのレプリカに変換します。 source_server_ipをソースインスタンスのパブリックIPアドレスに、source_portをソースインスタンスのRedisが使用するポートに必ず置き換えてください。

  1. replicaof source_server_ip source_port

プロンプトから、次のscanコマンドを実行します。 これにより、レプリカが現在保持しているすべてのキーが返されます。

  1. scan 0

レプリケーションが期待どおりに機能している場合は、レプリカに保持されているソースインスタンスのすべてのキーが表示されます。 手順1でサンプルデータをソースにロードした場合、scanコマンドの出力は次のようになります。

Output
1) "0" 2) 1) "string3" 2) "string1" 3) "set1" 4) "string2" 5) "hash1" 6) "list1"

注:このコマンドは、この例に示されているものとは異なる順序でキーを返す場合があることに注意してください。

ただし、このコマンドがソースRedisインスタンスで保持されているものと同じキーを返さない場合は、サーバーの構成ファイルの1つにエラーがあり、ターゲットデータベースがソースに接続できない可能性があります。 この場合、ターゲットRedisインスタンスへの接続を閉じ、ソースサーバーとターゲットRedisサーバーの両方で構成ファイルが正しく編集されていることを再確認してください。

接続を開いている間、期限切れに設定したキーがまだ揮発性であることを確認することもできます。 これを行うには、引数として次のキーの1つを指定してttlコマンドを実行します。

  1. ttl hash1

これにより、このキーが削除されるまでの秒数が返されます。

Output
5430

ソースインスタンスのデータがターゲットに正しく同期されたことを確認したら、replicaofコマンドをもう一度実行して、ターゲットをプライマリインスタンスに昇格させることができます。 ただし、今回はreplicaofの後にIPアドレスとポートを付けるのではなく、no oneの後に続けます。 これにより、ターゲットインスタンスはソースとの同期をすぐに停止します。

  1. replicaof no one

ソースから複製されたデータがターゲットに保持されていることを確認するには、前に入力したscanコマンドを再実行します。

scan 0

このコマンドの出力には、ターゲットがまだソースを複製しているときにscanコマンドを実行したときと同じキーが表示されるはずです。

Output
1) "0" 2) 1) "string3" 2) "string1" 3) "set1" 4) "string2" 5) "hash1" 6) "list1"

これで、すべてのデータをソースRedisインスタンスからターゲットに正常に移行できました。 ソースインスタンスにまだデータを書き込んでいるクライアントがある場合は、ターゲットにのみ書き込むようにクライアントを構成するのがよいでしょう。

結論

レプリケーション以外にも、あるRedisインスタンスから別のインスタンスにデータを移行するために使用できる方法はいくつかありますが、レプリケーションには、動作に必要な構成変更が比較的少なく、開始または停止するコマンドが1つだけであるという利点があります。

Redisの操作について詳しく知りたい場合は、Redisデータベースの管理方法に関するチュートリアルシリーズを確認することをお勧めします。 また、RedisデータをDigitalOceanが管理するRedisインスタンスに移動する場合は、ガイドに従ってください