Skip to content
Published on

Redis 7 クラスタ運用とメモリ最適化ハンドブック 2026

Authors
  • Name
    Twitter
Redis 7 クラスタ運用とメモリ最適化ハンドブック 2026

概要

Redisはインメモリデータストアの代表格として、キャッシングからセッション管理、リアルタイム分析、メッセージブローカーまで幅広く活用されている。Redis 7以降、Functions、ACL v2、Multi-Part AOFなど運用安定性とプログラマビリティを大幅に強化する機能が追加され、2025年にはAGPLv3ライセンスへの転換とともにエコシステムにも大きな変化があった。Valkey、KeyDBなどの代替手段が台頭し、インメモリデータストアの選択肢が多様化した状況である。

本ハンドブックではRedis 7.xベースのクラスタのアーキテクチャ設計からハッシュスロットのリバランシング、メモリ最適化戦略、データ構造別エンコーディングチューニング、永続化設定、モニタリング、障害復旧まで、実務運用に必要な全プロセスを扱う。各セクションには実践的なコマンドと設定例を含め、即座に適用可能なガイドを提供する。

Redis 7 の主要変更点

Redis Functions

Redis 7で導入されたFunctionsは、既存のEVALベースのLuaスクリプティングを置き換えるファーストクラスシチズンのプログラミングモデルである。FunctionsはRDBとAOFファイルとともに保存され、マスターからレプリカへ自動的に複製される。1つのライブラリに複数の関数を定義でき、コードの再利用性が高い。

#!lua name=mylib

-- 閲覧数の増加と閲覧履歴をアトミックに処理する関数
redis.register_function('increment_view', function(keys, args)
  local current = redis.call('HINCRBY', keys[1], 'views', 1)
  redis.call('ZADD', keys[1] .. ':history', redis.call('TIME')[1], args[1])
  return current
end)
# ライブラリのロード
cat mylib.lua | redis-cli -x FUNCTION LOAD REPLACE

# 関数の呼び出し
redis-cli FCALL increment_view 1 article:1001 "user:42"

# 登録済み関数一覧の確認
redis-cli FUNCTION LIST

ACL v2

ACL v2はキー単位で読み取り/書き込み権限を細かく制御できる機能を追加した。セレクター(Selector)の概念を導入し、1つのユーザーに複数のルールセットを付与できる。ルートセレクターが最初に評価され、追加セレクターが順番に適用される。

# キャッシュ専用ユーザー:cache:*キーに読み書き、session:*キーに読み取りのみ許可
redis-cli ACL SETUSER cache_worker on >StrongP@ss123 \
  ~cache:* +@all \
  (~session:* %R~session:* +@read)

# ACLルールの確認
redis-cli ACL GETUSER cache_worker

# 現在のACLリストをファイルに保存
redis-cli ACL SAVE

Multi-Part AOF

従来はAOFリライトプロセスで1つの大きなファイルを置き換える方式だったが、Redis 7のMulti-Part AOFは専用ディレクトリにbaseファイル(全データ)とincrファイル(増分データ)を分離して保存する。これによりディスク容量の無駄を削減し、AOF履歴管理が体系化された。

クラスタアーキテクチャ

Redis Clusterはデータを複数のノードに分散(シャーディング)して水平スケーラビリティを確保する分散アーキテクチャである。各マスターノードは16,384個のハッシュスロットの一部を担当し、クライアントはキーのCRC16ハッシュを通じて該当スロットのノードに直接アクセスする。

最小6ノードのクラスタ構成

プロダクション環境で推奨される最小構成はマスター3台+レプリカ3台の合計6ノードである。

# 6つのRedisインスタンスの設定(ポート7000〜7005)
for port in 7000 7001 7002 7003 7004 7005; do
  mkdir -p /opt/redis-cluster/${port}
  cat > /opt/redis-cluster/${port}/redis.conf << CONF
