【保存版】Redis Sentinelで実現する高可用性Redis環境の構築と運用 – 7つの実践ポイント

Redis Sentinelとは?システム安定性を支える重要機能を解説

Redis Sentinelが解決する3つの課題

Redis Sentinelは、Redisクラスター環境における高可用性(HA)を実現するための監視・制御システムです。主に以下の3つの重要な課題を解決します:

  1. 自動フェイルオーバーの実現
  • マスターノードの障害を即時に検知
  • スレーブノードから最適な新マスターを自動選出
  • クライアントアプリケーションの接続先を自動切り替え
  • フェイルオーバー完了までの時間を最小化(通常数秒〜数十秒)
  1. 継続的な監視とアラート
  • 各Redisインスタンスの死活監視
  • レプリケーション状態の監視
  • ネットワーク分断の検知
  • 異常検知時の通知機能
  1. クラスター構成の自動管理
  • マスター/スレーブ関係の動的管理
  • 設定変更の自動同期
  • クラスタートポロジーの維持と最適化
  • 新規ノードの自動検出と統合

従来のRedis構成との比較でわかるメリット

従来のRedis構成と比較して、Sentinelを導入することで以下のような明確なメリットが得られます:

  1. システム可用性の大幅な向上
評価項目従来の構成Sentinel構成
障害検知手動または外部監視ツールリアルタイム自動検知
フェイルオーバー手動切り替え必要完全自動化
ダウンタイム検知〜復旧まで長時間数秒〜数十秒に短縮
24時間運用運用チームの常時待機が必要自動化による省人化
  1. 運用管理の効率化
  • 監視作業の自動化による運用負荷の軽減
  • 障害対応の標準化と自動化
  • 構成変更作業の簡素化
  • 運用ドキュメントの簡略化
  1. システムの信頼性向上
  • 単一障害点の排除
  • 分散アーキテクチャによる耐障害性の向上
  • データ整合性の自動検証
  • 障害復旧時間の予測可能性
  1. スケーラビリティの確保
  • 読み取りスケールアウトの容易な実現
  • ノードの動的追加・削除のサポート
  • 地理分散構成への対応
  • 段階的な性能拡張の実現

Sentinelノードは以下のような分散構成を取ることで、監視システム自体の信頼性も確保しています:

         +----------------+
         | Sentinel Node 1|
         +----------------+
                |
+----------+    |    +----------+
|  Redis   |----+----+  Redis   |
|  Master  |    |    |  Slave   |
+----------+    |    +----------+
                |
         +----------------+
         | Sentinel Node 2|
         +----------------+

このように、Redis Sentinelは単なる監視ツールではなく、Redisクラスターの自律的な運用を実現する統合管理システムとして機能します。特に重要な業務システムやサービスレベルアグリーメント(SLA)の厳しい環境において、その価値を最大限に発揮します。

Redis Sentinelのアーキテクチャ詳解

マスター・スレーブ構成の仕組み

Redis Sentinelにおけるマスター・スレーブ構成は、以下の要素で構成されています:

  1. 基本構成要素
  • マスターノード:書き込み/読み取り可能な主ノード
  • スレーブノード:読み取り専用の複製ノード
  • Sentinelノード:監視・制御を行う管理ノード
  1. データレプリケーションの流れ
   [クライアント] → [マスターノード] 
                    ↓ レプリケーション
                 [スレーブノード1]
                 [スレーブノード2]
  1. 同期の仕組み
  • 初期同期:スレーブ追加時のフルデータ同期
  • 差分同期:通常運用時の変更データのみ同期
  • バックログ管理:切断時の再同期用データ保持

フェイルオーバーの動作プロセス

フェイルオーバーは以下の5つのステップで実行されます:

  1. 障害検知フェーズ
  • Sentinelによる定期的なヘルスチェック
  • PING応答のタイムアウト監視
  • 主観的ダウン(SDOWN)状態の判定
  1. 合意形成フェーズ
  • 複数のSentinelによる状態確認
  • 客観的ダウン(ODOWN)状態の判定
  • クォーラム達成の確認
  1. リーダー選出フェーズ
  • Raft合意アルゴリズムによるリーダーSentinel選出
  • 選出されたSentinelがフェイルオーバーを主導
  • 二重フェイルオーバーの防止
  1. 新マスター選出フェーズ
   選出基準:
   1. レプリケーション遅延が最小
   2. 優先度が最高
   3. レプリケーションIDが最新
   4. ランタイムID(数値的に小さい方)
  1. 構成変更フェーズ
  • 新マスターの昇格処理
  • 他スレーブの再接続
  • クライアント接続の切り替え

