---
title: "Redis 冗長化への道 | grasys blog"
url: "https://blog.grasys.io/post/tokura/redis-redundancy"
description: "前書き こんにちは！ grasys2 年目エンジニアの tokura です。 前回記事を書いた時からほぼ 1 年くらい経ってますね。時の流れは早いものです。 さて、今回も直近の業務で触ったものをテーマに書いていきます。 今回のテーマはタイトルの通り「Redis 冗長化」です。Redis（valkey）、sentine…"
---

# Redis 冗長化への道

-   ![](/_astro/noicon.CTHOhNiB_1HMs6A.webp)[tokura](/authors/tokura/)
-   公開日：2024年11月14日
-   カテゴリー：[Tech](/categories/tech/)
-   タグ：[#Redis](/tags/redis/)[#Redundancy](/tags/redundancy/)

![Redis 冗長化への道](/_astro/hero.BRGi6e3D_Z1P1iXi.webp)

## 前書き

こんにちは！ grasys2 年目エンジニアの tokura です。

前回記事を書いた時からほぼ 1 年くらい経ってますね。時の流れは早いものです。

さて、今回も直近の業務で触ったものをテーマに書いていきます。

今回のテーマはタイトルの通り「Redis 冗長化」です。Redis（valkey）、sentinel、HAproxy を使います。

構成を初めて見た時に感心したことを思い出しました。同じ気持ちになる人の参考になればと思います。

以下が今回のサーバ構成です。

-   サーバ 0 HAproxy
    
-   サーバ 1 master & sentinel
    
-   サーバ 2 replica & sentinel
    
-   サーバ 3 sentinel & sentinel
    

全 4 台で OS は Rocky Linux9 です  
それではよろしくお願いします

## Redis（valkey）server 設定

Redis 冗長化と言っても、最近は Valkey を目にする機会が増え、せっかくなので valkey で進めます。

（違いは名前くらいしかないと思いますが…）

### ビルドインストール

homebrew とかパッケージでもできるみたいですが、サーバ 1 に[ソース](https://github.com/valkey-io/valkey/releases)をダウンロードしてインストール。

Plain textcontent\_copy

```
wget -P /usr/local/src https://github.com/valkey-io/valkey/archive/refs/tags/8.0.1.tar.gz

tar -zxvf /usr/local/src/8.0.1.tar.gz
cd /usr/local/src/valkey-8.0.1

make                   # オプションとか必要なら適宜ビルド時に追加
make install
```

ビルド後は間違えて redis-cli って入力しても使えるようリンクが貼られてます

Plain textcontent\_copy

```
# ll  /usr/local/bin/
total 29568
lrwxrwxrwx 1 root root       16 Nov  5 11:25 redis-benchmark -> valkey-benchmark
lrwxrwxrwx 1 root root       16 Nov  5 11:25 redis-check-aof -> valkey-check-aof
lrwxrwxrwx 1 root root       16 Nov  5 11:25 redis-check-rdb -> valkey-check-rdb
lrwxrwxrwx 1 root root       10 Nov  5 11:25 redis-cli -> valkey-cli
lrwxrwxrwx 1 root root       15 Nov  5 11:25 redis-sentinel -> valkey-sentinel
lrwxrwxrwx 1 root root       13 Nov  5 11:25 redis-server -> valkey-server
-rwxr-xr-x 1 root root  6381928 Nov  5 11:25 valkey-benchmark
lrwxrwxrwx 1 root root       13 Nov  5 11:25 valkey-check-aof -> valkey-server
lrwxrwxrwx 1 root root       13 Nov  5 11:25 valkey-check-rdb -> valkey-server
-rwxr-xr-x 1 root root  7084456 Nov  5 11:25 valkey-cli
lrwxrwxrwx 1 root root       13 Nov  5 11:25 valkey-sentinel -> valkey-server
-rwxr-xr-x 1 root root 16802304 Nov  5 11:25 valkey-server
```

### Service 化

インストールもできたことなので service として redis（valkey）-server を立ち上げます。

/usr/local/src/valkey8.0.1 内にデフォルトファイルがあるので活用。

自サーバ用に編集するために適当にディレクトリ作成して持ってきます。

Plain textcontent\_copy

```
mkdir /usr/local/etc/valkey
 cp /usr/local/src/valkey8.0.1/utils/systemd-valkey_server.service /usr/local/etc/valkey/valkey.service 
 cp /usr/local/etc/valkey/valkey.conf  /usr/local/etc/valkey/
```

conf は以下を設定。その他かなり設定項目ありますが、サーバスペックや使い方によって要変更です。

追加で項目が必要そうなら…ドキュメントに頼りましょう

Plain textcontent\_copy

```
bind 0.0.0.0 
port 6379 
protected-mode no 
daemonize yes
```

service も簡潔に以下

Plain textcontent\_copy

```
[Unit]
Wants=network-online.target
After=network-online.target

[Service]
Type=forking
User=root
Group=root
ExecStartPre=/bin/touch /var/log/valkey/valkey.log
ExecStart=/usr/local/bin/valkey-server /usr/local/var/config.d/valkey/valkey.conf

[Install]
WantedBy=multi-user.target
```

`/usr/local/bin/valkey-server /usr/local/var/config.d/valkey/valkey.conf`

サービスファイル内の↑の部分の conf について

複数サーバを建てる際に同じ service ファイルで構成できるように↓的なリンクを貼っています

`/usr/local/var/config.d/valkey/valkey.conf -> /usr/local/etc/valkey/valkey.conf`

（運用だとこんな感じで動かしてるプロセスが多くあって非常に勉強になります）

後は service ファイルを systemd へ設定できたら準備完了です。

`/etc/systemd/system/valkey.service -> /usr/local/etc/valkey/valkey.service`

Plain textcontent\_copy

```
# systemctl status valkey.service
● valkey.service - Valkey data structure server
     Loaded: loaded (/etc/systemd/system/valkey.service; linked; preset: disabled)
     Active: active (running) since Fri 2024-11-08 06:56:33 UTC; 3min 24s ago
       Docs: https://github.com/valkey-io/valkey-doc
    Process: 149437 ExecStartPre=/bin/touch /var/log/valkey/valkey.log (code=exited, status=0/SUCCESS)
    Process: 149439 ExecStart=/usr/local/bin/valkey-server /usr/local/var/config.d/valkey/valkey.conf (code=exited, status=0/SUCCESS)
   Main PID: 149441 (valkey-server)
      Tasks: 6 (limit: 23069)
     Memory: 8.9M
        CPU: 920ms
     CGroup: /system.slice/valkey.service
             └─149441 "/usr/local/bin/valkey-server 0.0.0.0:6379"

Nov 08 06:56:33 tokura-test-1 systemd[1]: Starting Valkey data structure server...
Nov 08 06:56:33 tokura-test-1 systemd[1]: Started Valkey data structure server.
```

### Replication

1 のサーバが無事起動したら次は replication させます。

サーバ 2 に、ほぼサーバ 1 と同様に設定して conf で以下のように設定して以下のようなリンクを貼ります。

Plain textcontent\_copy

```
replicaof <サーバー1の外部IP>  6379
```

`/usr/local/var/config.d/valkey/valkey.conf -> /usr/local/etc/valkey/valkey-replica.conf`

サーバ 2 起動前にサーバ 1 の Redis に適当に key を入れておくと replication の確認にもなります。

2 も同様に起動して両サーバの valkey-cli で様子を見ます。

Plain textcontent\_copy

```
#  redis-cli info replication
# Replication
role:master
connected_slaves:1
slave0:ip=<サーバー2の外部IP>,port=6379
```

Plain textcontent\_copy

```
# valkey-cli info replication
# Replication
role:slave
master_host:<サーバー1の外部IP>
master_port:6379
```

ここまでは Redis の設定です。

次は Sentinel を入れていきます。

## Sentinel

Sentinel はレプリケーションしている Redis マスターに障害が発生して通信ができなくなった場合に「マスターがダウンした」と検知し、フェイルオーバーを実行する機能を持ちます

詳しい仕組みや設定については[公式](https://valkey.io/topics/sentinel/)を確認してください

### Sentinel の構成と 3 台目の必要性

`valkey-server` をインストールすると、`valkey-sentinel` も設定されているため、この Sentinel を利用してマスター監視とフェイルオーバー設定ができます。

ただし、Sentinel は 2 台構成ではフェイルオーバーに支障が出る場合があります。

フェイルオーバーを実行するには、Sentinel のグループ内で**過半数**の同意が必要なため、2 台だけで構成していると以下のようなリスクがあります

-   Sentinel が 2 台だけの構成で、1 台に入ってるマスターRedis と Sentinel がダウンした場合、残った 1 台の Sentinel ではフェイルオーバーを実行できない。

この問題を避けるために、3 台目の Sentinel をサーバ 3 に追加します。3 台構成にすることで、1 台のマスター Redis と Sentinel がダウンしても、残りの 2 台の Sentinel で過半数が確保でき、正しくフェイルオーバーが実行され、レプリカが新しいマスターに昇格されます。

#### conf と service

conf について server 設定時と同様に sentinel ディレクトリでも作成して conf ファイルを作成します。

Plain textcontent\_copy

```
mkdir /usr/local/etc/sentinelcp /usr/local/src/valkey8.0.1/sentinel.conf /usr/local/etc/sentinel/
```

service ファイルも同様です。`valkey-server` から↓のように書き換えるくらいで動きます。

Plain textcontent\_copy

```
ExecStartPre=/bin/touch /var/log/valkey/sentinel.logExecStart=/usr/local/bin/valkey-sentinel /usr/local/var/config.d/valkey/sentinel.conf
```

conf に関して今回は以下のように設定。

Plain textcontent\_copy

```
protected-mode no
port 26379
daemonize yes
pidfile "/var/run/valkey-sentinel.pid"
loglevel notice
logfile "/var/log/valkey/sentinel.log"
dir "/tmp"

sentinel monitor mymaster <サーバー1の外部IP> 6379 2

sentinel failover-timeout mymaster 10000

acllog-max-len 128

sentinel resolve-hostnames no
sentinel announce-hostnames no
```

sentinel で見るホストを hostname で取れるオプションもあるのでサーバ構成に応じて使ってください…

server設定の時はリンクで設定していたが、今回は `/usr/local/var/config.d/valkey/sentinel.conf` へ直接コピーする。理由は後述。

conf ファイルなどが設定できたら起動を確認。

Plain textcontent\_copy

```
# systemctl status sentinel.service
● sentinel.service - Valkey data structure server
     Loaded: loaded (/etc/systemd/system/sentinel.service; linked; preset: disabled)
     Active: active (running) since Fri 2024-11-08 07:50:47 UTC; 7s ago
```

この時 conf を見ると以下のような追記がされている

Plain textcontent\_copy

```
# Generated by CONFIG REWRITE
latency-tracking-info-percentiles 50 99 99.9
user default on nopass sanitize-payload ~* &* +@all
sentinel myid 4a81bfa9cffc81e0bb3122db27f21381f4b64b06
sentinel config-epoch mymaster 2
sentinel leader-epoch mymaster 2
sentinel current-epoch 2
```

Sentinel の conf を Redis のようにリンクではなくコピーしたのは、Sentinel 起動後に sentinel の conf に対してサーバ固有の追記が行われるためでした。

### FO 確認

Sentinel の起動が確認できたらフェイルオーバーを確認します。

サーバ 3 で `tail -f /var/log/valkey/sentinel.log` でログでも見ながら

Redis マスターのサーバ 1 で Redis を止めて、再度起動してみます。

すると sentinel.log で `+sdown` やら `+odown` ,`+switch-master` やらと FO が発生してそうなログが流れています。

replica だったサーバ 2 で確認してみると

Plain textcontent\_copy

```
 redis-cli info replication
# Replication
role:master
```

たしかに昇格しています。

ここでサーバ 3 の sentinel を止めて、sentinel を 2 台にした上でサーバ 2 の redis を止めてみます

Plain textcontent\_copy

```
# redis-cli info replication
# Replication
role:slave
master_host:<サーバー2の外部IP>
master_port:6379
master_link_status:down
```

昇格できません。もう一度サーバ 3 の Sentinel を動かすとあっさり昇格してくれました。sentinel サーバが 3 台ないと FO してくれないことが確認できました。

このままでも master が落ちたら勝手に切り替わって冗長じゃないか？と思ってたんですが、さらに上がありました。

## HAproxy の設定

HAproxy を使用することでより冗長な構成になります。

HAproxy は負荷分散およびプロキシサーバに用いられる OSS です。詳細は[公式](https://www.haproxy.org/)を参照ください。

#### ダウンロード

今回自分はパッケージマネージャで入れましたが、インストールしたい希望のバージョンある場合はソースから

Plain textcontent\_copy

```
# dnf info haproxy
Last metadata expiration check: 2:35:00 ago on Fri 08 Nov 2024 05:46:34 AM UTC.
Available Packages
Name         : haproxy
Version      : 2.4.22

# dnf install haproxy　-y
```

#### conf と service

インストール完了したら service から conf の場所を確認します

Plain textcontent\_copy

```
systemctl status haproxy
○ haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; preset: disabled)
```

Plain textcontent\_copy

```
[Unit]
Description=HAProxy Load Balancer
After=network-online.target
Wants=network-online.target

[Service]
EnvironmentFile=-/etc/sysconfig/haproxy
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "CFGDIR=/etc/haproxy/conf.d"
ExecStartPre=/usr/sbin/haproxy -f $CONFIG -f $CFGDIR -c -q $OPTIONS
ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -f $CFGDIR -p $PIDFILE $OPTIONS
ExecReload=/usr/sbin/haproxy -f $CONFIG -f $CFGDIR -c -q $OPTIONS
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
SuccessExitStatus=143
Type=notify

[Install]
WantedBy=multi-user.target
```

`/etc/haproxy/haproxy.cfg`

↑cfg を設定します。今回サーバ 0 のみですが HAproxy を多く設定するサーバがある場合は conf 分けてredis同様にリンクをここに貼った方が管理が楽になります。

以下 cfg デフォルトに書き加えたところ

Plain textcontent\_copy

```
frontend redis_frontend
    bind *:6379
    mode tcp
    default_backend redis_backend

backend redis_backend
    mode tcp
    option tcp-check
    tcp-check connect
    tcp-check send PING\r\n
    tcp-check expect string +PONG
    tcp-check send info\ replication\r\n
    tcp-check expect string role:master
    server test-1 <サーバー1の外部IP>:6379 check inter 1s
    server test-2 <サーバー2の外部IP>:6379 check inter 1s

listen stats
    bind :9000
    maxconn 16
    mode http
    stats enable
    stats uri /stats
    stats refresh 5s
```

追記後は HAproxy 再起動します

すると HAproxy が動いているサーバでは `redis-cli -p 6379` で IP を気にせず常に Redis の master を参照できるようになります。

可用性と冗長性が確保された環境で、安心して Redis を活用できるようになりました。

ちなみに最後の listen 部分を設定すると `http://<instance-Ip>:9000/stats` で proxy 状態がブラウザから確認できます。

以下 FO した後の様子で、test1 が赤く DOWN に、test2 が緑で UP になっているのが見えます。

![conf と serviceの画面](/_astro/01-Statistics_Report_for_HAProxy-1024x293-5964917a.Bcn-C8Tf_hucE0.webp)

## あとがき

以上が自分が歩んだ Redis の冗長化への道でした。

こうした方がモダンで良いよ！効率的でしょ！！などのアイデアありましたら、ぜひご教示ください！！！

大変勉強になります。

現在の目標としては、構築の時はより冗長かつ安定でいて運用が楽な構築を、運用の時は効率よく安全に、を目標として日々邁進中です。

grasys では、いろんな技術を見て触れる機会が多いのでエンジニアとしてとても充実した毎日を過ごしています。

また機会があれば何卒よろしくお願いいたします！！

## この記事を書いた人

[![](/_astro/noicon.CTHOhNiB_Z24aAgM.webp)](/authors/tokura/)

### [tokura](/authors/tokura/)

tokuraのプロフィールと執筆記事をご覧いただけます。

[プロフィールと記事一覧](/authors/tokura/)