port ${port}
cluster-enabled yes
cluster-config-file nodes-${port}.conf
cluster-node-timeout 5000
appendonly yes
appendfilename "appendonly.aof"
dir /opt/redis-cluster/${port}
maxmemory 4gb
maxmemory-policy allkeys-lfu
bind 0.0.0.0
protected-mode no
save 3600 1 300 100 60 10000
aof-use-rdb-preamble yes
CONF
  redis-server /opt/redis-cluster/${port}/redis.conf &
done

# クラスタ作成(マスター3 + レプリカ3)
redis-cli --cluster create \
  192.168.1.10:7000 192.168.1.10:7001 192.168.1.10:7002 \
  192.168.1.10:7003 192.168.1.10:7004 192.168.1.10:7005 \
  --cluster-replicas 1

Redis vs Valkey vs KeyDB 比較

2024年のRedisのライセンス変更(RSAL2/SSPLから後にAGPLv3への転換)を契機に、ValkeyとKeyDBへの関心が高まった。3つのプロジェクトすべてがRedisプロトコル互換であるため、既存のクライアントをそのまま使用できる。

項目Redis 7.x / 8.xValkey 8.xKeyDB
ライセンスAGPLv3 (2025〜)BSD 3-ClauseBSD 3-Clause
スレッディングモデルシングルスレッドイベントループ(I/Oスレッド対応)I/Oマルチスレッディング強化ネイティブマルチスレッディング
スループット基準Redis比で同等〜やや向上マルチコア時2〜5倍向上
ガバナンスRedis Ltd.Linux FoundationSnap Inc.
クラウドマネージドRedis Cloud、AWS ElastiCacheAWS ElastiCache、Google MemoryStore限定的
Functions対応7.0から対応互換対応非対応(Luaのみ)
適合シナリオ安定性、豊富なエコシステムオープンソースガバナンス重視高同時接続スループット要件

ハッシュスロットとリバランシング

Redis Clusterのすべてのキーは CRC16(key) mod 16384 の計算式でハッシュスロットにマッピングされる。16,384スロットという数値は、キー分散のきめ細かな制御とクラスタメタデータオーバーヘッドのバランスポイントとして設計された。理論的には最大16,384台のマスターノードまで拡張可能だが、実質的に推奨される上限は約1,000台である。

ハッシュタグによるスロット制御

マルチキー操作(MGET、パイプラインなど)のためには、関連するキーが同じスロットに存在する必要がある。ハッシュタグ構文を使用すると特定の部分のみがハッシュ計算に使用される。

# 同一スロットに配置:{user:1000}部分のみがハッシュ計算に使用される
redis-cli SET "{user:1000}.profile" '{"name":"Kim"}'
redis-cli SET "{user:1000}.settings" '{"theme":"dark"}'
redis-cli SET "{user:1000}.cart" '["item1","item2"]'

# 同じスロットか確認
redis-cli CLUSTER KEYSLOT "{user:1000}.profile"
redis-cli CLUSTER KEYSLOT "{user:1000}.settings"

スロットのリバランシング

ノードの追加や削除時にスロットを再分配する必要がある。ライブトラフィック中でも実行可能だが、ピーク時間を避けるのが望ましい。

# 新しいノードをクラスタに追加
redis-cli --cluster add-node 192.168.1.10:7006 192.168.1.10:7000

# 自動リバランシング:すべてのマスターにスロットを均等分配
redis-cli --cluster rebalance 192.168.1.10:7000

# 特定のノードから別のノードへスロットを手動移動
redis-cli --cluster reshard 192.168.1.10:7000 \
  --cluster-from <source-node-id> \
  --cluster-to <target-node-id> \
  --cluster-slots 1000 \
  --cluster-yes

# クラスタ状態の確認
redis-cli --cluster check 192.168.1.10:7000
redis-cli --cluster info 192.168.1.10:7000

メモリ最適化戦略

Redisはすべてのデータをメモリに保持するため、メモリ効率性がそのままコストに直結する。体系的なメモリ最適化により、同一のハードウェアでより多くのデータを処理できる。

maxmemory-policy 比較

メモリ上限に達した際にどのキーを削除するかを決定するポリシーである。Redis 7では8種類のポリシーを提供している。

