Redisチートシート(設定編)

- [1. 導入編](http://qiita.com/morrr/items/271548776938e7ddc0ec)
- [2. コマンド編](http://qiita.com/morrr/items/3639f549dcf33992c851)
- 3. 設定編

## 概要

Redisの設定方法について抜粋した。
またセキュリティ対応、レプリケーション、永続化といった応用項目ごとに、その設定方法をまとめた。

なおDockerや仮想マシン等の環境に対応するための設定方針については含めていない。


## 主要な設定項目

各バージョンのソース内に設定ファイルのサンプルがあるので、これをベースに作るといい([ex. 3.0 redis.conf](https://raw.githubusercontent.com/antirez/redis/3.0/redis.conf))。



- 設定ファイルは通常`redis.conf` などと命名する


- 設定ファイル内は、 `<キーワード> <引数1>, <引数2>, ...` の形式で書いていく
    - コメントは他のconfと同様に`#`


### .conf以外の設定の指定・変更方法

#### サーバの起動時に設定する
設定は、サーバの起動時に直接指定することもできる。

```
# 設定ファイルに 「port 6380」 と書くのと同じ
$ redis-server --port 6380
```

#### クライアントから設定する

`CONFIG SET`, `CONFIG GET`, ` CONFIG REWRITE` コマンドを使うことで、クライアントから設定を変更できる。
サーバを起動したまま設定変更できるが、設定項目には制限がある。


### 主要な設定項目

よく使いそうな設定項目を抜粋する。



#### 起動条件

```
# 他のconfigファイルを読み込む
include path/to/other_config.conf

# デーモン化 yes/no
daemonize no

# デーモン化する場合のPIDファイルのパスを指定
pidfile /var/run/redis.pid

# DB数を設定する
databases 2
```

#### 接続設定

```
# ポートを指定
port 6379

# クライアントを限定する
bind 127.0.0.1
```


#### タイムアウト
```
# タイムアウトを設定する(sec, 0の場合無効)
timeout 0

# TCPのKeepAlive機能を設定する(sec)
tcp-keepalive 0
```


#### ログ

```
# ログレベルを設定する(debug < verbose < notice < warning)
loglevel notice

# ログファイルを指定する(未設定時はSTDOUT)
logfile ''

# syslogを使う
syslog-enabled no

# syslogのIDを設定する
syslog-ident redis

# syslogのファシリティ(分類)を設定する(local0~local7)
syslog-facility local0

```

#### スナップショット

```

# ディスクへの保存条件
# ex. 900秒のうち、1つでもキーが更新されたら保存する
# saveは時間別に復数設定できる
save 900 1

# .rdbファイルの名前を指定する
dbfilename dump.rdb

# .rdbを圧縮する
rdbcompression yes

# .rdbにチェックサムを付ける
rdbchecksum yes

# .rdbを書き込むディレクトリを指定する
dir ./
```


#### 制限

```
# 最大接続数を設定(10000はデフォルト)
maxclients 10000

# メモリの利用可能容量を設定
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
maxmemory 4g


# メモリポリシを設定
# Redisがメモリを使い果たした際の挙動を設定する
#   volatile-lru      -> 期限切れのキーを、LRUに基づいて削除する
#   allkeys-lru       -> 全てのキーを、LRUに基づいて削除する
#   volatile-random   -> 期限切れのキーを、ランダムに削除する
#   allkeys-random    -> 全てのキーを、ランダムに削除する
#   volatile-ttl      -> TTLの小さい順にキーを削除する
#   noeviction        -> 書き込み時にエラーを返すようにする
maxmemory-policy noeviction


# volatile-ttlの場合のサンプリング頻度を設定する
# 小さいほど負荷は増すが厳密になる
maxmemory-samples 5
```
セキュリティ
------------------------------------------------------------

### 接続を制限する
外部の不特定多数から、TCP/ソケットでRedisに直接通信できるような状態にすべきではない。
設定ファイルによって接続元のIPや、接続数を制限すること。

```
bind 127.0.0.1
maxclients 3
```

### プロテクトモード

バージョン3.2.0以降において、以下の場合はプロテクトモード(protected mode)となる。

- bind設定がデフォルトのまま(制限なし)
- 認証系が未設定

プロテクトモードの場合は、ローカルホスト(loopback)の場合のみ正常に返答し、それ以外の場合はエラーを返すようになる。


### 認証を要求する

設定ファイルによって認証機能をONにすることができる。

```conf:redis.conf
requirepass <パスワード平文>
```

認証をONにすると、`AUTH`コマンドによって認証されない限り、Redisはあらゆるコマンドを拒否する。


```
> GET 'foo'
=> (error) NOAUTH Authentication required.

> auth bad_password
=> (error) ERR invalid password

> auth good_password
=> OK
```

なおAUTHコマンドを含めたすべてのRedisコマンドは平文で送受されるとのこと。
不特定多数がアクセスできる状態で運用したい場合はSSLプロキシなどを組み合わせて運用すべし、とのこと。


### コマンドを制限する

設定によってコマンドを改変することで、その利用を制限したり、使えなくすることができる。


```conf:redis.conf

# CONFIGコマンドを使えなくする
rename-command CONFIG ''

# CONFIGコマンドを、知っていないと使えない名前にする
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
```

### その他
Redisはインジェクションに対してはライブラリレベルで対応済とのこと(EVALによるLua実行含む)。



永続化(AOF)
------------------------------------------------------------

Redisは二種類の方法で、DBを永続化(ファイル保存)できる。
どちらも使わずに、完全揮発性のDBとして運用することも可能。

- RDB = 一定時間におけるDBのフルデータ
- AOF = Append Only File. 書き込み操作のたびに、その操作をロギングする


RDBファイルについては導入編、コマンド編を参照のこと。
AOFを利用する場合は、設定ファイルで有効化する。

```conf:redis.conf
# AOF有効
appendonly yes

# AOFファイル名を指定
appendfilename "appendonly.aof"

# AOF追加時のflah()システムコールの利用可否を設定する
# no        : fsyncしない。速い
# always    : AOFの書き込みごとに毎回fsyncする。遅いが安全
# everysec  : 1秒ごとにfsyncする。妥協
# よくわからない場合はeverysecにしておけ、とのこと
#
appendfsync everysec
```

RDBファイルと同様に、設定したパスにAOFファイルがあれば、起動時に読み込まれる。


レプリケーション
------------------------------------------------------------
- Redisは、マスタ/スレーブ方式でレプリケーションできる
- マスタは復数のスレーブを持てる
- スレーブ同士によるレプリケーションが可能
- レプリケーション処理はブロッキングが発生しない
- スレーブは基本的にRead-onlyだが、変更可能


まず、マスタに加えてスレーブとなるRedisを復数立ち上げる。
スレーブ側のRedisは、設定によってマスタを明示する。

```config:redis.conf(slave)

# マスタを指定
# SLAVEOFコマンドで代替可能
slaveof 127.0.0.1 6379

# Read-only状態を指定
slave-read-only yes
```

マスタ側はスレーブの正当性を認証できる

```config:redis.conf(master)
masterauth some_plain_password
```

レプリケーション状態は`INFO`コマンドで確認できる。



Sentinel
------------------------------------------------------------

Redis Sentinel = 状態監視システム。
センチネルはRedisとは別のバージョン体系が存在し、Redis2.8で正式導入された。

以下の機能を提供する:

- 監視
- 通知
- 自動フェールオーバー
- 接続先サーバの振り分け

また公式による注意点、基本方針として以下が示されている:

- センチネルはデフォルトではTCP26379ポートをリスンする
- センチネル自身も冗長化する必要があるため、通常復数のインスタンスで運用される
- 最低でも3台のセンチネルインスタンスを起動すること
- それぞれが独立した環境にデプロイされること
- センチネルによる分散システムは、レプリケーションによる同期の成否を保証しないこと
- クライアントがセンチネルをサポートしているか確認のこと



### 導入

センチネルは`redis-sentinel`コマンドに対して、それ用の設定ファイルを指定して起動する。
(設定ファイルは必須)

```bash
$ redis-sentinel path/to/redis-sentinel.conf

# あるいはredis-serverのオプションで指定する
$ redis-server path/to/redis-sentinel.conf --sentinel
```

### 設定

Redis自体の設定と同様に、ソースに設定のサンプルが含まれるため、これをベースに作るといい。
([ex. 3.0 sentinel.conf](https://raw.githubusercontent.com/antirez/redis/3.0/sentinel.conf))

センチネル関連の設定は、`sentinel`ディレクティブを用いる。
方針としては、

- 監視対象のマスターごとに、そのグループ名を含む設定を定義していく
- スレーブに関する情報は自動検出されるため、設定しなくていい

設定には、__quorum__という概念が出て来る。
quorumは、__いくつのセンチネルが異常を発見したら、障害発生とみなすのか__、その数を意味する。

以下、主要な設定項目を抜粋:


```conf:sentinel.conf

# ポートを指定
port 26379

# グループAを定義
# 指定のIP/ポートで接続し、2台のセンチネルが障害を観測した時点でフェールオーバする
sentinel monitor groupA 192.168.0.10 6379 2

# sentinelへの接続用のパスを設定
# requirepassの設定が優先される様子
sentinel auth-pass groupA some_password

# 障害発生とみなすためのタイムアウト時間を60,000msecに設定
sentinel down-after-milliseconds groupA 60000

# フェイルオーバー失敗時の再試行までの時間を180,000msecに設定
sentinel failover-timeout groupA 180000

# フェイルオーバー時に接続するスレーブの数
# この数は少ないほど、フェイルオーバーに時間がかかる
sentinel parallel-syncs groupA 1
```

### 接続

センチネルへの接続は、Redisと同様に`redis-cli`を使って行う。
(あるいはセンチネルに対応したバインディングAPIを用いる)


```bash
# センチネルに接続する
$ redis-cli -p 26379
```

接続後、`SENTINEL`コマンドによって接続先を指定できる。

```
# groupAのマスタの情報を問い合せ
> SENTINEL master groupA
=> 1) "name"
=> 2) "groupA"
=> 3) "ip"
=> 4) "127.0.0.1"
=> 5) "port"
=> 6) "6379"
=> ...

# IPとポートのみ問い合わせ
> SENTINEL get-master-addr-by-name groupA
=> 1) "127.0.0.1"
=> 2) "6379"

# 同様にスレーブの一覧を問い合せ
> SENTINEL slaves groupA

# 監視しているセンチネルの一覧を問い合わせ
> SENTINEL sentinels groupA


# フェールオーバーをテストしたい場合はDEBUGを使う
> DEBUG sleep 30

# 強制フェールオーバーもできる
> SENTINEL failover groupA
```


未調査項目
------------------------------------------------------------
- 通知とイベントハンドリング
- Docker, 仮想マシン等のNAT環境下での設定
- LUAスクリプト
- 監視と計測、パフォーマンスチューン


## 参考
- [Redis(公式)](https://redis.io/)
    - [Commands](https://redis.io/commands)
    - [Redis configuration](https://redis.io/topics/config)
    - [Redis Security](https://redis.io/topics/security)
    - [Redis Encryption](https://redis.io/topics/encryption)
    - [Redis Persistence](https://redis.io/topics/persistence)
    - [Replication](https://redis.io/topics/replication)
    - [Redis Sentinel Documentation](https://redis.io/topics/sentinel)