Sentinelノードの役割と必要数

  1. 主要な役割
  • 監視:各Redisノードの状態監視
  • 通知:管理者への障害通知
  • 自動フェイルオーバー:障害時の自動復旧
  • 構成プロバイダー:クライアントへの接続情報提供
  1. 推奨されるノード数 デプロイメント規模 推奨Sentinel数 クォーラム値 開発環境 3 2 小規模本番環境 3〜5 2〜3 大規模本番環境 5〜7 3〜4 地理分散環境 7以上 4以上
  2. 配置の考慮点
  • 異なる物理サーバーへの分散配置
  • ネットワークセグメントの分散
  • 電源系統の分散
  • データセンターをまたぐ配置
  1. パフォーマンスへの影響
   監視間隔:1秒
   タイムアウト:30秒(デフォルト)
   ネットワーク帯域:約1KB/秒/ノード
   CPU使用率:1%未満(通常時)
  1. 高度な設定オプション
  • ダウン検知のタイムアウト調整
  • フェイルオーバー実行の条件設定
  • スクリプトによる外部連携
  • カスタム通知の設定

このようなアーキテクチャにより、Redis Sentinelは高い信頼性と可用性を実現しています。適切な構成とパラメータ設定により、さまざまな運用要件に対応することが可能です。

Redis Sentinel環境の構築手順

基本的なセットアップ手順と設定ファイル

  1. Redis本体のインストール
# Ubuntuの場合
sudo apt-get update
sudo apt-get install redis-server

# CentOSの場合
sudo yum install epel-release
sudo yum install redis
  1. マスターノードの設定(redis.conf)
# 基本設定
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis/redis-server.pid

# レプリケーション関連
requirepass "master_password"
masterauth "master_password"

# 永続化設定
appendonly yes
appendfilename "appendonly.aof"
  1. スレーブノードの設定
# 基本設定(redis.conf)
port 6380
daemonize yes
pidfile /var/run/redis/redis-server.pid

# レプリケーション設定
replicaof 192.168.1.100 6379
masterauth "master_password"
  1. Sentinelの設定(sentinel.conf)
# Sentinelの基本設定
port 26379
daemonize yes
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel auth-pass mymaster master_password

# フェイルオーバー関連設定
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

PHPアプリケーションからの接続設定

  1. Predisを使用した接続設定
// Composerでのインストール
// composer require predis/predis

// Sentinelを使用した接続設定
$sentinels = [
    'tcp://192.168.1.100:26379',
    'tcp://192.168.1.101:26379',
    'tcp://192.168.1.102:26379'
];

$options = [
    'replication' => 'sentinel',
    'service' => 'mymaster',
    'parameters' => [
        'password' => 'master_password'
    ]
];

try {
    $client = new Predis\Client($sentinels, $options);
    // 接続テスト
    $client->ping();
} catch (Exception $e) {
    // エラーハンドリング
    error_log('Redis接続エラー: ' . $e->getMessage());
}
  1. PhpRedisを使用した接続設定
// PhpRedisのインストール
// pecl install redis

// Sentinelを使用した接続
$redis = new Redis();
$sentinel = new RedisSentinel('192.168.1.100', 26379);

try {
    // マスターの取得
    $master = $sentinel->getMasterAddrByName('mymaster');

    // マスターへの接続
    $redis->connect($master[0], $master[1]);
    $redis->auth('master_password');
} catch (RedisException $e) {
    error_log('Sentinel接続エラー: ' . $e->getMessage());
}

動作確認とテスト方法

  1. 基本的な動作確認
# Sentinelの状態確認
redis-cli -p 26379
sentinel master mymaster

# マスターの状態確認
redis-cli -h 192.168.1.100 -p 6379 info replication

# スレーブの状態確認
redis-cli -h 192.168.1.101 -p 6380 info replication
  1. フェイルオーバーテスト
// PHPでのフェイルオーバーテストスクリプト
<?php
$redis = new Redis();
$sentinel = new RedisSentinel('192.168.1.100', 26379);