ポリシー対象範囲アルゴリズム適合シナリオ
noevictionなし削除しない(書き込みエラー返却)データ損失不可の環境
allkeys-lru全キー最近使用頻度の低いキーを削除汎用キャッシュ
allkeys-lfu全キーアクセス頻度の低いキーを削除ホット/コールドパターンが明確なキャッシュ
allkeys-random全キーランダム削除均等なアクセスパターン
volatile-lruTTL設定済みキー最近未使用キーを削除キャッシュ+永続データ混在
volatile-lfuTTL設定済みキーアクセス頻度の低いキーを削除TTLデータ中のホット/コールド分離
volatile-randomTTL設定済みキーランダム削除TTLキー中の均等パターン
volatile-ttlTTL設定済みキー期限切れ間近のキーを削除短期キャッシュ優先削除

ほとんどのキャッシュ専用環境ではallkeys-lfuが最適である。キャッシュと永続データが混在する環境ではvolatile-lruを使用し、すべてのキャッシュキーにTTLを設定する必要がある。

MEMORYコマンドを活用した分析

# 特定キーのメモリ使用量を確認(バイト単位)
redis-cli MEMORY USAGE user:profile:10001
# (integer) 256

# ネストされた構造の場合、サンプル数を指定(0で全探索)
redis-cli MEMORY USAGE myhash SAMPLES 0

# メモリ診断レポート
redis-cli MEMORY DOCTOR
# "Sam, I have no memory problems"

# メモリ統計サマリー
redis-cli MEMORY STATS

# サーバー全体のメモリ情報
redis-cli INFO memory

redis.conf メモリチューニング設定

# 最大メモリと削除ポリシー
maxmemory 4gb
maxmemory-policy allkeys-lfu

# LFUアルゴリズムのチューニング
# lfu-log-factor:値が大きいほどカウンター増加が遅い(デフォルト10)
# lfu-decay-time:カウンター減少周期(分単位、デフォルト1)
lfu-log-factor 10
lfu-decay-time 1

# メモリデフラグの有効化(jemallocベース)
activedefrag yes
active-defrag-enabled yes
active-defrag-ignore-bytes 100mb
active-defrag-threshold-lower 10
active-defrag-threshold-upper 100
active-defrag-cycle-min 1
active-defrag-cycle-max 25

# Lazy Free設定:大容量キー削除時のバックグラウンド処理
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
replica-lazy-flush yes

# I/Oスレッド設定(Redis 7+)
io-threads 4
io-threads-do-reads yes

データ構造別エンコーディング最適化

Redisはデータサイズに応じて内部エンコーディングを自動的に切り替える。Redis 7からは従来のziplistの代わりにlistpackが使用され、6バイトヘッダーによりメモリ効率がさらに改善された。適切なしきい値設定で5〜10倍のメモリ削減効果が得られる。

データ構造小型エンコーディング大型エンコーディング切り替え条件設定
Hashlistpackhashtablehash-max-listpack-entries (128)、hash-max-listpack-value (64)
Listlistpackquicklistlist-max-listpack-size (-2)
Setlistpack / intsethashtableset-max-listpack-entries (128)、set-max-intset-entries (512)
Sorted Setlistpackskiplist + hashtablezset-max-listpack-entries (128)、zset-max-listpack-value (64)
Stringint / embstrraw自動(44バイト境界)
# redis.conf:エンコーディングしきい値調整例
# 小さなハッシュが多いワークロード:しきい値を上げてlistpackを維持
hash-max-listpack-entries 256
hash-max-listpack-value 128

# 小さなソート済みセットが多いランキングサービス
zset-max-listpack-entries 256
zset-max-listpack-value 64

# 小さなセットが多いタグシステム
set-max-listpack-entries 256
set-max-intset-entries 1024

# リストノードあたりの最大サイズ(-2 = 8KB、-1 = 4KB)
list-max-listpack-size -2
list-compress-depth 1

エンコーディングの確認と構造切り替えテスト

# 現在のエンコーディングを確認
redis-cli OBJECT ENCODING mykey

