MapR DBのテーブルのレプリケーション機能について


本記事ではMapR-DBのテーブルのレプリケーション機能について説明します。
テーブルのレプリケーション機能については既にセカンダリインデックスの作成時に[その一部を紹介](https://qiita.com/bigt23/items/731b0eb0634dc0e6451b)しています。
レプリケーション機能はMapR 6.0.0でリリースされたChange Data Capture(CDC)でも基盤として利用されます。
また、本記事ではテーブルのみですがMapR ES(Stream)のレプリケーションに利用することも出来ますので、扱いに慣れておいたほうがいいでしょう。
ただし、一つの記事ですべての項目を網羅することは難しいので、本記事では概要と簡単な設定例を紹介します。
英語でオーケーな方は本記事には目もくれずに、[このへん](https://maprdocs.mapr.com/60/MapR-DB/ReplicatingMapR-DBTables.html)からどんどん進めてください。

それでは本記事の目次です。

1. [はじめに](https://qiita.com/bigt23/items/c83707f3374deb962381#1-%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
2. [topology](https://qiita.com/bigt23/items/c83707f3374deb962381#2-topology)
3. [gateway](https://qiita.com/bigt23/items/c83707f3374deb962381#3-gateway)
3. [設定例(Master-Slave)](https://qiita.com/bigt23/items/c83707f3374deb962381#4-%E8%A8%AD%E5%AE%9A%E4%BE%8B-master---slave)
4. [設定例(Master-Master)](https://qiita.com/bigt23/items/c83707f3374deb962381#5-%E8%A8%AD%E5%AE%9A%E4%BE%8B-multi-master)

# 1. はじめに

レプリケーション機能は同一クラスタ内のテーブルでも異なるクラスタ内のテーブルでも、どちらにも設定可能となります。
テーブルはレプリケーション先のクラスタで稼働するgatewayプロセスによりバッファされ、レプリケーションされます。

![](https://maprdocs.mapr.com/60/MapROverview/images/gateway-simple.png)

レプリケーションはデフォルトで非同期で実行されますが、同期モードを選択することも出来ます。
同期モードを選択した場合、クライアントアプリケーションによるデータの更新は以下の2つが順番に実施されるまでブロックされます。

1. ソースクラスタのすべてのコンテナでデータが更新されたこと
2. 更新がgatewayにバッファされたこと

レプリケーションのtopologyはMaster-SlaveとMulti-Masterの2つのtopologyに大別されます。
こちらについては[2.topology](https://qiita.com/bigt23/items/c83707f3374deb962381#2-topology)で触れます。

gatewayの設定については[3.gateway](https://qiita.com/bigt23/items/c83707f3374deb962381#3-gateway)で触れます。

レプリケーションで同一キーに書き込まれるデータの順序ですが、サーバに記録された順番が必ずしも守られるわけではありません。
ネットワークの遅延などが生じた場合、古いデータが後から書き込まれる可能性がありますので、レプリカを参照するアプリケーションは書き込みの順番に依存しないよう設計されている必要があります。
![](https://maprdocs.mapr.com/60/MapR-DB/images/29229933.jpg)

なお、テーブルのレプリケーションは商用のライセンス(M7)が必要となります。


# 2. topology

Master-SlaveとMulti-Masterの2つのtopologyについて説明します。

### 2.1 Master-Slave

ソースのクラスタをMaster、レプリケーション先(ターゲット)のクラスタをSlaveとするtopologyです。
Master、Slaveはそれぞれ一つ以上のクラスタから構成されます。
MasterからSlaveへ片道方向に更新されますので、Slaveのみで加えた更新についてはSlaveのみで保持されます。

具体的な構成を見ていきましょう。

#### Master-Slave Case １
Master1台Slave2台のシンプルな構成です。
ここでは'sanfrancisco', 'newyork', 'hyderabad'がそれぞれクラスタ名で、'customers'がレプリケーション対象のテーブル、'G'の青丸がgatewayを示しています。

![](https://maprdocs.mapr.com/60/MapR-DB/images/29229940.jpg)

#### Master-Slave Case ２
Masterを複数にすることも可能です。
コンフリクトが発生したときの対応は後ほど紹介する[Multi-Masterの場合と同じ](https://qiita.com/bigt23/items/c83707f3374deb962381#22-multi-master)です。
![](https://maprdocs.mapr.com/60/MapR-DB/images/29229939.jpg)

#### Master-Slave Case ３
loopを構成することも出来ます。この場合、テーブルへの各オペレーションはユニークなID(UUID)にひも付きますので、レプリケーションが1周した際に既に実施されたオペレーションについては元のテーブルには実施されません。
![](https://maprdocs.mapr.com/60/MapR-DB/images/29229937.jpg)

MapRのオンラインドキュメントでは[その他のMaster-Slave構成も紹介されています](https://maprdocs.mapr.com/60/MapR-DB/ReplicatingMapR-DBTables-master-slave.html)のでチェックしてみてください。

### 2.2 Multi-Master

Multi-Master構成ではそれぞれのクラスタにgatewayが存在し、同一のテーブルを更新しあう形を取ります。
下図の例では、'sanfrancisco'と'newyork'クラスタにそれぞれ存在する'customers'テーブルを、それぞれのクラスタに存在するgatewayが更新しあいます。
![](https://maprdocs.mapr.com/60/MapR-DB/images/29229948.jpg)

テーブルに対する各オペレーションはUUIDに紐付いているので、実施済みの更新が元のテーブルで再度実行されることはありません。

#### コンフリクト発生時のポリシー(binaryテーブル)

データ更新のコンフリクトが発生した場合、Binaryテーブルではタイムスタンプを比較して順序を決定します。
非常にレアですが、タイムスタンプも一致した場合、ソーステーブルに変更が到着した時間を比較します。
さらにレアですが、ソーステーブルへの変更到着時間まで一致した場合、Cライブラリのmemcmpにより比較を行い、より大きい値を選びます。

#### コンフリクト発生時のポリシー(JSONテーブル)

JSONテーブルでは型に対して優先順位が決定されていますので、コンフリクト時には優先度が高い型を持つ値が採用されます。
優先順位の詳細に関しましては[こちら](https://maprdocs.mapr.com/60/MapR-DB/ReplicatingMapR-DBTables-multimaster.html)をご参照ください。

# 3. gateway

gatewayはソースクラスタからのデータをバッファし、ターゲットクラスタに展開します。
このとき、ターゲットクラスタに複数のgatewayを配置することで、gatewayがダウンした際のフェールオーバが行えるようになります。
また、ソースクラスタは各gatewayに対するリクエストをラウンドロビンで行いますので、ネットワークの負荷を分散することが出来ます。
gatewayのインストールとソースクラスタからの設定に関しては[こちら](https://qiita.com/bigt23/items/731b0eb0634dc0e6451b#2-gateway%E3%81%AE%E6%BA%96%E5%82%99)に記載しましたので参考にしてください。

もしすべてのgatewayがダウンし、ソースクラスタからのレプリケーションが行えない場合、更新用のデータはすべてソースクラスタのMFS上に蓄積されます。
こちらの更新用データがソースクラスタ上のディスクを逼迫するようであれば、`maprcli table replica remove`で一旦レプリケーションを止め、gatewayが復旧してから再度レプリケーションを実施してください。


# 4. 設定例 (Master - Slave)

それでは簡単なレプリケーションの設定例を、Master-Slave構成から見ていきます。
今回はノンセキュアなクラスタclusterA、clusterBでの設定例となり、clusterAをソース、clusterBをターゲットのクラスタとします。
また、設定の前提としてそれぞれのクラスタの各ホスト同士がそれぞれ疎通出来る状態である必要があります。

|        | Master       |    Slave    |
|:-----------------:|:-----------------:|:------------------:|
| クラスタ名   |    clusterA |        clusterB   |
| ノード名     |    nodeA1, nodeA2, nodeA3 |   nodeB1, nodeB2, nodeB3 |
| テーブルパス | /user/mapr/db/binary_table | /user/mapr/db/binary_table_[auto,manual] |

テーブルパス名にあるように、Master-Slaveの例ではバイナリテーブルをレプリケーションしてみます。
レプリケーション先は後ほど紹介するようにautosetupコマンドとマニュアル操作の2つで作ってみます。

### 4.1 ターゲットクラスタ側の準備

ターゲットクラスタで必要な作業はgatewayのセットアップです。
以下のようにgatewayをインストールしてください。

```shell-session
# yum install mapr-gateway
# /opt/mapr/server/configure.sh -R
# maprcli node services -name gateway -action restart -nodes `hostname -f`
```

### 4.2 ソースクラスタ側の準備

ソースクラスタのすべてのノードでmapr-clusters.confを修正し、ターゲットクラスタ側のクラスタ情報を追記してください。

```shell-session
# clush -a cat /opt/mapr/conf/mapr-clusters.conf
nodeA1: clusterA secure=false nodeA1:7222 nodeA2:7222 nodeA3:7222
nodeA1: clusterB secure=false nodeB1:7222 nodeB2:7222 nodeB3:7222
nodeA2: clusterA secure=false nodeA1:7222 nodeA2:7222 nodeA3:7222
nodeA2: clusterB secure=false nodeB1:7222 nodeB2:7222 nodeB3:7222
nodeA3: clusterA secure=false nodeA1:7222 nodeA2:7222 nodeA3:7222
nodeA3: clusterB secure=false nodeB1:7222 nodeB2:7222 nodeB3:7222
```

次にターゲットクラスタのgatewayの設定をします。

```shell-session
# maprcli cluster gateway set -dstcluster clusterB -gateways "nodeB1 nodeB2 nodeB3"
``` 

以上で準備は終了です。

### 4.3 Replicationの設定

Replicationの設定は大きくautosetupを使うか使わないかに二分されます。
最初にautosetupを使った設定、次に使わずにマニュアルで設定する方法を紹介します。

#### 4.3.1 autosetupを使ったReplicationの自動設定

autosetupを使った場合、１コマンドですべての設定が終了します。

```shell-session
$ maprcli table replica autosetup -path <ソースクラスタのテーブルパス> -replica <ターゲットクラスタのテーブルパス>
```

現時点ではソースクラスタの各ノードのmapr-clusters.confにターゲットのクラスタ情報が記載されていますので、以下のコマンドをソースクラスタのいずれかのノードで実行します。

```shell-session
$ maprcli table replica autosetup -path /mapr/clusterA/user/mapr/db/binary_table -replica /mapr/clusterB/user/mapr/db/binary_table_auto

セットアップの確認
$ maprcli table replica list -path /mapr/clusterA/user/mapr/db/binary_table -json
{
        "timestamp":1529636092932,
        "timeofday":"2018-06-22 02:54:52.932 GMT+0000 AM",
        "status":"OK",
        "total":1,
        "data":[
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/binary_table_auto",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/binary_table_auto",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,
                        "throttle":false,
                        "idx":1,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"23844c12-ccf9-5105-974b-01cd642c5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}
```

copyTableCompletionPercentageでレプリケーションの進捗がわかります。
データが少ないので一瞬でレプリケーションされたようです。
実際に確認してみましょう。

```shell-session
$ hbase shell
hbase(main):001:0> scan '/mapr/clusterA/user/mapr/db/binary_table'
ROW                                        COLUMN+CELL
 row1                                      column=cf1:c1, timestamp=1529399345277, value=v1
 row1                                      column=cf1:c2, timestamp=1529399345277, value=v2
...
 row9                                      column=cf1:c1, timestamp=1529399345277, value=v9
 row9                                      column=cf1:c2, timestamp=1529399345277, value=v9
40 row(s) in 0.1610 seconds

hbase(main):001:0> scan '/mapr/clusterA/user/mapr/db/binary_table_auto'
ROW                                        COLUMN+CELL
 row1                                      column=cf1:c1, timestamp=1529399345277, value=v1
 row1                                      column=cf1:c2, timestamp=1529399345277, value=v2
...
 row9                                      column=cf1:c1, timestamp=1529399345277, value=v9
 row9                                      column=cf1:c2, timestamp=1529399345277, value=v9
40 row(s) in 0.1610 seconds

hbase(main):011:0> put '/mapr/clusterA/user/mapr/db/binary_table', 'row1', 'cf1:c1', 'modified_val1'
0 row(s) in 0.0180 seconds

hbase(main):012:0> get '/mapr/clusterA/user/mapr/db/binary_table', 'row1'
COLUMN                                     CELL
 cf1:c1                                    timestamp=1529905863290, value=modified_val1
 cf1:c2                                    timestamp=1529399345277, value=v2
2 row(s) in 0.0080 seconds

hbase(main):013:0> get '/mapr/clusterB/user/mapr/db/binary_table_auto', 'row1'
COLUMN                                     CELL
 cf1:c1                                    timestamp=1529905863290, value=modified_val1
 cf1:c2                                    timestamp=1529399345277, value=v2
2 row(s) in 0.0030 seconds
```

元のテーブル及び変更分のデータのレプリケーションが確認出来ました

#### 4.3.2 autosetupを使わないReplicationのマニュアル設定

autosetupを使わない場合、冗長なコマンドをいくつか打ち込む必要があります。
正直これらのコマンドを知っている必要がどれだけあるのか不明ですが、内部的な動作の勉強にもなるので一応紹介します。
ここでは先程の`/mapr/clusterA/user/mapr/db/binary_table`テーブルを`/mapr/clusterB/user/mapr/db/binary_table_manual`にレプリケートしてみます。

```shell-session
メタ情報をコピーしつつレプリケート先のテーブル作成
$ maprcli table create -path /mapr/clusterB/user/mapr/db/binary_table_manual -copymetafrom /mapr/clusterA/user/mapr/db/binary_table

レプリカ先として登録
$  maprcli table replica add -path /mapr/clusterA/user/mapr/db/binary_table -replica /mapr/clusterB/user/mapr/db/binary_table_manual -paused true

レプリカ先を確認。autosetupで作成したテーブルとマニュアルで作成したテーブルが登録されていることを確認
$ maprcli table replica list -path /mapr/clusterA/user/mapr/db/binary_table -json
{
        "timestamp":1529642781361,
        "timeofday":"2018-06-22 04:46:21.361 GMT+0000 AM",
        "status":"OK",
        "total":2,
        "data":[
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/binary_table_auto",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/binary_table_auto",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,
                        "throttle":false,
                        "idx":1,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"23844c12-ccf9-5105-974b-01cd642c5b00",
                        "copyTableCompletionPercentage":100
                },
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/binary_table_manual",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/binary_table_manual",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":true,
                        "throttle":false,
                        "idx":2,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":false,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"2aeb208f-b83d-0487-6d0d-0d1c6b2c5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}

upstream先として登録
$ maprcli table upstream add -path /mapr/clusterB/user/mapr/db/binary_table_manual -upstream /mapr/clusterA/user/mapr/db/binary_table

upstream先のリストを確認
$ maprcli table upstream list -path /mapr/clusterB/user/mapr/db/binary_table_manual
cluster  idx  uuid                                  table
clusterA   1    1e2eb69e-64ea-aafb-a5fd-070cc8285b00  /user/mapr/db/binary_table

レプリケーションを始める前にデータを移しておく。先程テーブルを作成したときにbulkloadを有効にしていなかったので、bulkloadはfalseにしています
$ hbase com.mapr.fs.hbase.tools.mapreduce.CopyTable -src /mapr/clusterA/user/mapr/db/binary_table -dst /mapr/clusterB/user/mapr/db/binary_table_manual -bulkload false

レプリケーションを開始
$ maprcli table replica resume -path /mapr/clusterA/user/mapr/db/binary_table -replica /mapr/clusterB/user/mapr/db/binary_table_manual

```

やっと終了しました。
それでは実際にデータがレプリケートされていることを再度確認してみましょう。

```shell-session
hbase(main):004:0> scan '/mapr/clusterB/user/mapr/db/binary_table_manual'
 row9                                      column=cf1:c1, timestamp=1529399345277, value=v9
 row9                                      column=cf1:c2, timestamp=1529399345277, value=v9
40 row(s) in 0.1350 seconds

hbase(main):005:0* put '/mapr/clusterA/user/mapr/db/binary_table', 'row1', 'cf1:c2', 'modified_val2'
0 row(s) in 0.0130 seconds

hbase(main):006:0> get '/mapr/clusterA/user/mapr/db/binary_table', 'row1'
COLUMN                                     CELL
 cf1:c1                                    timestamp=1529905863290, value=modified_val1
 cf1:c2                                    timestamp=1529906301210, value=modified_val2
2 row(s) in 0.0100 seconds

hbase(main):007:0> get '/mapr/clusterB/user/mapr/db/binary_table_manual', 'row1'
COLUMN                                     CELL
 cf1:c1                                    timestamp=1529905863290, value=modified_val1
 cf1:c2                                    timestamp=1529906301210, value=modified_val2
2 row(s) in 0.0030 seconds

```

binary_table_manualテーブルにも問題なくレプリケートされていますね。

この時点で２つのレプリケーション先があるので、１つを止めて実際に片方にだけレプリケーションされるか確認して遊んでみましょう

```shell-session
$  maprcli table replica pause -path /mapr/clusterA/user/mapr/db/binary_table -replica /mapr/clusterB/user/mapr/db/binary_table_manual

$  maprcli table replica list -path /mapr/clusterA/user/mapr/db/binary_table  -json
{
        "timestamp":1529644564519,
        "timeofday":"2018-06-22 05:16:04.519 GMT+0000 AM",
        "status":"OK",
        "total":2,
        "data":[
                {
                        "cluster":"clusterA",
                        "table":"/user/mapr/db/binary_table",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/binary_table",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,                 <<<<---- ココ
                        "throttle":false,
                        "idx":1,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"23844c12-ccf9-5105-974b-01cd642c5b00",
                        "copyTableCompletionPercentage":100
                },
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/binary_table_manual",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/binary_table_manual",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":true,                 <<<<---- ココ
                        "throttle":false,
                        "idx":2,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":false,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"2aeb208f-b83d-0487-6d0d-0d1c6b2c5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}

```

/user/mapr/db/binary_table_manualの"paused"設定がtrueになっていますね。
では再度レプリケーションの状況を確認してみます。

```shell-session
$ hbase shell

hbase(main):004:0> get '/mapr/clusterA/user/mapr/db/binary_table', 'row_additional'
COLUMN                                     CELL
 cf1:c1                                    timestamp=1529906439232, value=additional_value
1 row(s) in 0.0230 seconds

hbase(main):005:0> get '/mapr/clusterB/user/mapr/db/binary_table_auto', 'row_additional'
COLUMN                                     CELL
 cf1:c1                                    timestamp=1529906439232, value=additional_value
1 row(s) in 0.0070 seconds

hbase(main):006:0> get '/mapr/clusterB/user/mapr/db/binary_table_manual', 'row_additional'
COLUMN                                     CELL
0 row(s) in 0.0020 seconds

```


clusterBのbinary_table_autoのみデータのレプリケートが有効になっていますね。
以上のように１コマンドでreplicationのon/offがコントロール出来ます。


# 5. 設定例 (Multi-Master)

続いてMulti-Masterの構成でのレプリケーションについて紹介します。
Master-Slave同様、ノンセキュアなクラスタであるclusterAとclusterBを利用します。
また、clusterAをMaster, clusterBをSlaveとした[4.設定例(Master-Slave)](https://qiita.com/bigt23/items/c83707f3374deb962381#4-%E8%A8%AD%E5%AE%9A%E4%BE%8B-master---slave)での設定をそのまま利用し、この上にclusterAをSlave, clusterBをMasterとする設定を追加設定する形で実現します。
そのため、 **Multi-Masterを実現する上では[4.1 ターゲットクラスタ側の準備](https://qiita.com/bigt23/items/c83707f3374deb962381#41-%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E5%81%B4%E3%81%AE%E6%BA%96%E5%82%99)と[4.2 ソースクラスタ側の準備](https://qiita.com/bigt23/items/c83707f3374deb962381#42-%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E5%81%B4%E3%81%AE%E6%BA%96%E5%82%99)の設定をすべて行ってから以降の設定を実施** してください。
Multi-Master構成ではBinaryテーブルではなくJSONテーブルを使い、Binaryテーブルのときと同様autosetupを使う場合と使わない場合を紹介します。

|        | Master       |    Master    |
|:-----------------:|:-----------------:|:------------------:|
| クラスタ名   |    clusterA |        clusterB   |
| ノード名     |    nodeA1, nodeA2, nodeA3 |   nodeB1, nodeB2, nodeB3 |
| テーブルパス | /user/mapr/db/json_table | /user/mapr/db/json_table_[auto,manual]  |




### 5.1 ターゲットクラスタ側の準備

Master-Slaveの場合はclusterAをMaster、clusterBをSlaveとし、ターゲットクラスタとしてclusterBのみgatewayの設定を行いました。
Mult-Masterの場合はclusterBに続いてclusterAにおいてもgatewayのインストールと設定、起動を行ってください。

### 5.2 ソースクラスタ側の準備

Master-Slaveの実行時はclusterA側においてソースクラスタとしての設定を行いました。
Multi-Masterの場合はclusterBにおいても、以下の２つの設定を行います。

* すべてのノードでmapr-clusters.confを修正し、ターゲットクラスタ側のクラスタ情報を記載する

```shell-session
# clush -a cat /opt/mapr/conf/mapr-clusters.conf
nodeB1: clusterB secure=false nodeB1:7222 nodeB2:7222 nodeB3:7222
nodeB1: clusterA secure=false nodeA1:7222 nodeA2:7222 nodeA3:7222
nodeB2: clusterB secure=false nodeB1:7222 nodeB2:7222 nodeB3:7222
nodeB2: clusterA secure=false nodeA1:7222 nodeA2:7222 nodeA3:7222
nodeB3: clusterB secure=false nodeB1:7222 nodeB2:7222 nodeB3:7222
nodeB3: clusterA secure=false nodeA1:7222 nodeA2:7222 nodeA3:7222
```

* [5.1](https://qiita.com/bigt23/items/c83707f3374deb962381#51-%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E5%81%B4%E3%81%AE%E6%BA%96%E5%82%99)で設定したgatewayをclusterBからclusterAへのgatewayとして登録する

```shell-session
# maprcli cluster gateway set -dstcluster clusterA -gateways "nodeA1 nodeA2 nodeA3"
``` 

### 5.3 Replicationの設定

Multi-Master構成においてもautosetupを使う場合と使わない場合をそれぞれ紹介します。

#### 5.3.1 autosetupを使ったReplicationの自動設定

Replicaitonの設定はBinaryテーブルの場合と同じです。
Multi-Masterの場合、以下のように`-multimaster true`オプションを追加してください。

```shell-session
$ maprcli table replica autosetup -path /mapr/clusterA/user/mapr/db/json_table -replica /mapr/clusterB/user/mapr/db/json_table_auto -multimaster true
```

設定が反映されている確認してみます

```shell-session
$ maprcli table replica list -path /mapr/clusterA/user/mapr/db/json_table -json
{
        "timestamp":1529656815217,
        "timeofday":"2018-06-22 08:40:15.217 GMT+0000 AM",
        "status":"OK",
        "total":1,
        "data":[
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/json_table_auto",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/json_table_auto",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,
                        "throttle":false,
                        "idx":4,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"2a3757ab-3c22-d8da-24cd-07968d2c5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}

$ maprcli table replica list -path /mapr/clusterB/user/mapr/db/json_table_auto -json
{
        "timestamp":1529656891472,
        "timeofday":"2018-06-22 08:41:31.472 GMT+0000 AM",
        "status":"OK",
        "total":1,
        "data":[
                {
                        "cluster":"clusterA",
                        "table":"/user/mapr/db/json_table",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/json_table",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,
                        "throttle":false,
                        "idx":1,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"4bbbad2b-fca9-3979-b245-0de4441e5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}
```

両方向にレプリケーションが設定できているのが確認できました。
では、実際にデータがコピー、更新されるか確認してみましょう

```shell-session
clusterB側へのデータコピー確認
maprdb mapr:> find /mapr/clusterB/user/mapr/db/json_table_auto
{"_id":"2000","PROP":{"intelligence":72,"lead":80,"power":90},"USERNAME":"信","total_core":242}
{"_id":"2001","PROP":{"intelligence":88,"lead":98,"power":78},"USERNAME":"嬴政","total_core":264}
{"_id":"2002","PROP":{"intelligence":80,"lead":75,"power":78},"USERNAME":"漂","total_core":233}
{"_id":"2003","PROP":{"intelligence":90,"lead":85,"power":80},"USERNAME":"昌文君","total_core":255}
{"_id":"2004","PROP":{"intelligence":88,"lead":85,"power":60},"USERNAME":"河了貂","total_core":233}
{"_id":"2005","PROP":{"intelligence":86,"lead":84,"power":80},"USERNAME":"壁","total_core":250}
{"_id":"2006","PROP":{"intelligence":87,"lead":80,"power":95},"USERNAME":"羌瘣","total_core":262}
{"_id":"2007","PROP":{"intelligence":76,"lead":68,"power":55},"USERNAME":"成蟜","total_core":199}
{"_id":"2008","PROP":{"intelligence":80,"lead":65,"power":50},"USERNAME":"竭氏","total_core":195}
{"_id":"2009","PROP":{"intelligence":62,"lead":61,"power":87},"USERNAME":"左慈","total_core":210}
{"_id":"3000","PROP":{"intelligence":62,"lead":61,"power":87},"USERNAME":"黄斑"}
{"_id":"3003","PROP":{"intelligence":90,"lead":85,"power":80},"USERNAME":"kingdom","total_core":255}

clusterB側にデータを挿入
maprdb mapr:> insert /mapr/clusterB/user/mapr/db/json_table_auto --value '{"_id":"3004",  "USERNAME":"呂不韋",  "total_score":240, "PROP":{"intellligence":90, "power":60, "lead":90}}'
Document with id: ""3004"" inserted.

clusterB側でデータ挿入確認
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_auto --id "3004"
{"_id":"3004","PROP":{"intellligence":90,"lead":90,"power":60},"USERNAME":"呂不韋","total_score":240}
1 document(s) found.

clusterB -> clusterAへのレプリケーション確認
maprdb mapr:> findbyid /mapr/clusterA/user/mapr/db/json_table --id "3004"
{"_id":"3004","PROP":{"intellligence":90,"lead":90,"power":60},"USERNAME":"呂不韋","total_score":240}
1 document(s) found.

clusterA側にデータ挿入
maprdb mapr:> insert /mapr/clusterA/user/mapr/db/json_table --value '{"_id":"3005", "USERNAME":"昌平君", "total_score":281, "PROP":{"intellligence":97, "power":89, "lead":95}}'
Document with id: ""3005"" inserted.

clusterA側でデータ挿入確認
maprdb mapr:> findbyid /mapr/clusterA/user/mapr/db/json_table --id "3005"
{"_id":"3005","PROP":{"intellligence":97,"lead":95,"power":89},"USERNAME":"昌平君","total_score":281}
1 document(s) found.

clusterA -> clusteｒBへのレプリケーション確認
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_auto --id "3004"
{"_id":"3005","PROP":{"intellligence":97,"lead":95,"power":89},"USERNAME":"昌平君","total_score":281}
1 document(s) found.
```

両方向へのレプリケーションを確認出来ました。

#### 5.3.2 autosetupを使わないReplicationのマニュアル設定

autosetupを使わない場合もMaster-Slaveとほぼ同様になりますが、Multi-Masterの場合は両方向に対して設定を行う必要があります。
Binaryテーブル同様、clusterAのjson_tableとclusterBのjson_table_manualを使った設定例を羅列していきます。

```shell-session
$ maprcli table create -path /mapr/clusterB/user/mapr/db/json_table_manual -copymetafrom /mapr/clusterA/user/mapr/db/json_table -tabletype json
ERROR (22) -  java.lang.RuntimeException: Error occurred while instantiating com.mapr.fs.hbase.HTableImpl11.
==> java.lang.UnsupportedOperationException: HBase api's cannot be used for MapR-DB JSON tabletype tables..
```

いきなり失敗しました。
`copymetafrom`コマンドは今の所Binaryテーブルでしか利用できないようです(バグ?)。
仕方ないので通常通りテーブルを作ってデータをコピーする方向でやってみます。

```shell-session
テーブル作成
$ maprcli table create -tabletype json -path  /mapr/clusterB/user/mapr/db/json_table_manual

レプリケーションの設定
$ maprcli table replica add -path /mapr/clusterA/user/mapr/db/json_table -replica /mapr/clusterB/user/mapr/db/json_table_manual -paused true

clusterA側からレプリケーション確認。autosetup使用時と合わせてレプリケーション先が表示される。
$ maprcli table replica list -path /mapr/clusterA/user/mapr/db/json_table -json
{
        "timestamp":1529658595403,
        "timeofday":"2018-06-22 09:09:55.403 GMT+0000 AM",
        "status":"OK",
        "total":2,
        "data":[
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/json_table_auto",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/json_table_auto",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,
                        "throttle":false,
                        "idx":4,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"2a3757ab-3c22-d8da-24cd-07968d2c5b00",
                        "copyTableCompletionPercentage":100
                },
                {
                        "cluster":"clusterB",
                        "table":"/user/mapr/db/json_table_manual",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/json_table_manual",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":true,
                        "throttle":false,
                        "idx":5,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":false,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"9febaf75-9849-9f6a-0b48-033dbc2c5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}

upstream設定
$ maprcli table upstream add -path /mapr/clusterB/user/mapr/db/json_table_manual -upstream /mapr/clusterA/user/mapr/db/json_table

clusterBへのupstream先確認
$ maprcli table upstream list -path /mapr/clusterB/user/mapr/db/json_table_manual
cluster  idx  uuid                                  table
clusterA   1    4bbbad2b-fca9-3979-b245-0de4441e5b00  /user/mapr/db/json_table

データのコピー
maprdb mapr:> mapr copytable -src /mapr/clusterA/user/mapr/db/json_table  -dst  /mapr/clusterB/user/mapr/db/json_table_manual

レプリケーション開始
$ maprcli table replica resume -path /mapr/clusterA/user/mapr/db/json_table -replica /mapr/clusterB/user/mapr/db/json_table_manual
```

ここまででclusterA側からclusterB側へのレプリケーションの設定が終わりました。
続いて同様の処理をclusterB側からclusterA側に向けて設定します。

```shell-session
レプリケーション設定
$ maprcli table replica add -path /mapr/clusterB/user/mapr/db/json_table_manual -replica  /mapr/clusterA/user/mapr/db/json_table

clusterB側からレプリケーション設定の確認。clusterAへのレプリケーションが表示される
$ maprcli table replica list -path /mapr/clusterB/user/mapr/db/json_table_manual -json
{
        "timestamp":1529658919672,
        "timeofday":"2018-06-22 09:15:19.672 GMT+0000 AM",
        "status":"OK",
        "total":1,
        "data":[
                {
                        "cluster":"clusterA",
                        "table":"/user/mapr/db/json_table",
                        "type":"MapRDB",
                        "replicaPath":"/user/mapr/db/json_table",
                        "replicaState":"REPLICA_STATE_REPLICATING",
                        "paused":false,
                        "throttle":false,
                        "idx":1,
                        "networkencryption":false,
                        "synchronous":false,
                        "networkcompression":"lz4",
                        "propagateExistingData":false,
                        "isUptodate":true,
                        "minPendingTS":0,
                        "maxPendingTS":0,
                        "bytesPending":0,
                        "putsPending":0,
                        "bucketsPending":0,
                        "uuid":"4bbbad2b-fca9-3979-b245-0de4441e5b00",
                        "copyTableCompletionPercentage":100
                }
        ]
}

upstream設定
$ maprcli table upstream add -path /mapr/clusterA/user/mapr/db/json_table -upstream /mapr/clusterB/user/mapr/db/json_table_manual
```

これにて設定が終わりです。
この時点で[5.1](https://qiita.com/bigt23/items/c83707f3374deb962381#51-%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%83%E3%83%88%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E5%81%B4%E3%81%AE%E6%BA%96%E5%82%99)での設定も合わせて以下のようなレプリケーションが実現されています。

```
json_table_auto(clusterB) ↔ json_table(clusterA) ↔ json_table_manual(clusterB)
``` 

この構成では以下の様な挙動を取ります。

* json_tableに加えた変更がjson_table_auto, json_table_manualどちらにもレプリケートされる
* json_table_manual(もしくは\_auto)に加えた変更はjson_tableを経由してjson_table\_auto(もしくは_manual)にもレプリケートされる

実際に確認してみましょう。

```shell-session

clusterA側にデータ挿入
maprdb mapr:> insert /mapr/clusterA/user/mapr/db/json_table --value '{"_id":"3006", "USERNAME":"蒙武", "total_score":273, "PROP":{"intellligence":84, "power":99, "lead":90}}'

まずはclusterA側で確認
maprdb mapr:> findbyid /mapr/clusterA/user/mapr/db/json_table --id "3006"
{"_id":"3006","PROP":{"intellligence":84,"lead":90,"power":99},"USERNAME":"蒙武","total_score":273}
1 document(s) found.

clusterB側で確認 @ json_table_manual
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_manual --id "3006"
{"_id":"3006","PROP":{"intellligence":84,"lead":90,"power":99},"USERNAME":"蒙武","total_score":273}
1 document(s) found.

clusterB側で確認 @ json_table_auto
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_auto --id "3006"
{"_id":"3006","PROP":{"intellligence":84,"lead":90,"power":99},"USERNAME":"蒙武","total_score":273}
1 document(s) found.



clusterBのjson_table_manualからデータ挿入
insert /mapr/clusterB/user/mapr/db/json_table_auto --value '{"_id":"3007", "USERNAME":"李斯", "total_score":229, "PROP":{"intellligence":90, "power":55, "lead":84}}'

まずはjson_table_autoでデータの挿入を確認
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_auto --id "3007"
{"_id":"3007","PROP":{"intellligence":90,"lead":84,"power":55},"USERNAME":"李斯","total_score":229}
1 document(s) found.

clusterA側でレプリケーション確認
maprdb mapr:> findbyid /mapr/clusterA/user/mapr/db/json_table --id "3007"
{"_id":"3007","PROP":{"intellligence":90,"lead":84,"power":55},"USERNAME":"李斯","total_score":229}
1 document(s) found.

clusterB側で確認 @ json_table_manual
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_manual --id "3007"
{"_id":"3007","PROP":{"intellligence":90,"lead":84,"power":55},"USERNAME":"李斯","total_score":229}
1 document(s) found.


clusterBのjson_table_manualからデータ挿入
maprdb mapr:> insert /mapr/clusterB/user/mapr/db/json_table_manual --value '{"_id":"3008", "USERNAME":"蔡沢", "total_score":188, "PROP":{"intellligence":93, "power":3, "lead":92}}'

まずはjson_table_manualで挿入を確認
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_manual --id "3008"
{"_id":"3008","PROP":{"intellligence":93,"lead":92,"power":3},"USERNAME":"蔡沢","total_score":188}
1 document(s) found.

clusterAでレプリケーション確認
maprdb mapr:> findbyid /mapr/clusterA/user/mapr/db/json_table --id "3008"
{"_id":"3008","PROP":{"intellligence":93,"lead":92,"power":3},"USERNAME":"蔡沢","total_score":188}
1 document(s) found.

clusterB側で確認 @ json_table_auto
maprdb mapr:> findbyid /mapr/clusterB/user/mapr/db/json_table_auto --id "3008"
{"_id":"3008","PROP":{"intellligence":93,"lead":92,"power":3},"USERNAME":"蔡沢","total_score":188}
1 document(s) found.

```

レプリケーションの挙動が確認できました。
少しずつレプリケーションに慣れてきましたね！
今後はこのレプリケーションを使ったCDCやストリームのレプリケーションについても紹介していきます