// 接続維持ループ
while (true) {
    try {
        $master = $sentinel->getMasterAddrByName('mymaster');
        $redis->connect($master[0], $master[1]);
        $redis->auth('master_password');

        // データ書き込みテスト
        $redis->set('test_key', date('Y-m-d H:i:s'));
        echo "書き込み成功: " . $redis->get('test_key') . "\n";

        sleep(1);
    } catch (Exception $e) {
        echo "エラー発生: " . $e->getMessage() . "\n";
        echo "再接続を試みます...\n";
        sleep(1);
    }
}
  1. チェックリスト
確認項目確認方法期待値
レプリケーション状態info replicationrole:master/slave
Sentinel監視状態sentinel master mymasterflags:master
フェイルオーバー動作マスター停止テスト自動切り替え
データ整合性キー値の比較全ノードで一致
性能レイテンシチェック1ms以下
  1. 監視項目の設定
# Sentinelの詳細な監視設定
sentinel notification-script mymaster /etc/redis/notify.sh
sentinel client-reconfig-script mymaster /etc/redis/reconfig.sh
sentinel down-after-milliseconds mymaster 5000

このような構成で、高可用性を備えたRedis Sentinel環境を構築することができます。実運用では、ネットワークの分離やセキュリティ設定なども考慮に入れる必要があります。

Redis Sentinelの運用ベストプラクティス

効果的なモニタリング方法

  1. システムメトリクスの監視
メトリクス監視項目警告閾値危険閾値
メモリ使用率used_memory_rss80%90%
CPU使用率cpu_sys70%85%
レプリケーション遅延master_repl_offset10005000
クライアント接続数connected_clients50008000
  1. Prometheusによる監視設定例
# prometheus.yml
scrape_configs:
  - job_name: 'redis_exporter'
    static_configs:
      - targets: ['localhost:9121']
    metrics_path: /metrics
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
  1. Grafanaダッシュボードの推奨パネル
  • マスター/スレーブの状態
  • フェイルオーバーの発生回数
  • コマンド実行レイテンシ
  • メモリ使用状況
  • ネットワークI/O

パフォーマンスチューニングのポイント

  1. メモリ管理の最適化
# redis.conf
maxmemory 8gb
maxmemory-policy allkeys-lru
maxmemory-samples 10

# システム設定
vm.overcommit_memory = 1
vm.swappiness = 0
  1. ネットワーク設定の最適化
# システム設定
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_keepalive_time = 300

# redis.conf
tcp-keepalive 300
tcp-backlog 65535
  1. 永続化設定の調整
# AOF設定
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# RDB設定
save 900 1
save 300 10
save 60 10000

障害検知の閾値設定

  1. Sentinel基本設定のチューニング
# sentinel.conf

# ダウン検知の基本設定
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000

# クォーラム設定
sentinel monitor mymaster 192.168.1.100 6379 2

# 並列同期数
sentinel parallel-syncs mymaster 1

# 通知スクリプト
sentinel notification-script mymaster /etc/redis/notify.sh
  1. 環境別の推奨閾値
環境down-after-millisecondsfailover-timeoutparallel-syncs
開発5000600001
ステージング100001800001
本番(標準)150003000001
本番(大規模)300006000002
  1. カスタムスクリプトの実装例
#!/bin/bash
# /etc/redis/notify.sh

# 障害通知スクリプト
EVENT_TYPE=$1
EVENT_DESC=$2
MASTER_NAME=$3
MASTER_IP=$4
MASTER_PORT=$5

# Slack通知
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"Redis Sentinel Event\nType: $EVENT_TYPE\nDesc: $EVENT_DESC\nMaster: $MASTER_NAME ($MASTER_IP:$MASTER_PORT)\"}" \
https://hooks.slack.com/services/YOUR/WEBHOOK/URL

# メール通知
echo "Redis Sentinel Event\nType: $EVENT_TYPE\nDesc: $EVENT_DESC\nMaster: $MASTER_NAME ($MASTER_IP:$MASTER_PORT)" | \
mail -s "Redis Sentinel Alert" admin@example.com
  1. 異常検知のベストプラクティス
  • 複数のSentinelノードでの合意形成を確認
  • ネットワーク分断を考慮した閾値設定
  • 誤検知を防ぐための適切な遅延設定
  • 環境に応じた段階的な閾値調整
  1. 監視設定の例(Zabbix)