# 小さなハッシュ(listpack)
redis-cli HSET small:hash f1 v1 f2 v2 f3 v3
redis-cli OBJECT ENCODING small:hash
# "listpack"

# しきい値超過時にhashtableに自動切り替え
# 129個のフィールドを持つハッシュを作成(デフォルトhash-max-listpack-entries=128超過)
for i in $(seq 1 129); do
  redis-cli HSET big:hash "field_${i}" "value_${i}"
done
redis-cli OBJECT ENCODING big:hash
# "hashtable"

# 整数のみで構成されたSet:intsetエンコーディング
redis-cli SADD int:set 1 2 3 4 5
redis-cli OBJECT ENCODING int:set
# "intset"

永続化(RDB/AOF)設定

Redisはインメモリデータベースであるため、障害時のデータ復旧には適切な永続化戦略が不可欠である。Redis 7のMulti-Part AOFにより永続化メカニズムが大幅に改善された。

RDB vs AOF vs ハイブリッドモード比較

項目RDBAOFハイブリッド(RDB + AOF)
保存方式定期的なスナップショットすべての書き込みコマンドログRDBプリアンブル + AOF増分
ファイルサイズ小さい(バイナリ圧縮)大きい(コマンドテキスト)中間
データ損失可能性最後のスナップショット以降の損失fsync設定で最小化最小
復旧速度速い遅い(コマンドリプレイ)速い
fork負荷スナップショットごとにforkリライト時のみforkリライト時にfork
ディスクI/O低い(断続的)高い(継続的)中間
適合シナリオバックアップ、災害復旧データ無損失必須プロダクション推奨

プロダクション推奨の永続化設定

# redis.conf:ハイブリッドモード(プロダクション推奨)

# RDBスナップショット周期:3600秒(1時間)内に1回変更、300秒内に100回、60秒内に10000回
save 3600 1 300 100 60 10000

# AOFの有効化
appendonly yes
appendfilename "appendonly.aof"

# AOF fsyncポリシー:everysec(パフォーマンスと安定性のバランス)
appendfsync everysec

# ハイブリッドモードの有効化:AOFリライト時にRDB形式をプリアンブルとして使用
aof-use-rdb-preamble yes

# Multi-Part AOFディレクトリ(Redis 7デフォルト)
appenddirname "appendonlydir"

# AOFリライトのトリガー条件
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# RDB圧縮とチェックサム
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb

# バックグラウンド保存失敗時の書き込み停止
stop-writes-on-bgsave-error yes

モニタリングとアラート

安定したRedisクラスタ運用のためには、コアメトリクスをリアルタイムで収集し、しきい値ベースのアラートを設定する必要がある。

コアモニタリングメトリクス

# メモリ使用量の確認
redis-cli INFO memory | grep -E "used_memory_human|used_memory_rss_human|mem_fragmentation_ratio"
# used_memory_human:2.85G
# used_memory_rss_human:3.12G
# mem_fragmentation_ratio:1.09

# クラスタ状態の確認
redis-cli CLUSTER INFO
# cluster_state:ok
# cluster_slots_assigned:16384
# cluster_slots_ok:16384
# cluster_known_nodes:6
# cluster_size:3

# 秒間コマンド処理量
redis-cli INFO stats | grep instantaneous_ops_per_sec

# 接続数の確認
redis-cli INFO clients | grep connected_clients

# キースペースヒット率(キャッシュ効率)
redis-cli INFO stats | grep -E "keyspace_hits|keyspace_misses"

# スローログの確認(10ms以上かかったコマンド)
redis-cli SLOWLOG GET 10
redis-cli SLOWLOG LEN

Pythonベースのモニタリングスクリプト

import redis
from redis.cluster import RedisCluster

# Redis Cluster接続
startup_nodes = [
    {"host": "192.168.1.10", "port": 7000},
    {"host": "192.168.1.10", "port": 7001},
    {"host": "192.168.1.10", "port": 7002},
]

