Redis 3.0 diskless replicationの検証



俺です。
Redisバージョン: 3.0.5

Redis内のデータがnGB超えていたのでチューニングする。
repl-timeoutはRedisのデータサイズに応じて長めに設定したものの、
slave再接続時にmasterで実行されるdisk出力のbgsaveを抑える方法があったので検証した。

[参考](http://takeshiyako.blogspot.jp/2015/04/bigdata-redis-replication.html) m(__)m

# 検証結果

- nGB超のデータを扱う際はディスクレスレプリケーションが有効です。
- ディスクレスレプリケーションであればmasterで一時ダンプは出力されないので`cached memory`は消費しません
- デフォルトのレプリケーションに比べてFull syncの時間が1/2になりました。
- 本例(master/slave関係)ではmasterのノードにのみディスクレスレプリケーションのパラメータをセットしましたが、Sentinelを利用する場合は全Redisノードに対して設定しておくのが良いと思います


# 準備

ターゲットインスタンス

- r3.xlarge

データサイズ

- RedisのデータはYCSBで作ったダミーデータ.サイズ 20GB

- カーネルパラメータ

master/slave共に下記が有効

```
vm.swappiness=1
vm.overcommit_memory=1
```

- redis.conf(master/slave)

デフォルト値にrepl-timeoutを追加

```
repl-timeout 1800
```

- redis.conf(slave)

```
slaveof <master ipaddr> 6379
```

## 通常のreplication

- 検証手順

Redis masterを起動し、20GBのデータをロードする
Redis slaveを起動し、Redis masterとレプリケーションする
`ps aux|grep redis`, `redis-cli info`と`redis.log`を確認する

### masterの挙動

- slaveを起動してmasterへ接続する時にmasterでbgsaveを実行する

`Full resync target: disk`となっている
一度masterでrdbファイルを出力/作成し、slaveのrdbディレクトリへ転送している模様

- masterのプロセス確認

masterではbgsaveが動作している

```
[root@ip-172-31-5-23 lib]# ps aux|grep redis
redis     6921 13.3 64.8 20516304 20375152 ?   Ssl  02:34   1:18 /usr/bin/redis-server *:6379
root      6958  0.0  0.0 107932   616 pts/1    S+   02:39   0:00 tail -f redis.log
redis     6969 95.4 64.8 20516692 20374780 ?   R    02:43   0:42 redis-rdb-bgsave *:6379
root      6975  0.0  0.0 114632   920 pts/0    S+   02:43   0:00 grep redis
```

```
6921:M 30 Nov 02:43:08.540 - Accepted 172.31.13.112:34156
6921:M 30 Nov 02:43:08.541 * Slave 172.31.13.112:6379 asks for synchronization
6921:M 30 Nov 02:43:08.541 * Full resync requested by slave 172.31.13.112:6379
6921:M 30 Nov 02:43:08.541 * Starting BGSAVE for SYNC with target: disk
6921:M 30 Nov 02:43:08.778 * Background saving started by pid 6969
..省略
6921:M 30 Nov 02:51:40.880 * Synchronization with slave 172.31.13.112:6379 succeeded
```

### slaveの挙動

- redis.log

```
3099:S 30 Nov 02:43:08.530 * Connecting to MASTER 172.31.5.23:6379
3099:S 30 Nov 02:43:08.530 * MASTER <-> SLAVE sync started
3099:S 30 Nov 02:43:08.530 * Non blocking connect for SYNC fired the event.
3099:S 30 Nov 02:43:08.530 * Master replied to PING, replication can continue...
3099:S 30 Nov 02:43:08.530 * Partial resynchronization not possible (no cached master)
3099:S 30 Nov 02:43:08.769 * Full resync from master: 61865c4afa66868ceee549a5fb1ebfc1020e934a:1
..省略
3099:S 30 Nov 02:51:40.977 * MASTER <-> SLAVE sync: Flushing old data
3099:S 30 Nov 02:51:54.437 * MASTER <-> SLAVE sync: Loading DB in memory
3099:S 30 Nov 02:53:56.212 - Accepted 127.0.0.1:42239
3099:S 30 Nov 02:53:56.225 - Client closed connection
3099:S 30 Nov 02:54:40.104 * MASTER <-> SLAVE sync: Finished with success
```


# diskless replication

事前に下記パラメータをセットする
パラメータドキュメントは[github](https://raw.githubusercontent.com/antirez/redis/3.0/redis.conf)を参照

### レプリケーションタイムアウトの調整

```redis-cli CONFIG SET repl-timeout "1800"```

### ディスクレスレプリケーションの有効化

```redis-cli CONFIG SET repl-diskless-sync "yes"```

### repl-diskless-sync-delayを0にする

スレーブ接続時の待ち時間をなしにする。

```redis-cli CONFIG SET repl-diskless-sync-delay 0```

### バッファリミットを無効化

クライアント(slave)が強制切断されないようにバッファリミットを無効にする

```redis-cli CONFIG SET client-output-buffer-limit "slave 0 0 0"```

## masterの挙動

- slaveを起動してmasterへ接続する時にmasterでbgsaveを実行する


- masterのプロセス確認

masterでは`redis-rdb-to-slaves`が動作している

```
[root@ip-172-31-5-23 lib]# ps aux|grep redis
redis     6921  5.1 64.8 20516304 20375188 ?   Ssl  02:34   1:31 /usr/bin/redis-server *:6379
redis     7103 79.4 64.8 20516688 20374632 ?   R    03:01   1:48 redis-rdb-to-slaves *:6379
root      7115  0.0  0.0 114632   924 pts/0    R+   03:03   0:00 grep redis
```

- redis.log

`Starting BGSAVE for SYNC with target: slaves sockets`となっている
slaveのsocketへ直接BGSAVEのダンプを転送している模様
 
```
6921:M 30 Nov 03:01:34.496 # Connection with slave client id #33 lost.
6921:M 30 Nov 03:01:34.522 - Accepted 172.31.13.112:34189
6921:M 30 Nov 03:01:34.522 * Slave 172.31.13.112:6379 asks for synchronization
6921:M 30 Nov 03:01:34.522 * Full resync requested by slave 172.31.13.112:6379
6921:M 30 Nov 03:01:35.220 * Starting BGSAVE for SYNC with target: slaves sockets
6921:M 30 Nov 03:01:35.459 * Background RDB transfer started by pid 7103
6921:M 30 Nov 03:05:03.333 * Background RDB transfer terminated with success
6921:M 30 Nov 03:05:03.333 # Slave 172.31.13.112:6379 correctly received the streamed RDB file.
6921:M 30 Nov 03:05:03.333 * Streamed RDB transfer with slave 172.31.13.112:6379 succeeded (socket). Waiting for REPLCONF ACK from slave to
enable streaming
..省略..
6921:M 30 Nov 03:06:19.609 * Synchronization with slave 172.31.13.112:6379 succeeded
```

### slaveのredis.log

```
3305:S 30 Nov 03:01:34.514 * Connecting to MASTER 172.31.5.23:6379
3305:S 30 Nov 03:01:34.514 * MASTER <-> SLAVE sync started
3305:S 30 Nov 03:01:34.515 * Non blocking connect for SYNC fired the event.
3305:S 30 Nov 03:01:34.515 * Master replied to PING, replication can continue...
3305:S 30 Nov 03:01:34.515 * Partial resynchronization not possible (no cached master)
3305:S 30 Nov 03:01:35.213 * Full resync from master: 61865c4afa66868ceee549a5fb1ebfc1020e934a:1429
3305:S 30 Nov 03:01:35.454 * MASTER <-> SLAVE sync: receiving streamed RDB from master
..省略..
3305:S 30 Nov 03:05:02.855 * MASTER <-> SLAVE sync: Flushing old data
3305:S 30 Nov 03:05:02.855 * MASTER <-> SLAVE sync: Loading DB in memory
3305:S 30 Nov 03:06:19.096 * MASTER <-> SLAVE sync: Finished with success
```


### 参考 Redis Full resync中のslaveステータス遷移

`redis-cli info replication` の結果

- masterで実行

Master bgsave中のステータス
slaveはwait_bgsaveになっている

```
# Replication
role:master
connected_slaves:1
slave0:ip=172.31.13.112,port=6379,state=wait_bgsave,offset=0,lag=0
master_repl_offset:253
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:252
```

↓

bgsave完了後、バルクロードが開始される。
send_bulkに変更される

```
[root@ip-172-31-5-23 lib]# redis-cli info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.31.13.112,port=6379,state=send_bulk,offset=0,lag=0
master_repl_offset:337
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:336
```

↓

onlineに変更される

```
[root@ip-172-31-5-23 lib]# redis-cli info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.31.13.112,port=6379,state=online,offset=1051,lag=1
master_repl_offset:1051
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1050
```