# Zabbixトリガー設定
- 名前: Redis Sentinelマスターダウン
  条件: {redis.sentinel.master.status} = 0
  重要度: 高

- 名前: Redis Sentinelクォーラム未達
  条件: {redis.sentinel.quorum.status} < {$MIN_QUORUM}
  重要度: 警告

- 名前: Redisレプリケーション遅延
  条件: {redis.replication.delay} > 1000
  重要度: 警告

これらの設定と監視により、Redis Sentinelの安定運用が可能となります。実際の運用では、システムの規模や要件に応じて適切にカスタマイズすることが重要です。

PHPでのRedis Sentinel活用例

Predisを使用した実装例

  1. 基本的な接続設定
<?php
require 'vendor/autoload.php';

class RedisSentinelConnection {
    private $client;
    private $sentinels = [
        'tcp://192.168.1.100:26379',
        'tcp://192.168.1.101:26379',
        'tcp://192.168.1.102:26379'
    ];

    private $options = [
        'replication' => 'sentinel',
        'service' => 'mymaster',
        'parameters' => [
            'password' => 'master_password',
            'database' => 0
        ],
        'prefix' => 'app:',
    ];

    public function __construct() {
        try {
            $this->client = new Predis\Client($this->sentinels, $this->options);
        } catch (Exception $e) {
            $this->handleConnectionError($e);
        }
    }

    private function handleConnectionError($e) {
        error_log("Redis接続エラー: " . $e->getMessage());
        // リトライロジックやフォールバック処理を実装
    }

    public function getClient() {
        return $this->client;
    }
}
  1. セッション管理での活用例
<?php
class RedisSessionHandler implements SessionHandlerInterface {
    private $redis;
    private $ttl;

    public function __construct(RedisSentinelConnection $connection, $ttl = 3600) {
        $this->redis = $connection->getClient();
        $this->ttl = $ttl;
    }

    public function open($path, $name): bool {
        return true;
    }

    public function close(): bool {
        return true;
    }

    public function read($id): string {
        $data = $this->redis->get("session:$id");
        return $data ?: '';
    }

    public function write($id, $data): bool {
        return $this->redis->setex("session:$id", $this->ttl, $data);
    }

    public function destroy($id): bool {
        $this->redis->del("session:$id");
        return true;
    }

    public function gc($max_lifetime): bool {
        return true; // Redisの有効期限機能により自動的に処理
    }
}

// 使用例
$connection = new RedisSentinelConnection();
$handler = new RedisSessionHandler($connection);
session_set_save_handler($handler, true);
session_start();
  1. キャッシュシステムの実装例
<?php
class RedisCache {
    private $redis;
    private $defaultTtl;

    public function __construct(RedisSentinelConnection $connection, $defaultTtl = 3600) {
        $this->redis = $connection->getClient();
        $this->defaultTtl = $defaultTtl;
    }

    public function get($key) {
        try {
            $value = $this->redis->get($key);
            return $value ? json_decode($value, true) : null;
        } catch (Exception $e) {
            error_log("キャッシュ取得エラー: " . $e->getMessage());
            return null;
        }
    }

    public function set($key, $value, $ttl = null) {
        try {
            $ttl = $ttl ?: $this->defaultTtl;
            $serialized = json_encode($value);
            return $this->redis->setex($key, $ttl, $serialized);
        } catch (Exception $e) {
            error_log("キャッシュ設定エラー: " . $e->getMessage());
            return false;
        }
    }
}

PhpRedisでの接続方法

  1. 基本的な接続処理
<?php
class RedisSentinelManager {
    private $sentinels = [
        ['host' => '192.168.1.100', 'port' => 26379],
        ['host' => '192.168.1.101', 'port' => 26379],
        ['host' => '192.168.1.102', 'port' => 26379]
    ];

    private $masterName = 'mymaster';
    private $password = 'master_password';

    public function getMasterConnection(): Redis {
        $redis = new Redis();

        foreach ($this->sentinels as $sentinel) {
            try {
                $sentinel = new RedisSentinel($sentinel['host'], $sentinel['port']);
                $master = $sentinel->getMasterAddrByName($this->masterName);

                if ($master) {
                    $redis->connect($master[0], $master[1]);
                    $redis->auth($this->password);
                    return $redis;
                }
            } catch (RedisException $e) {
                continue;
            }
        }

        throw new Exception('利用可能なマスターが見つかりません');
    }
}