rc = RedisCluster(
    startup_nodes=startup_nodes,
    decode_responses=True,
    password="your_secure_password",
    socket_timeout=5,
    retry_on_timeout=True,
)

def check_cluster_health():
    """クラスタ全体の状態を点検し、異常時にアラートを送信する。"""
    alerts = []

    # クラスタ状態の確認
    cluster_info = rc.cluster_info()
    if cluster_info.get("cluster_state") != "ok":
        alerts.append(f"[CRITICAL] クラスタ状態異常: {cluster_info.get('cluster_state')}")

    # 各ノードのメモリ使用率を点検
    for node in rc.get_nodes():
        try:
            info = rc.get_redis_connection(node).info("memory")
            used = info["used_memory"]
            maxmem = info.get("maxmemory", 0)
            if maxmem > 0:
                usage_pct = (used / maxmem) * 100
                if usage_pct > 85:
                    alerts.append(
                        f"[WARNING] ノード {node.host}:{node.port} "
                        f"メモリ使用率 {usage_pct:.1f}%"
                    )

            # メモリフラグメンテーション率を点検
            frag_ratio = info.get("mem_fragmentation_ratio", 1.0)
            if frag_ratio > 1.5:
                alerts.append(
                    f"[WARNING] ノード {node.host}:{node.port} "
                    f"メモリフラグメンテーション率 {frag_ratio:.2f}"
                )
        except Exception as e:
            alerts.append(f"[ERROR] ノード {node.host}:{node.port} 接続失敗: {e}")

    return alerts


def get_memory_report():
    """ノード別メモリ使用状況レポートを生成する。"""
    report = []
    for node in rc.get_nodes():
        try:
            info = rc.get_redis_connection(node).info("memory")
            report.append({
                "node": f"{node.host}:{node.port}",
                "role": node.server_type,
                "used_memory_human": info["used_memory_human"],
                "used_memory_rss_human": info["used_memory_rss_human"],
                "fragmentation_ratio": info["mem_fragmentation_ratio"],
                "used_memory_peak_human": info["used_memory_peak_human"],
            })
        except Exception as e:
            report.append({"node": f"{node.host}:{node.port}", "error": str(e)})
    return report


if __name__ == "__main__":
    # クラスタヘルスチェック
    alerts = check_cluster_health()
    if alerts:
        for alert in alerts:
            print(alert)
        # send_to_slack(alerts) または send_to_pagerduty(alerts)
    else:
        print("すべてのノード正常")

    # メモリレポート出力
    for item in get_memory_report():
        print(item)

アラートしきい値基準

メトリクスWARNINGCRITICAL説明
メモリ使用率75%超90%超maxmemory対比used_memory
メモリフラグメンテーション率1.5超2.0超mem_fragmentation_ratio
接続数5,000超8,000超connected_clients
キャッシュヒット率90%未満80%未満keyspace_hits / (hits + misses)
スローログ頻度10件/分超50件/分超10ms以上かかったコマンド
レプリケーション遅延1MB超10MB超master_repl_offsetの差分

トラブルシューティング

メモリフラグメンテーション問題

mem_fragmentation_ratioが1.5を超えるとjemallocのメモリフラグメンテーションが深刻な状態である。頻繁なキーの作成/削除が原因であり、activedefrag機能を有効化してランタイムで解消できる。

# 現在のフラグメンテーション率を確認
redis-cli INFO memory | grep mem_fragmentation_ratio

# ランタイムでActive Defragを有効化
redis-cli CONFIG SET activedefrag yes
redis-cli CONFIG SET active-defrag-threshold-lower 10

# デフラグの進行状況を確認
redis-cli INFO memory | grep -E "active_defrag"

ビッグキー(Big Key)の検出

単一キーに過度なデータが保存されると、ネットワーク遅延、メモリスパイク、スローログ増加の原因となる。

# ビッグキースキャン(SCANベース、プロダクションでも安全)
redis-cli --bigkeys

# 特定キーの正確なメモリ使用量
redis-cli MEMORY USAGE large:hash SAMPLES 0

# ビッグキーの非同期削除(UNLINK = ノンブロッキングDEL)
redis-cli UNLINK large:hash

