Envoy: Redis

# tldr
勉強がてらにEnvoyのドキュメントを邦訳してみました。ベースはGoogle Translateで、ところどころ不自然な箇所を直しています。

原文としたのEnvoyのドキュメントは[こちらのディレクトリ以下](https://github.com/envoyproxy/envoy/tree/master/docs)にあります（ライセンス：[Apache License 2.0](https://github.com/envoyproxy/envoy/blob/master/LICENSE), [NOTICE](https://github.com/envoyproxy/envoy/blob/master/NOTICE)）。

目次は[こちら](https://qiita.com/kentakozuka/items/27cc937fba4c18b226d0)です。



## Redis

EnvoyはRedisプロキシとして機能し、クラスタ内のインスタンス間でコマンドを分割できます。このモードでは、Envoyの目的は、可用性とパーティションの許容度を一貫性の上に維持することです。これが、EnvoyとRedis Clusterを比較する際の重要なポイントです。 Envoyはベストエフォートキャッシュとして設計されています。つまり、矛盾するデータを調整したり、グローバルに一貫したクラスタメンバーシップの見方を維持したりすることはありません。また、アクセスパターン、削除、または分離の要件に基づいて、さまざまなワークロードからさまざまなアップストリームクラスターへのコマンドのルーティングをサポートします。

RedisプロジェクトはRedisに関連しているので、パーティション分割に関する詳細なリファレンスを提供します。 「パーティショニング：複数のRedisインスタンス間でデータを分割する方法」を参照してください。

エンボイレディスの特徴：

- Redisプロトコルコーデック。
- ハッシュベースのパーティショニング
- ケタマ分布
- 詳細なコマンド統計
- アクティブおよびパッシブヘルスチェック
- ハッシュタグ付け。
- プレフィックスルーティング

計画されている将来の機能強化：

- 追加のタイミング統計
- 回路遮断
- 断片化されたコマンドに対して折りたたみを要求します。
- レプリケーション
- 組み込み再試行
- トレース

設定

フィルタ設定の詳細については、Redisプロキシフィルタ設定のリファレンスを参照してください。

対応するクラスタ定義は、リングハッシュロードバランシングを使用して設定する必要があります。

アクティブヘルスチェックが必要な場合は、Redisヘルスチェッカーとして設定されたカスタムヘルスチェックを使用してクラスタを設定する必要があります。

パッシブヘルスチェックが必要な場合は、外れ値検出も設定します。

パッシブヘルスチェックの目的で、接続タイムアウト、コマンドタイムアウト、および接続クローズは5xxにマップされます。 Redisからの他のすべての応答は成功としてカウントされます。

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

プロトコルレベルでは、パイプラインがサポートされています。 MULTI（トランザクションブロック）ではありません。最高のパフォーマンスを得るために、可能な限りパイプライン化を使用してください。

コマンドレベルでは、Envoyはサーバーに確実にハッシュできるコマンドのみをサポートします。 PINGは唯一の例外であり、EnvoyがPONGで即座に応答します。 PINGへの引数は許可されていません。他のすべてのサポートされているコマンドはキーを含まなければなりません。サポートされているコマンドは、おそらく失敗のシナリオを除いて、元のRedisコマンドと機能的に同じです。

各コマンドの使用方法の詳細については、公式のRedisコマンドリファレンスを参照してください。
コマンドグループ
ping接続
DELジェネリック
ダンプジェネリック
既存ジェネリック
EXPIREジェネリック
EXPIREATジェネリック
PERSISTジェネリック
PEXPIREジェネリック
PEXPIREATジェネリック
PTTLジェネリック
RESTOREジェネリック
タッチジェネリック
TTLジェネリック
タイプ総称
UNLINKジェネリック
GEOADDジオ
GEODISTジオ
GEOHASHジオ
GEOPOSジオ
GEORADIUS_ROジオ
GEORADIUSBYMEMBER_ROジオ
HDELハッシュ
HEXISTSハッシュ
HGETハッシュ
HGETALLハッシュ
HINCRBYハッシュ
HINCRBYFLOATハッシュ
HKEYSハッシュ
HLENハッシュ
HMGETハッシュ
HMSETハッシュ
HSCANハッシュ
HSETハッシュ
HSETNXハッシュ
HSTRLENハッシュ
HVALSハッシュ
LINDEXリスト
LINSERTリスト
LLENリスト
LPOPリスト
LPUSHリスト
LPUSHXリスト
LRANGEリスト
LREMリスト
LSETリスト
LTRIMリスト
RPOPリスト
RPUSHリスト
RPUSHXリスト
EVALスクリプティング
EVALSHAスクリプティング
SADDセット
SCARDセット
SISMEMBERセット
SMEMBERSセット
SPOPセット
SRANDMEMBERセット
SREMセット
SSCANセット
ZADDソートセット
ZCARDソートセット
ZCOUNTソートセット
ZINCRBYソートセット
ZLEXCOUNTソートセット
ZRANGEソートセット
ZRANGEBYLEXソートセット
ZRANGEBYSCOREソートセット
ZRANKソートセット
ZREMソートセット
ZREMRANGEBYLEXソートセット
ZREMRANGEBYRANKソートセット
ZREMRANGEBYSCOREソートセット
ZREVRANGEソートセット
ZREVRANGEBYLEXソートセット
ZREVRANGEBYSCOREソートセット
ZREVRANKソートセット
ZPOPMINソートセット
ZPOPMAXソートセット
ZSCANソートセット
ZSCOREソートセット
APPEND文字列
BITCOUNT文字列
BITFIELD文字列
BITPOS文字列
DECR文字列
DECRBY文字列
GET文字列
GETBIT文字列
GETRANGE文字列
GETSET文字列
INCR文字列
INCRBY文字列
INCRBYFLOATストリング
MGET文字列
MSET文字列
PSETEX文字列
SET文字列
SETBIT文字列
SETEXストリング
SETNX文字列
SETRANGE文字列
STRLEN文字列
故障モード

もしRedisがエラーを投げたら、そのエラーをコマンドへの応答として渡します。 Envoyは、エラーデータ型を含むRedisからの応答を通常の応答として扱い、それを呼び出し元に渡します。

Envoyはクライアントに応じて独自のエラーを生成することもできます。
エラー意味
アップストリームホストがありませんリングハッシュロードバランサーは、キー用に選択されたリング位置に使用可能な正常なホストがありませんでした。
upstream failureバックエンドがタイムアウト期間内に応答しなかったか、または接続を閉じました。
データ型または長さが原因で、コマンドスプリッタの最初のステージでコマンドが拒否されました。
unsupported commandこのコマンドはEnvoyによって認識されなかったため、バックエンドサーバーにハッシュすることができないため、サービスを受けることができません。
応答数（例：DEL）を合計した断片化されたコマンドは、もしあれば、受信したエラーの総数を返します。
アップストリームプロトコルエラー断片化したコマンドが予期しないデータ型を受信したか、またはバックエンドがRedisプロトコルに準拠していない応答で応答しました。
コマンドの引数の数が間違っている特定のコマンドは、引数の数が正しいことをEnvoyにチェックインします。

MGETの場合、取得できない個々のキーごとにエラー応答が生成されます。たとえば、5つのキーを取得し、2つのキーのバックエンドがタイムアウトした場合、値の代わりにそれぞれに対してエラー応答が返されます。

$ redis-cli MGET a b c d e
1） "アルファ"
2）「ブラボー」
3）（エラー）アップストリーム障害
4）（エラー）上流障害
5） "エコー"

# Redisクラスターチュートリアル

この文書はRedis Clusterの入門書です。分散システムの概念を理解するのに複雑なものは使用しません。これは、Redis Cluster仕様でカバーされている詳細に入ることなく、ユーザーの観点からシステムがどのように振る舞うかを説明することなく、クラスターをセットアップし、テストし、そして操作する方法についての指示を提供します。

ただし、このチュートリアルでは、わかりやすい方法で、最終ユーザーの観点からRedis Clusterの可用性と一貫性の特性に関する情報を提供しようとします。

このチュートリアルにはRedisバージョン3.0以降が必要です。

本格的なRedis Cluster展開を実行する予定がある場合は、厳密には必要でなくても、より正式な仕様をお勧めします。ただし、このドキュメントから始めて、しばらくしてからRedis Clusterを使い、あとでこの仕様を読んでおくことをお勧めします。

## Redisクラスター101

Redis Clusterは、データが複数のRedisノードにわたって自動的に分割されるRedisインストールを実行する方法を提供します。

Redis Clusterは、パーティション分割中にある程度の可用性も提供します。つまり、実際には、一部のノードに障害が発生したり通信できなくなった場合でも操作を続行することができます。ただし、大規模な障害が発生すると（たとえば、大多数のマスターが使用できない場合など）、クラスターは動作を停止します。

実際的には、Redis Clusterで何が得られますか？

- データセットを複数のノードに自動的に分割する機能。
- ノードのサブセットに障害が発生しているとき、またはクラスタの他の部分と通信できないときに操作を続行する機能。


## Redis ClusterのTCPポート

すべてのRedis Clusterノードは、2つのTCP接続を開く必要があります。クライアントにサービスを提供するために使用される通常のRedis TCPポート（6379など）と、データポートに10000を加算したポート（この例では16379）。

この2番目の上位ポートはクラスタバス、つまりバイナリプロトコルを使用したノード間通信チャネルに使用されます。クラスタバスは、障害検出、構成の更新、フェイルオーバーの承認などのためにノードによって使用されます。クライアントは決してクラスタバスポートと通信するのではなく、常に通常のRedisコマンドポートと通信しないでください。ただし、ファイアウォールで両方のポートを開くようにしてください。そうしないと、Redisクラスタノードが通信できなくなります。

コマンドポートとクラスタバスポートのオフセットは固定されており、常に10000です。

Redisクラスタが適切に動作するためには、各ノードに必要なことに注意してください。

    通常のクライアント通信ポート（通常6379）は、クライアントと通信して、クラスタに到達する必要があるすべてのクライアント、およびその他のすべてのクラスタノード（キーの移行にクライアントポートを使用する）に対して開かれています。
    クラスタバスポート（クライアントポート+ 10000）は、他のすべてのクラスタノードから到達可能でなければなりません。

両方のTCPポートを開かないと、クラスタは期待通りに動作しません。

クラスタバスは、ノード間のデータ交換に異なるバイナリプロトコルを使用します。これは、帯域幅と処理時間をほとんど使用せずにノード間で情報を交換するのに適しています。

## RedisクラスタとDocker

現在Redis ClusterはNAT環境やIPアドレスやTCPポートが再マッピングされている一般的な環境をサポートしていません。

Dockerはポートマッピングと呼ばれる手法を使用します。Dockerコンテナー内で実行されているプログラムは、プログラムが使用していると思われるものとは異なるポートで公開される可能性があります。これは、同じサーバーで同じポートを使用して複数のコンテナーを同時に実行するのに役立ちます。

DockerをRedis Clusterと互換性のあるものにするためには、Dockerのホストネットワークモードを使用する必要があります。詳細についてはDockerのドキュメントの--net = hostオプションを確認してください。

## Redis Clusterデータ分割

Redis Clusterは、一貫したハッシュを使用しませんが、概念的にはすべてのキーがハッシュスロットと呼ばれるものの一部である、異なる形式の分割を使用します。

Redis Clusterには16384のハッシュスロットがあり、与えられたキーのハッシュスロットが何かを計算するために、私たちは単にキーのモジュロ16384を取ります。

Redisクラスタのすべてのノードがハッシュスロットのサブセットを担当しているので、たとえば、3つのノードを持つクラスタがあるとします。ここで、

    ノードAには、0〜5500のハッシュスロットがあります。
    ノードBには、5501から11000までのハッシュスロットが含まれています。
    ノードCには、11001から16383までのハッシュスロットがあります。

これにより、クラスタ内のノードを簡単に追加および削除できます。たとえば、新しいノードDを追加する場合は、ノードA、B、CからDにハッシュスロットを移動する必要があります。同様に、クラスタからノードAを削除する場合は、Aが提供するハッシュスロットを移動するだけです。ノードAが空になったら、クラスタから完全に削除できます。

あるノードから別のノードにハッシュスロットを移動しても、動作を停止したり、ノードを追加または削除したり、ノードが保持しているハッシュスロットの割合を変更したりする必要はありません。

Redis Clusterは、単一のコマンド実行（またはトランザクション全体、またはLuaスクリプト実行）に関わるすべてのキーがすべて同じハッシュスロットに属する限り、複数のキー操作をサポートします。ユーザーは、ハッシュタグと呼ばれる概念を使用して、複数のキーを同じハッシュスロットの一部にすることができます。

ハッシュタグはRedis Cluster仕様に文書化されていますが、要点は、キー内の{}括弧の間にサブストリングがある場合、そのストリング内にあるものだけがハッシュされるということです。例えばこの{foo}キーと別の{foo} keyは同じハッシュスロット内にあることが保証されており、複数のキーを引数としてコマンド内で一緒に使用できます。

## Redis Clusterマスタースレーブモデル

マスターノードのサブセットに障害が発生した場合や大多数のノードと通信できない場合でも使用可能な状態を維持するために、Redis Clusterはすべてのハッシュスロットが1（マスター自体）からNレプリカ（N）までのマスタースレーブモデルを使用します。 -1追加のスレーブノード）。

ノードA、B、Cを含むこの例のクラスタでは、ノードBに障害が発生した場合、クラスタは続行できません。これは、5501〜11000の範囲のハッシュスロットを処理する方法がなくなったためです。

ただし、クラスタが作成されたとき（または後で）、すべてのマスタにスレーブノードを追加するので、最終クラスタはマスタノードであるA、B、C、およびスレーブノードであるA1、B1、C1で構成されます。ノードBに障害が発生しても、システムは続行できます。

ノードB1がBを複製し、Bが失敗すると、クラスタはノードB1を新しいマスターとして昇格させ、正常に動作し続けます。

ただし、ノードBとB1が同時に故障した場合、Redis Clusterは動作を継続できません。

## Redisクラスタの一貫性保証

Redis Clusterは強い一貫性を保証することができません。実際的には、これは特定の条件下でRedis Clusterがシステムによってクライアントに認識された書き込みを失う可能性があることを意味します。

Redis Clusterが書き込みを失う可能性がある最初の理由は、非同期レプリケーションを使用しているためです。つまり、書き込み中に次のことが起こります。

    あなたのクライアントはマスターBに書き込みます。
    マスターBはあなたのクライアントにOKと答えます。
    マスターBはその書き込みをそのスレーブB1、B2、およびB3に伝搬します。

ご覧のとおり、Bはクライアントに応答する前にB1、B2、B3からの確認応答を待機しません。これはRedisにとって非常に大きな待ち時間のペナルティであるため、クライアントが何かを書き込むとBは書き込みを確認し、クラッシュする前にクラッシュします。書き込みをそのスレーブに送信できれば、書き込みを受信しなかったスレーブの1つをマスターに昇格させて、書き込みを永久に失うことができます。

これは、毎秒データをディスクにフラッシュするように構成されているほとんどのデータベースで発生することと非常によく似ています。したがって、分散システムを含まない従来のデータベースシステムの過去の経験から、すでに考えることができるシナリオです。同様に、クライアントに返信する前にデータベースにディスク上のデータを強制的にフラッシュさせることで一貫性を向上させることができますが、通常これは極端に低いパフォーマンスにつながります。これは、Redisクラスタの場合の同期レプリケーションと同等です。

基本的に、パフォーマンスと一貫性の間にはトレードオフがあります。

Redis Clusterは絶対に必要なときに同期書き込みをサポートし、WAITコマンドで実装されているため、書き込みが失われる可能性ははるかに低くなります。ただし、Redis Clusterは同期レプリケーションを使用しても強い一貫性を実装しません。書き込みを受信できなかったスレーブがマスターとして選出されるという障害シナリオ。

Redis Clusterが書き込みを失う別の注目すべきシナリオがあります。これは、少なくともマスターを含む少数のインスタンスでクライアントが分離されているネットワークパーティション中に発生します。

例として、3つのマスターと3つのスレーブを持つA、B、C、A1、B1、C1で構成される6ノードのクラスターを考えます。 Z1と呼ぶクライアントもあります。

パーティションが作成された後、パーティションの一方の側にA、C、A1、B1、C1があり、もう一方の側にBとZ1がある可能性があります。

Z1はまだBに書き込むことができ、それはその書き込みを受け入れます。パーティションが非常に短時間で修復された場合、クラスタは通常どおり続行されます。ただし、B1がパーティションの多数決側でマスターに昇格するのに十分な時間パーティションが続くと、Z1がBに送信している書き込みは失われます。

Z1がBに送信できる書き込み量には最大ウィンドウがあることに注意してください。パーティションのマジョリティ側がマスターとしてスレーブを選択するのに十分な時間が経過すると、マイノリティ側のすべてのマスターノードが書き込みを受け付けなくなります。 。

この時間はRedis Clusterの非常に重要な設定ディレクティブであり、ノードタイムアウトと呼ばれます。

ノードタイムアウトが経過した後、マスターノードは失敗したと見なされ、そのレプリカの1つに置き換えることができます。同様に、ノードタイムアウトが他のマスターノードの大部分を感知できるようにするためにマスターノードなしで経過した後、それはエラー状態に入りそして書き込みを受け入れるのを止める。


## Redis Cluster設定パラメータ

クラスタの配置例を作成しようとしています。先に進む前に、Redis Clusterがredis.confファイルで導入する設定パラメータを紹介しましょう。いくつかは明白になり、あなたが読み続けるにつれて他のものはより明確になるでしょう。

    cluster-enabled <yes / no>：yesの場合、特定のRedisインスタンスでRedis Clusterサポートが有効になります。それ以外の場合、インスタンスは通常どおりスタンドアロンインスタンスとして起動します。
    cluster-config-file <ファイル名>：このオプションの名前にかかわらず、これはユーザーが編集可能な設定ファイルではありませんが、Redis Clusterノードが存在するたびにクラスター設定（基本的には状態）を自動的に保持するファイルです。起動時に再読み込みできるようにするための変更。このファイルには、クラスタ内の他のノード、その状態、永続変数などの情報がリストされます。多くの場合、このファイルは何らかのメッセージ受信の結果として書き換えられ、ディスク上にフラッシュされます。
    cluster-node-timeout <ミリ秒>：Redis Clusterノードが失敗したと見なされずに使用不可になることができる最大時間。マスターノードが指定された時間を超えて到達できない場合、そのスレーブによってフェイルオーバーされます。このパラメータはRedis Clusterの他の重要なことを制御します。特に、指定された時間内に大多数のマスターノードにアクセスできないすべてのノードは、クエリの受け入れを停止します。
    cluster-slave-validity-factor <factor>：ゼロに設定されている場合、マスターとスレーブ間のリンクが切断されたままであっても、スレーブは常にマスターのフェイルオーバーを試みます。値が正の場合、最大切断時間はノードのタイムアウト値にこのオプションで提供される係数を掛けた値として計算されます。ノードがスレーブの場合、マスターリンクが切断されてもフェイルオーバーを開始しようとしません。指定された時間よりも長い。たとえば、ノードのタイムアウトが5秒に設定され、妥当性係数が10に設定されている場合、50秒を超えてマスターから切断されたスレーブはそのマスターのフェイルオーバーを試行しません。 0以外の値を設定すると、フェイルオーバー可能なスレーブがない場合、マスターの障害後にRedis Clusterが使用できなくなる可能性があります。その場合、クラスタは元のマスターがクラスタに再参加したときにのみ使用可能に戻ります。
    cluster-migration-barrier <count>：他のスレーブがどのスレーブでもカバーされなくなったマスターに移行するために、マスターが接続したままになるスレーブの最小数。詳細については、このチュートリアルのレプリカの移行に関する適切なセクションを参照してください。
    cluster-require-full-coverage <yes / no>：これがyesに設定されている場合（デフォルト）、キースペースの一部の割合がどのノードでもカバーされていないと、クラスターは書き込みの受け入れを停止します。このオプションがnoに設定されていると、キーのサブセットに関する要求しか処理できない場合でも、クラスターは引き続きクエリーを処理します。
    
    

## Redisクラスターの作成と使用

注：Redis Clusterを手動でデプロイするには、その運用上の特定の側面を学ぶことが非常に重要です。ただし、できるだけ早くクラスタを起動してできるだけ早く（できるだけ早く）実行する場合は、このセクションと次のセクションをスキップし、create-clusterスクリプトを使用してRedisクラスタを直接作成するに進んでください。

クラスタを作成するには、まず空のRedisインスタンスをいくつかクラスタモードで実行する必要があります。これは基本的に、Redisインスタンスがクラスタ固有の機能とコマンドを有効にするように特別なモードを設定する必要があるため、通常のRedisインスタンスを使用してクラスタを作成しないことを意味します。

以下は、最小のRedisクラスタ設定ファイルです。

ポート7000
クラスタ対応
クラスタ構成ファイルnodes.conf
クラスタノードタイムアウト5000
付録はい

ご覧のとおり、クラスタモードを有効にするものは、単にcluster-enabledディレクティブです。すべてのインスタンスには、このノードの設定が保存されているファイルのパスも含まれています。デフォルトでは、このファイルはnodes.confです。このファイルは人間が触れることはありません。起動時にRedis Clusterインスタンスによって生成され、必要になるたびに更新されます。

期待通りに動作する最小のクラスタには、少なくとも3つのマスターノードが含まれている必要があります。最初のテストでは、3つのマスターと3つのスレーブで6ノードクラスタを起動することを強くお勧めします。

これを行うには、新しいディレクトリを入力して、任意のディレクトリ内で実行するインスタンスのポート番号にちなんで名付けられた次のディレクトリを作成します。

何かのようなもの：

mkdirクラスターテスト
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005

各ディレクトリ内に、7000から7005までのredis.confファイルを作成します。設定ファイルのテンプレートとして、上記の小さな例を使用してください。ただし、ディレクトリ名に従って、ポート番号7000を正しいポート番号に置き換えてください。 。

GitHubの不安定版ブランチにある最新のソースからコンパイルしたredis-server実行可能ファイルをcluster-testディレクトリにコピーし、最後にお気に入りのターミナルアプリケーションで6つのターミナルタブを開きます。

このようにすべてのインスタンスを起動します。タブごとに1つずつです。

CD 7000
../redis-server ./redis.conf

すべてのインスタンスのログからわかるように、nodes.confファイルが存在しなかったため、すべてのノードが新しいIDを割り当てます。

[82462] 26 Nov 11：56：55.329 *クラスタ構成が見つかりません、私は97a3a64667477371c4479320d683e4c8db5858b1です

このIDは、インスタンスがクラスタのコンテキスト内で一意の名前を持つようにするために、この特定のインスタンスによって永久に使用されます。すべてのノードは、IPやポートではなく、このIDを使用して他のすべてのノードを記憶します。 IPアドレスとポートは変更される可能性がありますが、一意のノード識別子はノードの存続期間中決して変更されません。この識別子を単にノードIDと呼びます。



クラスタを作成する

多数のインスタンスが実行されているので、意味のある構成をノードに書き込んでクラスターを作成する必要があります。

Redis 5を使用している場合は、redis-cliに組み込まれているRedis Clusterコマンドラインユーティリティを使用して新しいクラスタを作成したり、既存のクラスタを確認したり、再構築したりすることができます。

Redisバージョン3または4には、非常によく似たredis-trib.rbという古いツールがあります。これはRedisソースコード配布のsrcディレクトリにあります。 redis-tribを実行するにはredis gemをインストールする必要があります。

宝石インストールredis

最初の例、つまりクラスターの作成は、Redis 5ではredis-cli、Redis 3および4ではredis-tribの両方を使用して表示されます。ただし、次の例では、redis-cliのみを使用します。構文は非常によく似ているので、redis-trib.rb helpを使用して古い構文に関する情報を取得することで、コマンドラインを簡単に変更できます。重要：必要に応じて、問題なくRedis 4クラスターに対してRedis 5 redis-cliを使用できます。

redis-cliを使用してRedis 5用のクラスターを作成するには、単純に次のように入力します。

redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
- クラスターレプリカ1

Redis 4または3にredis-trib.rbを使用するには、次のように入力します。

./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

新しいクラスタを作成したいので、ここで使用するコマンドはcreateです。オプション--cluster-replicas 1は、作成されたすべてのマスターに対してスレーブが必要であることを意味します。他の引数は、新しいクラスタを作成するために使用したいインスタンスのアドレスのリストです。

明らかに、私たちの要件を満たす唯一のセットアップは、3つのマスターと3つのスレーブを持つクラスターを作成することです。

Redis-cliはあなたに設定を提案します。 yesと入力して、提案された構成を受け入れます。クラスタが構成され、結合されます。つまり、インスタンスは互いに対話するためにブートストラップされます。最後に、すべてがうまくいった場合は、次のようなメッセージが表示されます。

[OK]全16384スロットをカバー

これは、利用可能な16384のスロットのそれぞれにサービスを提供するマスターインスタンスが少なくともあることを意味します。
create-clusterスクリプトを使用してRedisクラスターを作成する

上で説明したように個々のインスタンスを手動で設定して実行してRedisクラスタを作成したくない場合は、はるかに単純なシステムがあります（ただし、同じ量の操作上の詳細については習得できません）。

Redisディストリビューションのutils / create-clusterディレクトリをチェックするだけです。内部にcreate-clusterというスクリプトが含まれています（それが含まれているディレクトリと同じ名前です）。これは単純なbashスクリプトです。 3つのマスターと3つのスレーブで6ノードのクラスターを起動するには、次のコマンドを入力します。

    クラスタ作成開始
    create-cluster create

redis-cliユーティリティでクラスタレイアウトを受け入れたい場合は、手順2で「yes」と答えてください。

これでクラスタと対話できるようになりました。最初のノードはデフォルトでポート30001で起動します。完了したら、次のようにしてクラスタを停止します。

    create-clusterを停止します。

スクリプトの実行方法の詳細については、このディレクトリ内のREADMEを読んでください。


クラスターで遊ぶ

この段階でのRedis Clusterの問題の1つは、クライアントライブラリの実装の欠如です。

私は以下の実装を知っています。

    redis-rb-clusterは、他の言語への参照として私（@antirez）によって書かれたRubyの実装です。これは元のredis-rbを簡単にラップしたもので、クラスタと効率的に対話するための最小限のセマンティクスを実装しています。
    redis-py-cluster Pythonへのredis-rb-clusterの移植。ほとんどのredis-py機能をサポートします。活発に開発中です。
    人気のあるPredisがRedis Clusterをサポートしています。このサポートは最近更新され、現在開発中です。
    最もよく使われているJavaクライアント、Jedisは最近Redis Clusterのサポートを追加しました。プロジェクトREADMEのJedis Clusterセクションを見てください。
    StackExchange.RedisはC＃のサポートを提供します（そしてほとんどの.NET言語で正常に動作するはずです; VB、F＃など）。
    thunk-redisはNode.jsとio.jsのサポートを提供します。これはパイプライン処理とクラスタを備えたさんく/約束ベースのredisクライアントです。
    redis-go-clusterは、Redigoライブラリクライアントをベースクライアントとして使用するGo言語用のRedis Clusterの実装です。結果集約によってMGET / MSETを実装します。
    GitHubのRedisリポジトリの不安定版ブランチにあるredis-cliユーティリティは、-cスイッチを付けて起動すると、非常に基本的なクラスタサポートを実装します。

Redis Clusterをテストする簡単な方法は、上記のクライアントのいずれかを試すか、単にredis-cliコマンドラインユーティリティを使うことです。以下は後者を使用した対話の例です。

$ redis-cli -c -p 7000
redis 127.0.0.1:7000> fooバーを設定
- > 127.0.0.1:7002にあるスロット[12182]にリダイレクト
OK
redis 127.0.0.1:7002>こんにちは世界を設定
- > 127.0.0.1:7000にあるスロット[866]にリダイレクトされました
OK
redis 127.0.0.1:7000> fooを入手
- > 127.0.0.1:7002にあるスロット[12182]にリダイレクト
"バー"
redis 127.0.0.1:7000>こんにちは
- > 127.0.0.1:7000にあるスロット[866]にリダイレクトされました
"世界"

注：スクリプトを使用してクラスターを作成した場合、ノードはデフォルトで30001から始まるさまざまなポートをlistenすることがあります。

redis-cliクラスターのサポートは非​​常に基本的なので、Redisクラスターノードがクライアントを正しいノードにリダイレクトできるという事実を常に使用します。真面目なクライアントはそれ以上のことをし、ハッシュスロットとノードアドレス間のマップをキャッシュして正しいノードへの正しい接続を直接使うことができます。フェールオーバー後やシステム管理者がノードを追加または削除してクラスタレイアウトを変更した後など、クラスタ構成内で何かが変更された場合にのみマップが更新されます。
redis-rb-clusterを使ってサンプルアプリを書く

Redis Clusterの操作方法を説明する前に、フェイルオーバーやリシャーディングなどのことを行う前に、何らかのサンプルアプリケーションを作成するか、少なくとも単純なRedis Clusterクライアント対話のセマンティクスを理解できるようにする必要があります。

このようにして、例を実行しながら、同時にノードが失敗するようにしたり、再分散を開始したりして、Redis Clusterが実際の状況下でどのように動作するかを確認できます。誰もクラスタに書き込んでいない間に何が起こるかを見ることはあまり役に立ちません。

このセクションでは、2つの例を示したredis-rb-clusterの基本的な使用法について説明します。最初のものは以下であり、redis-rb-cluster配布物内のexample.rbファイルです。

   1 './cluster'が必要です
   2
   ARGV.length！= 2の場合は3
   4 startup_nodes = [
   5 {：host => "127.0.0.1"、：port => 7000}、
   6 {：ホスト=> "127.0.0.1"、ポート=> 7001}
   7 ]
   その他8
   9 startup_nodes = [
  10 {：ホスト=> ARGV [0]、：ポート=> ARGV [1] .to_i}
  11]
  12終了
  13年
  14 rc = RedisCluster.new（startup_nodes、32、：timeout => 0.1）
  15年
  最後の16 =偽
  17年
  最後ではありませんが18
  19はじまる
  20 last = rc.get（ "__ last__"）
  21 last = 0の場合、0
  22救助=> e
  23「エラー＃{e.to_s}」が表示されます
  24眠り1
  25終了
  26終了
  27年
  28（（last.to_i + 1）.. 1000000000）.each {| x |
  29開始
  30 rc.set（ "foo＃{x}"、x）
  31 rc.getを入れます（ "foo＃{x}"）
  32 rc.set（ "__ last __"、x）
  33救助=> e
  34 "エラー＃{e.to_s}"が記録されています
  35終了
  36眠り0.1
  37}
  
  
アプリケーションは非常に単純なことをします、それは次々にfoo <number>の形のキーをnumberに設定します。したがって、プログラムを実行すると、結果は次の一連のコマンドになります。

    SET foo0 0
    SET foo1 1
    SET foo2 2
    などなど

プログラムは、例外で終了するのではなく画面にエラーを表示するように設計されているため、通常よりも複雑に見えます。そのため、クラスタで実行されるすべての操作はbegin rescueブロックによってラップされます。

14行目はプログラムの最初の興味深い行です。起動ノードのリスト、このオブジェクトが異なるノードに対して許容される最大接続数を引数として使用してRedis Clusterオブジェクトを作成し、最後に、特定の操作後のタイムアウトが失敗したと見なされます。

起動ノードは、クラスタのすべてのノードである必要はありません。重要なことは、少なくとも1つのノードに到達できるということです。また、redis-rb-clusterは最初のノードに接続できるようになるとすぐに、この起動ノードのリストを更新します。あなたは他のどんな深刻なクライアントでもそのようなふるまいを予想するべきです。

これで、Redis Clusterオブジェクトインスタンスがrc変数に格納されたので、通常のRedisオブジェクトインスタンスであるかのように、オブジェクトを使用する準備が整いました。

これはまさに18行目から26行目で起こることです。例を再起動するとき、foo0から始めたくないので、カウンタをRedis自体の中に格納します。上記のコードは、このカウンタを読み取るように、またはカウンタが存在しない場合は値0を割り当てるように設計されています。

ただし、クラスタが停止してエラーが返されている場合でも繰り返し試行したいので、これがwhileループであることに注意してください。通常のアプリケーションはそれほど注意する必要はありません。

28から37行目では、キーが設定されているかエラーが表示されているメインループが開始されます。

ループ終了時のスリープコールに注意してください。テストでは、クラスタにできるだけ速く書き込む必要がある場合はスリープを解除できます（もちろんこれは実際の並列処理を行わずにビジーなループになるため、通常は10k ops /秒になります）。条件のベスト）。

通常、サンプルアプリケーションを人間が理解しやすいように、書き込みは遅くなります。

アプリケーションを起動すると、次の出力が生成されます。

ruby ./example.rb
1
2
3
4
5
6
7
8
9
^ C（私はここでプログラムを止めました）

これはあまりおもしろいプログラムではないので、すぐにもっと良いものを使うつもりですが、プログラムが実行されているときにリチャージ中に何が起きるのかはすでにわかりました。


クラスターを再充電する

これで、クラスタの再分散を試す準備が整いました。これを行うには、example.rbプログラムを実行したままにして、プログラムの実行に何らかの影響があるかどうかを確認してください。また、リシャーディング中にもっと深刻な書き込み負荷がかかるようにするために、スリープコールをコメントすることをお勧めします。

再設定とは、基本的にハッシュスロットをノードのセットから別のノードのセットに移動することを意味します。クラスタの作成と同様に、redis-cliユーティリティを使用してこれを行います。

再入金を開始するには、次のように入力します

redis-cli --cluster reshard 127.0.0.1:7000

単一のノードを指定するだけで、redis-cliは他のノードを自動的に見つけます。

現時点ではredis-cliは管理者サポートで再分類することしかできません。ただ、このノードから別のノードに5％のスロットを移動すると言うことはできません（ただし、実装するのは簡単です）。それでそれは質問から始まります。 1つ目は、どのくらいの規模の変更を希望するかです。

スロットをいくつ移動しますか（1から16384）。

例がまだスリープコールなしで実行されている場合は、1000個のハッシュスロットを再構成することを試みることができます。

次に、redis-cliは、再分割の対象、つまりハッシュスロットを受け取るノードは何かを知る必要があります。最初のマスターノード、つまり127.0.0.1:7000を使用しますが、インスタンスのノードIDを指定する必要があります。これはすでにredis-cliによってリストに表示されていましたが、必要ならば次のコマンドでノードのIDを見つけることができます。

$ redis-cli -p 7000のクラスターノード|自分をグレップ
97a3a64667477371c4479320d683e4c8db5858b1：0自分自身、マスター - 0 0 0接続しています0-5460

わかりましたので、私のターゲットノードは97a3a64667477371c4479320d683e4c8db5858b1です。

どのノードからこれらのキーを取得したいのかを尋ねられます。他のすべてのマスターノードから少しハッシュスロットを取得するために、allと入力します。

最後の確認が終わると、redis-cliがノードから別のノードに移動しようとしているスロットごとにメッセージが表示され、実際のキーが一方から他方に移動するたびにドットが印刷されます。

リシャーディングが進行中の間、あなたはあなたのサンプルプログラムが動いているのを影響されないで見ることができるはずです。必要に応じて、再請求中に何度も停止して再起動できます。

再分割が終了したら、次のコマンドでクラスタの状態をテストできます。

redis-cli --cluster check 127.0.0.1:7000

すべてのスロットは通常どおりカバーされますが、今回は127.0.0.1:7000のマスターにはさらに多くのハッシュスロットがあります（6461前後）。
リシャーディング操作のスクリプティング

対話的な方法で手動でパラメータを入力する必要なしに、再変更は自動的に実行されることができます。これは、次のようなコマンドラインを使用して可能です。

redis-cli reshard <host>：<port> --cluster-from <node-id> --cluster-to <node-id> --cluster-slots <スロット数> --cluster-yes

頻繁に再設定する可能性がある場合は、これによってある程度の自動化が可能になりますが、現時点ではredis-cliが自動的にクラスタのバランスを調整し、必要に応じてスロットをインテリジェントに移動することはできません。この機能は将来追加される予定です。


もっと面白いサンプルアプリケーション

先ほど書いたサンプルアプリケーションはあまり良くありません。書き込まれた内容が正しいかどうかを確認することなく、簡単な方法でクラスタに書き込みます。

私たちの見地からは、書き込みを受けているクラスターは、キーfooをすべての操作に対して常に42に書き込むことができますが、まったく気付かないでしょう。

そのため、redis-rb-clusterリポジトリには、consistency-test.rbと呼ばれるもっと興味深いアプリケーションがあります。デフォルトでは1000個のカウンタセットを使用し、カウンタをインクリメントするためにINCRコマンドを送信します。

しかし、単に書くのではなく、アプリケーションはさらに2つのことを行います。

    INCRを使用してカウンタが更新されると、アプリケーションは書き込みを記憶します。
    また、書き込みのたびにランダムカウンタを読み取り、値が予想した値であるかどうかを確認し、メモリ内の値と比較します。

これが意味することは、このアプリケーションは単純な一貫性チェッカーであり、クラスタが書き込みを失ったかどうか、または確認応答を受け取らなかった書き込みを受け入れたかどうかを判断できることです。最初のケースでは、私たちが覚えているものよりも小さい値を持つカウンターが表示されますが、2番目のケースでは値が大きくなります。

一貫性テストアプリケーションを実行すると、毎秒1行の出力が生成されます。

$ ruby​​ consistency-test.rb
925 R（0エラー）| 925 W（0エラー）|
5030 R（0エラー）| 5030 W（0エラー）|
9261 R（0エラー）| 9261 W（0エラー）|
13517 R（0エラー）| 13517 W（0エラー）|
17780 R（0エラー）| 17780 W（0エラー）|
22025 R（0エラー）| 22025 W（0エラー）|
25818 R（0エラー）| 25818 W（0エラー）|

この行は、実行された読み取りと書き込みの数、およびエラーの数を示しています（システムが使用不可になってからのエラーのために照会は受け入れられませんでした）。

何らかの矛盾が見つかった場合は、新しい行が出力に追加されます。これは、たとえばプログラムの実行中にカウンタを手動でリセットした場合に発生します。

$ redis-cli -h 127.0.0.1 -p 7000 set key_217 0
OK

（他のタブで私が見る...）

94774 R（0エラー）| 94774 W（0エラー）|
98821 R（0エラー）| 98821 W（0エラー）|
102886 R（0エラー）| 102886 W（0エラー）| 114失った
107046 R（0エラー）| 107046 W（0エラー）| 114失った

カウンターを0に設定した場合、実際の値は114でした。そのため、プログラムは114個の失われた書き込み（クラスターによって記憶されていないINCRコマンド）を報告します。

このプログラムはテストケースとしてはるかに興味深いので、Redis Clusterフェイルオーバーをテストするために使用します。


フェイルオーバーのテスト

注：このテスト中は、一貫性テストアプリケーションを実行した状態でタブを開いてください。

フェイルオーバーを引き起こすために、私たちができる最も簡単なこと（それはまた、分散システムで発生する可能性がある意味的に最も単純な失敗）は、単一のプロセス、この場合は単一のマスターをクラッシュさせることです。

次のコマンドでクラスタを識別してクラッシュさせることができます。

$ redis-cli -p 7000のクラスターノード| grepマスター
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385482984082 0接続5960-10921
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master - 0 1385482983582 0接続11423-16383
97a3a64667477371c4479320d683e4c8db5858b1：0自分自身、マスター - 0 0 0接続しています0-5959 10922-11422

7000、7001、および7002がマスターです。 DEBUG SEGFAULTコマンドでノード7002をクラッシュさせましょう。

$ redis-cli -p 7002 debug segfault
エラー：サーバーが接続を閉じました

これで、一貫性テストの出力を調べて、報告内容を確認できます。

18849 R（0エラー）| 18849 W（0エラー）|
23151 R（0エラー）| 23151 W（0エラー）|
27302 R（0エラー）| 27302 W（0エラー）|

...多くのエラー警告がここにあります...

29659 R（578エラー）| 29660 W（577エラー）|
33749 R（578エラー）| 33750 W（577エラー）|
37918 R（578エラー）| 37919 W（577エラー）|
42077 R（578エラー）| 42078 W（577エラー）|

フェイルオーバー中にわかるように、システムは578の読み取りと577の書き込みを受け入れることができませんでしたが、データベースに矛盾は発生しませんでした。このチュートリアルの最初の部分で説明したように、Redis Clusterは非同期レプリケーションを使用しているため、フェイルオーバー中に書き込みが失われる可能性があるため、これは予想外のことです。私たちが言っていないのは、Redisがクライアントに返信とスレーブに複製するコマンドをほぼ同時に送信しているため、これが起こる可能性は非常に低いということです。したがって、データを失う非常に小さなウィンドウがあります。しかし、トリガーするのが難しいという事実は、それが不可能であるという意味ではないので、これはRedisクラスターによって提供される一貫性保証を変更しません。

フェイルオーバー後のクラスタ設定を確認できます（その間に、クラッシュしたインスタンスを再起動して、スレーブとしてクラスタに再参加します）。

$ redis-cli -p 7000のクラスタノード
3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004スレーブ3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0接続
a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003スレーブ97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0接続
97a3a64667477371c4479320d683e4c8db5858b1：0自分自身、マスター - 0 0 0接続しています0-5959 10922-11422
3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385503419023 3接続11423-16383
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385503417005 0接続5960-10921
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002スレーブ3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3接続

これで、マスターはポート7000、7001、および7005で実行されています。以前はマスターだったもの、つまりポート7002で実行されているRedisインスタンスは、7005のスレーブになりました。

CLUSTER NODESコマンドの出力は威圧的に見えるかもしれませんが、実際は非常に単純で、以下のトークンで構成されています。

    ノードID
    ip：port
    フラグ：マスター、スレーブ、私自身、失敗、...
    スレーブの場合は、マスターのノードID
    まだ応答を待っている最後の保留中のPINGの時間。
    最後に受信したPONGの時刻
    このノードの設定時期（クラスタの仕様を参照）。
    このノードへのリンクのステータス。
    スロットは提供しました...
    
    

手動フェイルオーバー

マスター上で実際に問題を起こさずにフェイルオーバーを強制することが役に立つ場合があります。たとえば、マスターノードの1つのRedisプロセスをアップグレードするには、可用性への影響を最小限に抑えてそれをスレーブにするためにフェールオーバーすることをお勧めします。

手動フェイルオーバーは、CLUSTER FAILOVERコマンドを使用してRedis Clusterでサポートされます。これは、フェイルオーバーしたいマスターのスレーブの1つで実行する必要があります。

手動フェイルオーバーは特別なものであり、実際のマスタ障害に起因するフェイルオーバーと比較して安全です。なぜなら、システムが確実に新しい場合に限ってクライアントを元のマスタから新しいマスタに切り替えることによって、プロセスにおけるデータ損失を回避するからです。マスターは古いものからのすべての複製ストリームを処理しました。

これは手動フェールオーバーを実行するときスレーブログで見るものです：

＃手動フェイルオーバーユーザーの要求が受け入れられました。
＃一時停止されたマスターの手動フェールオーバーのための受信複製オフセット：347540
＃すべてのマスターレプリケーションストリームが処理され、手動フェイルオーバーが開始されます。
＃選挙の開始が0ミリ秒遅れた（ランク＃0、オフセット347540）。
＃エポック7545のフェールオーバー選挙の開始。
＃フェイルオーバーの選挙で勝利しました。私は新しい主人です。

基本的に、フェイルオーバーしているマスターに接続されているクライアントは停止します。同時に、マスターは自分の複製オフセットをスレーブに送信し、スレーブは自分の側のオフセットに達するのを待ちます。複製オフセットに達すると、フェイルオーバーが開始され、古いマスターに構成切り替えについて通知されます。クライアントが古いマスターでブロック解除されると、クライアントは新しいマスターにリダイレクトされます。
新しいノードを追加する

新しいノードを追加することは基本的に、新しいマスターの場合は空のノードを追加してそこにデータを移動するプロセス、またはスレーブの場合は既知のノードのレプリカとしてセットアップするように指示するプロセスです。

新しいマスターインスタンスを追加することから始めて、両方を示します。

どちらの場合も、実行する最初の手順は空のノードを追加することです。

これは、ポート番号を除いて他のノードに使用されているのと同じ構成で、ポート7006（既存の6つのノードに対して7000から7005まで使用）で新しいノードを開始するのと同じくらい簡単です。前のノードで使用した設定に準拠するために、

    端末アプリケーションに新しいタブを作成します。
    cluster-testディレクトリを入力してください。
    7006という名前のディレクトリを作成します。
    内部にredis.confファイルを作成します。他のノードで使用されているものと同じですが、ポート番号として7006を使用します。
    最後に../redis-server ./redis.confでサーバーを起動します。

この時点でサーバーは稼働しているはずです。

これで、ノードを既存のクラスタに追加するために、通常どおりredis-cliを使用できます。

redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000

ご覧のとおり、最初の引数として新しいノードのアドレスを指定し、2番目の引数としてクラスタ内のランダムに存在するノードのアドレスを指定して、add-nodeコマンドを使用しました。

実用的な意味では、redis-cliはここではほとんど役に立ちませんでした。ノードにCLUSTER MEETメッセージを送信しただけです。これは手動で実行することも可能です。ただし、redis-cliは動作する前にクラスタの状態もチェックするため、内部がどのように機能するかを知っている場合でも、常にredis-cliを介してクラスタ操作を実行することをお勧めします。

これで、新しいノードに接続して、それが実際にクラスタに参加したかどうかを確認できます。

redis 127.0.0.1:7006>クラスタノード
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385543178575 0接続5960-10921
3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004スレーブ3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385543179583 0接続
f093c80dde814da99c5cf72a7dd01590792b783b：0自分自身、マスター - 0 0 0接続しています
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002スレーブ3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543178072 3接続
a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003スレーブ97a3a64667477371c4479320d683e4c8db5858b1 0 1385543178575 0接続
97a3a64667477371c4479320d683e4c8db5858b1 127.0.0.1:7000 master - 0 1385543179080 0接続0-5959 10922-11422
3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385543177568 3接続11423-16383

このノードはすでにクラスタに接続されているので、クライアントクエリをすでに正しくリダイレ​​クトでき、一般的にはクラスタの一部と言えます。ただし、他のマスターと比較して2つの特殊性があります。

    ハッシュスロットが割り当てられていないため、データは保持されません。
    スロットが割り当てられていないマスターであるため、スレーブがマスターになりたい場合は選挙プロセスに参加しません。

これで、redis-cliのリシャーディング機能を使用して、このノードにハッシュスロットを割り当てることが可能になりました。前のセクションですでに説明したように、これを示すことは基本的に無用です。違いはありません。空のノードをターゲットとして持つのは単なる再販です。


レプリカとして新しいノードを追加する

新しいレプリカを追加するには、2つの方法があります。明らかなのは、redis-cliを再度使用することですが、 - cluster-slaveオプションを使用すると、次のようになります。

redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave

ここでのコマンドラインは、新しいマスターを追加するために使用したものとまったく同じであるため、レプリカを追加するマスターを指定することはしていません。この場合、redis-cliは新しいノードを、より少ないレプリカを持つマスターの中からランダムマスターのレプリカとして追加します。

ただし、次のコマンドラインを使用して、新しいレプリカのターゲットにするマスターを正確に指定できます。

redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e

このようにして、新しいレプリカを特定のマスターに割り当てます。

レプリカを特定のマスターに追加するより手動の方法は、新しいノードを空のマスターとして追加してから、CLUSTER REPLICATEコマンドを使用してレプリカにすることです。これは、ノードがスレーブとして追加されたが、それを別のマスターのレプリカとして移動したい場合にも機能します。

たとえば、現在11423-16383の範囲のハッシュスロットを提供していて、ノードIDが3c3a0c74aae0b56170ccb03a76b60cfe7dc1912eであるノード127.0.0.1:7005のレプリカを追加するには、必要な作業はすべて新しいノードに接続することだけです。空のマスターとして追加して）コマンドを送信します。

redis 127.0.0.1:7006>クラスタレプリケート3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e

それでおしまい。これで、このハッシュスロットのセット用の新しいレプリカが作成され、クラスタ内の他のすべてのノードが（それらの設定を更新するのに必要な数秒後に）すでに認識されています。次のコマンドで確認できます。

$ redis-cli -p 7000のクラスターノード| grepスレーブ| grep 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
f093c80dde814da99c5cf72a7dd01590792b783b 127.0.0.1:7006スレーブ3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617702 3接続
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002スレーブ3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617198 3接続

ノード3c3a0c ...には2つのスレーブがあり、ポート7002（既存のもの）と7006（新しいもの）で実行されています。
ノードを削除する

スレーブノードを削除するには、redis-cliのdel-nodeコマンドを使用するだけです。

redis-cli --cluster del-node 127.0.0.1:7000 `<node-id>`

最初の引数は、クラスタ内の単なるランダムノードです。2番目の引数は、削除するノードのIDです。

マスターノードも同様に削除できますが、マスターノードを削除するには、それが空でなければなりません。マスターが空でない場合は、その前にマスターから他のすべてのマスターノードにデータを再構成する必要があります。

マスターノードを削除する別の方法は、そのスレーブの1つを介して手動でフェールオーバーし、新しいマスターのスレーブになった後にノードを削除することです。クラスタ内の実際のマスター数を減らしたい場合は、これは役に立ちません。その場合は、再シャーディングが必要です。


レプリカの移行

Redis Clusterでは、次のコマンドを使用するだけで、いつでも別のマスターと複製するようにスレーブを再設定することができます。

クラスターの複製<master-node-id>

ただし、システム管理者の助けを借りずに、レプリカをあるマスターから別のマスターに自動的に移動するという特別なシナリオがあります。レプリカの自動再構成はレプリカ移行と呼ばれ、Redisクラスターの信頼性を向上させることができます。

注：Redis Cluster Specificationでレプリカの移行の詳細を読むことができます。ここでは、一般的な概念とその恩恵を受けるために何をすべきかについての情報のみを提供します。

特定の条件下でクラスタレプリカをあるマスターから別のマスターに移動させることができるのは、通常、Redisクラスターは特定のマスターに接続されているレプリカの数と同じくらい障害に強いからです。

たとえば、すべてのマスターに1つのレプリカがあるクラスターでは、マスターとそのレプリカが同時に失敗した場合に操作を続行できません。これは、マスターが提供していたハッシュスロットのコピーを保持するインスタンスが他にないためです。しかし、ネットスプリットは同時に多数のノードを分離する可能性がありますが、単一ノードにローカルなハードウェアまたはソフトウェアの障害など、他の多くの種類の障害は、同時に発生する可能性が非常に低いクラスの障害です。したがって、すべてのマスターがスレーブを持つクラスターでは、スレーブは午前4時に殺害され、マスターは午前6時に殺害される可能性があります。これでもクラスターは動作しなくなります。

システムの信頼性を向上させるために、すべてのマスターにレプリカを追加するオプションがありますが、これはコストがかかります。レプリカの移行により、わずか数人のマスターにさらにスレーブを追加できます。したがって、合計20のインスタンスに対して、それぞれ1つのスレーブを持つ10のマスターがあります。ただし、たとえば、いくつかのマスターのスレーブとして3つのインスタンスを追加すると、特定のマスターが複数のスレーブを持つことになります。

レプリカマイグレーションでは、マスターがスレーブなしで残っていると、複数のスレーブを持つマスターからのレプリカが孤立マスターにマイグレーションされます。したがって、上記の例のように、スレーブが午前4時にダウンした後も、別のスレーブが代わりになり、マスターが午前5時に失敗した場合でも、クラスタが継続できるように選択できるスレーブがあります。動作します。

それでは、レプリカの移行について知っておくべきことは何でしょうか。

    クラスターは、特定の瞬間に最大数のレプリカを持つマスターからレプリカを移行しようとします。
    レプリカの移行から恩恵を受けるには、クラスター内の単一のマスターにさらにいくつかのレプリカを追加するだけでよく、どのマスターであってもかまいません。
    cluster-migration-barrierと呼ばれるレプリカ移行機能を制御する設定パラメータがあります。それについての詳細はRedis Clusterに付属のredis.confファイルの例で読むことができます。
    
    

Redisクラスター内のノードのアップグレード

スレーブノードをアップグレードするのは簡単です。ノードを停止してRedisの更新バージョンで再起動するだけでよいからです。スレーブノードを使用して読み取りをスケーリングするクライアントが存在する場合、特定のスレーブノードが利用できない場合、それらは別のスレーブに再接続できるはずです。

マスターのアップグレードはもう少し複雑で、推奨される手順は次のとおりです。

    CLUSTER FAILOVERを使用して、マスターからそのスレーブの1つへの手動フェールオーバーをトリガーします（このドキュメントの「手動フェールオーバー」の項を参照）。
    マスターがスレーブに変わるのを待ちます。
    最後に、スレーブの場合と同じようにノードをアップグレードします。
    マスターをアップグレードしたばかりのノードにしたい場合は、アップグレードしたノードをマスターに戻すために、新しい手動フェールオーバーを起動します。

この手順に従って、すべてのノードがアップグレードされるまで、一方のノードをもう一方のノードから順番にアップグレードする必要があります。
Redisクラスタへの移行

Redis Clusterへの移行を希望するユーザーは、単一のマスターしか持っていない場合もあれば、社内アルゴリズムまたはクライアントライブラリまたはRedisプロキシによって実装されたシャーディングアルゴリズムを使用してキーがNノードに分割される既存のシャーディング設定を使用している場合もあります。

どちらの場合もRedis Clusterに簡単に移行できますが、最も重要なのは、アプリケーションで複数キー操作を使用する場合とその方法です。 3つの異なるケースがあります。

    複数キー操作、トランザクション、または複数キーを含むLuaスクリプトは使用されません。キーは独立してアクセスされます（トランザクションまたは複数のコマンドをグループ化したLuaスクリプトを介して、同じキーについてまとめてアクセスする場合でも）。
    複数のキーを含む複数のキー操作、トランザクション、またはLuaスクリプトが使用されますが、同じハッシュタグを持つキーでのみ使用されます。つまり、一緒に使用されるキーはすべて{...}サブストリングを持ちます。たとえば、次の複数キー操作は、同じハッシュタグのコンテキストで定義されています。SUNION {user：1000} .foo {user：1000} .bar
    複数のキーを含む複数のキー操作、トランザクション、またはLuaスクリプトは、明示的または同じハッシュタグを持たないキー名で使用されます。

3番目のケースはRedis Clusterでは処理されません。アプリケーションは、マルチキー操作を使用しないか、同じハッシュタグのコンテキスト内でのみ使用するために変更する必要があります。

ケース1とケース2がカバーされているので、同じ方法で処理されるこれら2つのケースに焦点を当てます。したがって、ドキュメントでは区別されません。

既存のデータセットがN個のマスターに分割されていると仮定します（既存の分割がない場合はN = 1）。データセットをRedis Clusterに移行するには、次の手順が必要です。

    あなたのクライアントを止めなさい。 Redis Clusterへの自動ライブマイグレーションは現在不可能です。あなたのアプリケーション/環境のコンテキストでライブマイグレーションを調整することができるかもしれません。
    BGREWRITEAOFコマンドを使用して、AOFファイルが完全に生成されるのを待って、N人のマスターすべてに対して追加専用ファイルを生成します。
    AOFファイルをaof-1からaof-Nのどこかに保存します。この時点で、必要に応じて古いインスタンスを停止することができます（仮想化されていない展開では、同じコンピュータを頻繁に再利用する必要があるので便利です）。
    N個のマスターと0個のスレーブで構成されるRedisクラスターを作成します。後で奴隷を追加します。すべてのノードが永続化のために追加専用ファイルを使用していることを確認してください。
    すべてのクラスタノードを停止し、それらの追加専用ファイルを既存の追加専用ファイル（最初のノードにaof-1、2番目のノードにaof-2、最大aof-N）に置き換えます。
    新しいAOFファイルを使用してRedis Clusterノードを再起動します。彼らは彼らの設定に従ってそこにあるべきではないキーがあると文句を言うでしょう。
    各ノードが信頼できるかどうかにかかわらずキーがハッシュスロットに従って移行されるようにクラスタを修正するには、redis-cli --cluster fixコマンドを使用します。
    最後にredis-cli --cluster checkを使用して、クラスタが正常であることを確認します。
    Redis Cluster対応のクライアントライブラリを使用するように変更されたクライアントを再起動します。

外部インスタンスからRedisクラスターにデータをインポートする別の方法があります。これは、redis-cli --cluster importコマンドを使用することです。

このコマンドは、実行中のインスタンスのすべてのキーをソースインスタンスから削除して、指定された既存のRedisクラスターに移動します。ただし、ソースインスタンスとしてRedis 2.8インスタンスを使用する場合、2.8では移行接続キャッシュが実装されていないため操作が遅くなる可能性があるため、このような操作を実行する前にRedis 3.xバージョンでソースインスタンスを再起動することをお勧めします。