エラーハンドリングのベストプラクティス

  1. リトライメカニズムの実装
<?php
class RedisRetryWrapper {
    private $connection;
    private $maxRetries;
    private $retryDelay;

    public function __construct($connection, $maxRetries = 3, $retryDelay = 100) {
        $this->connection = $connection;
        $this->maxRetries = $maxRetries;
        $this->retryDelay = $retryDelay;
    }

    public function executeWithRetry(callable $operation) {
        $attempts = 0;
        $lastException = null;

        while ($attempts < $this->maxRetries) {
            try {
                return $operation($this->connection);
            } catch (Exception $e) {
                $lastException = $e;
                $attempts++;

                if ($attempts < $this->maxRetries) {
                    usleep($this->retryDelay * 1000 * $attempts);
                    $this->reconnect();
                }
            }
        }

        throw new Exception(
            "操作が失敗しました。試行回数: $attempts, " .
            "最後のエラー: " . $lastException->getMessage()
        );
    }

    private function reconnect() {
        // 再接続ロジックの実装
    }
}

// 使用例
$wrapper = new RedisRetryWrapper($redisConnection);
$result = $wrapper->executeWithRetry(function($redis) {
    return $redis->get('important_key');
});
  1. サーキットブレーカーパターンの実装
<?php
class RedisCircuitBreaker {
    private $failureThreshold;
    private $resetTimeout;
    private $failures = 0;
    private $lastFailureTime = 0;
    private $state = 'CLOSED';

    public function __construct($failureThreshold = 5, $resetTimeout = 60) {
        $this->failureThreshold = $failureThreshold;
        $this->resetTimeout = $resetTimeout;
    }

    public function execute(callable $operation) {
        $this->checkState();

        if ($this->state === 'OPEN') {
            throw new Exception('Circuit Breaker is OPEN');
        }

        try {
            $result = $operation();
            $this->recordSuccess();
            return $result;
        } catch (Exception $e) {
            $this->recordFailure();
            throw $e;
        }
    }

    private function checkState() {
        if ($this->state === 'OPEN' && 
            time() - $this->lastFailureTime >= $this->resetTimeout) {
            $this->state = 'HALF-OPEN';
        }
    }

    private function recordSuccess() {
        if ($this->state === 'HALF-OPEN') {
            $this->state = 'CLOSED';
            $this->failures = 0;
        }
    }

    private function recordFailure() {
        $this->failures++;
        $this->lastFailureTime = time();

        if ($this->failures >= $this->failureThreshold) {
            $this->state = 'OPEN';
        }
    }
}

これらの実装例により、PHPアプリケーションでRedis Sentinelを効果的に活用することができます。実際の運用では、システムの要件に応じて適切にカスタマイズすることが重要です。

Redis Sentinelのトラブルシューティング

よくある障害パターンと対処法

  1. フェイルオーバーの失敗
症状考えられる原因対処方法
フェイルオーバーが開始されないクォーラム不足Sentinelの稼働数確認と復旧
フェイルオーバーが途中で停止ネットワーク分断ネットワーク状態の確認と修復
誤ったフェイルオーバー発生タイムアウト設定が厳しすぎるdown-after-millisecondsの調整
# フェイルオーバーの状態確認
redis-cli -p 26379
sentinel masters    # マスターの状態確認
sentinel slaves mymaster    # スレーブの状態確認

# クォーラムの確認
redis-cli -p 26379 sentinel ckquorum mymaster
  1. レプリケーション遅延

確認コマンド:

# マスターでの確認
redis-cli -h master_host info replication

# スレーブでの確認
redis-cli -h slave_host info replication | grep -E "master_repl_offset|slave_repl_offset"

対処方法:

# redis.conf(スレーブ側)
client-output-buffer-limit slave 256mb 64mb 60
repl-backlog-size 512mb
  1. メモリ関連の問題
# メモリ使用状況の確認
redis-cli info memory

# メモリポリシーの確認と設定
redis-cli config get maxmemory-policy
redis-cli config set maxmemory-policy allkeys-lru

ログ解析のポイント

  1. 重要なログパターン