MOVEDリダイレクションの繰り返し

クライアントが間違ったノードにリクエストを送り続けてMOVEDレスポンスを受ける場合、クライアントライブラリがクラスタモードをサポートしているか確認する必要がある。スタンドアロンモードのクライアントではスロットルーティングが行われない。

レプリカ同期の失敗

レプリカがフルリシンクを繰り返す場合はrepl-backlog-sizeを十分に増やす必要がある。デフォルト値は1MBだが、トラフィックが多い環境では64MB〜256MBに拡大する。

# redis.conf
repl-backlog-size 256mb
repl-backlog-ttl 3600

障害復旧手順

自動フェイルオーバー

Redis Clusterはノード障害を自動検出し、レプリカをマスターに昇格させる。cluster-node-timeout(デフォルト15000ms)以内に過半数のマスターが該当ノードをPFAILと判断するとFAIL状態に遷移し、そのマスターのレプリカの1つが自動昇格される。

# 現在のクラスタノード状態を確認
redis-cli CLUSTER NODES

# 特定ノードがFAIL状態か確認
redis-cli CLUSTER INFO | grep cluster_state

# 手動フェイルオーバー(レプリカで実行)
redis-cli -p 7003 CLUSTER FAILOVER

# 強制フェイルオーバー(マスターが応答不能時)
redis-cli -p 7003 CLUSTER FAILOVER FORCE

ノード交換手順

  1. 障害ノードの除去:redis-cli --cluster del-node <cluster-ip:port> <node-id>
  2. 新インスタンス起動後にクラスタ参加:redis-cli --cluster add-node <new-ip:port> <cluster-ip:port>
  3. レプリカの割り当て:redis-cli -p <new-port> CLUSTER REPLICATE <master-node-id>
  4. スロットの正常分配を確認:redis-cli --cluster check <cluster-ip:port>

RDB/AOFベースのデータ復旧

# AOFファイルの整合性検証
redis-check-aof --fix /opt/redis-cluster/7000/appendonlydir/appendonly.aof.1.incr.aof

# RDBファイルの整合性検証
redis-check-rdb /opt/redis-cluster/7000/dump.rdb

# バックアップからの復旧:インスタンス停止後RDB/AOFファイルを置き換え
redis-cli -p 7000 SHUTDOWN NOSAVE
cp /backup/dump.rdb /opt/redis-cluster/7000/dump.rdb
redis-server /opt/redis-cluster/7000/redis.conf

運用チェックリスト

プロダクションRedisクラスタの安定運用のための項目別チェックリストである。

デプロイ前の点検

  • maxmemoryとmaxmemory-policyがワークロードに適切に設定されているか
  • クラスタノード数が最低6つ(マスター3+レプリカ3)以上あるか
  • 各ノードのメモリが実際のデータの2倍以上確保されているか(fork時のCOWを考慮)
  • ACLルールが最小権限の原則に従って設定されているか
  • ネットワーク帯域幅とレイテンシがクラスタ要件を満たしているか

日次点検

  • メモリ使用率が75%未満であるか
  • mem_fragmentation_ratioが1.5未満であるか
  • スローログに異常なパターンがないか
  • レプリケーション遅延(replication lag)が許容範囲内であるか
  • キャッシュヒット率が90%以上維持されているか

週次点検

  • ビッグキースキャンで異常なサイズのキーを確認したか
  • 未使用キー(アイドル時間基準)を整理したか
  • RDB/AOFバックアップファイルの整合性を検証したか
  • クラスタスロット分配が均等であるか
  • セキュリティパッチとRedisマイナーバージョンアップデートを検討したか

月次点検

  • maxmemory設定値がデータ増加トレンドに適切であるか
  • エンコーディングしきい値(listpack entries/value)が現在のデータパターンに最適であるか
  • 障害復旧手順をフェイルオーバードリルで検証したか
  • クライアントライブラリバージョンが最新であるか
  • キャパシティプランニングにより3〜6か月以内の拡張必要性を判断したか

参考資料