# Sentinelログ
+sdown    # 主観的ダウンの検知
+odown    # 客観的ダウンの検知
+try-failover    # フェイルオーバー試行
+failover-state    # フェイルオーバー状態の変更
+switch-master    # マスター切り替えの実行
  1. ログ収集と分析ツール設定
# fluent.conf
<source>
  @type tail
  path /var/log/redis/sentinel.log
  tag redis.sentinel
  <parse>
    @type regexp
    expression /(?<time>\d{1,2}:\d{1,2}:\d{1,2}) (?<pid>\d+):(?<role>[X,C,S]) (?<message>.*)/
  </parse>
</source>

<match redis.sentinel>
  @type elasticsearch
  host elasticsearch.example.com
  port 9200
  index_name redis-sentinel-logs
  type_name redis_log
</match>
  1. 監視すべきログメッセージ
ログパターン重要度対応方法
+sdown警告対象ノードの状態確認
+odown重要即時対応が必要
-sdown情報復旧の確認
+switch-master重要フェイルオーバーの検証
+tilt緊急Sentinelの状態確認

パフォーマンス低下時の改善手順

  1. 性能診断手順
# レイテンシの確認
redis-cli --latency-history

# スロークエリの特定
redis-cli slowlog get 10

# クライアント接続状況
redis-cli info clients

# メモリ断片化の確認
redis-cli info memory | grep fragmentation
  1. パフォーマンス改善設定
# redis.conf
# メモリ最適化
maxmemory-policy allkeys-lru
maxmemory-samples 10

# レプリケーション最適化
repl-backlog-size 512mb
repl-backlog-ttl 3600

# 永続化設定の調整
appendfsync everysec
no-appendfsync-on-rewrite yes
  1. システムチューニング
# システム設定の最適化
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo 1 > /proc/sys/vm/overcommit_memory
echo 512 > /proc/sys/net/core/somaxconn

# ディスクI/O設定
echo deadline > /sys/block/sda/queue/scheduler
  1. モニタリングスクリプト例
<?php
// パフォーマンスモニタリングスクリプト
function checkRedisPerformance($host, $port) {
    $redis = new Redis();
    $redis->connect($host, $port);

    $metrics = [
        'latency' => microtime(true),
        'memory' => $redis->info('memory'),
        'clients' => $redis->info('clients'),
        'stats' => $redis->info('stats')
    ];

    // レイテンシチェック
    $redis->ping();
    $metrics['latency'] = (microtime(true) - $metrics['latency']) * 1000;

    // 結果の解析と報告
    if ($metrics['latency'] > 100) {
        error_log("High latency detected: {$metrics['latency']}ms");
    }

    if ($metrics['memory']['used_memory_rss'] > 8589934592) { // 8GB
        error_log("High memory usage detected");
    }

    return $metrics;
}
  1. パフォーマンス改善チェックリスト
  • [ ] メモリ使用率の確認と最適化
  • [ ] ネットワークレイテンシの測定
  • [ ] クライアント接続数の適正化
  • [ ] スロークエリの特定と改善
  • [ ] レプリケーション遅延の確認
  • [ ] システムリソースの確認
  • [ ] ディスクI/Oの最適化
  • [ ] バックグラウンド処理の影響確認

これらのトラブルシューティング手法を活用することで、Redis Sentinelの安定運用が可能となります。定期的なログ解析とモニタリングを行い、問題の早期発見と対応を心がけることが重要です。

Redis Sentinelの発展的な使い方

大規模システムでの構成例

  1. マルチデータセンター構成
[データセンターA]
    Master Redis
    └── Slave Redis
    └── Sentinel (3台)

[データセンターB]
    Slave Redis
    └── Sentinel (3台)

[データセンターC]
    Slave Redis
    └── Sentinel (3台)

設定例:

# sentinel.conf (DC-A)
sentinel monitor mymaster 10.0.1.100 6379 5
sentinel known-sentinel mymaster 10.0.2.100 26379 dc2
sentinel known-sentinel mymaster 10.0.3.100 26379 dc3

# データセンター間の通信設定
sentinel announce-ip 10.0.1.100
sentinel announce-port 26379
  1. シャーディング構成
<?php
// シャーディング実装例
class RedisShardedSentinel {
    private $shards;
    private $totalShards;

    public function __construct($shardConfigs) {
        $this->totalShards = count($shardConfigs);
        foreach ($shardConfigs as $shardId => $config) {
            $this->shards[$shardId] = new RedisSentinelConnection(
                $config['sentinels'],
                $config['master_name']
            );
        }
    }

    public function get($key) {
        $shardId = $this->getShardId($key);
        return $this->shards[$shardId]->get($key);
    }

    private function getShardId($key) {
        return crc32($key) % $this->totalShards;
    }
}

クラウド環境での構築ポイント

  1. AWS環境での構成例
# Terraform設定例
resource "aws_elasticache_replication_group" "redis_cluster" {
  replication_group_id          = "redis-sentinel-cluster"
  replication_group_description = "Redis with Sentinel"
  node_type                    = "cache.r5.large"
  number_cache_clusters        = 3
  automatic_failover_enabled   = true

  cluster_mode {
    replicas_per_node_group = 2
    num_node_groups         = 1
  }
}

resource "aws_security_group" "redis_security_group" {
  name        = "redis-sentinel-sg"
  description = "Security group for Redis Sentinel"

  ingress {
    from_port   = 6379
    to_port     = 6379
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }

  ingress {
    from_port   = 26379
    to_port     = 26379
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }
}
  1. Kubernetes環境での構成
# redis-sentinel-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-sentinel
spec:
  serviceName: redis-sentinel
  replicas: 3
  selector:
    matchLabels:
      app: redis-sentinel
  template:
    metadata:
      labels:
        app: redis-sentinel
    spec:
      containers:
      - name: redis
        image: redis:6.2
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: redis-data
          mountPath: /data
      - name: sentinel
        image: redis:6.2
        command: ["redis-sentinel", "/etc/redis/sentinel.conf"]
        volumeMounts:
        - name: sentinel-config
          mountPath: /etc/redis
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

監視システムとの連携方法

  1. Prometheusとの連携
# prometheus.yml
scrape_configs:
  - job_name: 'redis_exporter'
    static_configs:
      - targets:
        - 'redis-exporter:9121'
    metrics_path: /metrics
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance

# Grafanaダッシュボード設定
{
  "panels": [
    {
      "title": "Redis Sentinel Status",
      "type": "stat",
      "targets": [
        {
          "expr": "redis_sentinel_masters",
          "legendFormat": "Masters"
        }
      ]
    },
    {
      "title": "Failover Events",
      "type": "graph",
      "targets": [
        {
          "expr": "rate(redis_sentinel_failover_total[5m])",
          "legendFormat": "Failovers/min"
        }
      ]
    }
  ]
}
  1. アラート設定
# alertmanager.yml
groups:
- name: redis_sentinel_alerts
  rules:
  - alert: RedisSentinelQuorumLost
    expr: redis_sentinel_quorum < 2
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "Sentinel quorum lost"
      description: "Redis Sentinel quorum is below minimum threshold"

  - alert: RedisSentinelNoMaster
    expr: redis_sentinel_masters == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "No Redis master available"
  1. カスタム監視スクリプト
<?php
// Sentinelヘルスチェックスクリプト
class SentinelHealthCheck {
    private $sentinels;
    private $masterName;

    public function __construct($sentinels, $masterName) {
        $this->sentinels = $sentinels;
        $this->masterName = $masterName;
    }

    public function check() {
        $health = [
            'quorum' => 0,
            'master_status' => false,
            'slaves_count' => 0
        ];

        foreach ($this->sentinels as $sentinel) {
            try {
                $redis = new RedisSentinel(
                    $sentinel['host'],
                    $sentinel['port']
                );

                $master = $redis->master($this->masterName);
                if ($master) {
                    $health['quorum']++;
                    $health['master_status'] = true;
                    $health['slaves_count'] = count(
                        $redis->slaves($this->masterName)
                    );
                }
            } catch (Exception $e) {
                error_log("Sentinel health check error: " . $e->getMessage());
            }
        }

        return $health;
    }
}

// 使用例
$checker = new SentinelHealthCheck([
    ['host' => '10.0.1.100', 'port' => 26379],
    ['host' => '10.0.1.101', 'port' => 26379],
    ['host' => '10.0.1.102', 'port' => 26379]
], 'mymaster');

$health = $checker->check();

これらの発展的な使用方法により、Redis Sentinelを大規模システムやクラウド環境で効果的に活用することができます。実際の導入時には、システムの要件や規模に応じて適切な構成を選択することが重要です。