キャッシュ・アーキテクチャ:Redis、 Memcached
キャッシュ・アーキテクチャ: Redis、 Memcached
1)いつ、なぜキャッシュ
目標:レイテンシーを削減し、DB/PSP/外部 APIをオフロードし、ピークを緩和します。
多くの場合、キャッシュレイヤーはマルチレベルである:In-process (L1)→service-level (Redis/Memcached L2)→edge/CDN。内部キャッシュはホット読み取りを高速化し、L2はサービスで一般的です。エッジはパブリックコンテンツです。
2) Redis vs Memcached-概要
ルール:複雑なデータ構造、永続性、pub/sub/streams/scriptsが必要な場合は、Redisを使用してください。耐久性のない超簡単、高速、安価なKVキャッシュレイヤーがMemcachedの場合。
3)キャッシングパターン
3.1キャッシュアサイド(遅延)
アプリケーションはcache→a miss→reads from the database→put the cache with TTLから読み込みます。
シンプルなTTL制御、キャッシュの独立性。−ミスの場合に可能な「嵐」。
3.2読み取りスルー
クライアント/プロキシ自体がミス時に原点から引き上げ、キャッシュに入れます。
一元化されたロジック。−より複雑なインフラストラクチャ。
3.3書き込みスルー/書き込みの後ろ
Write-through:最初にキャッシュに書き込み、次にデータベースに書き込みます。
書き込み後ろ:キューへの書き込み、データベース内の非同期フラッシュ(クラッシュ時に潜在的な損失-ログが必要)。
3.4 2層(L1+L2)
短いTTLとソフトTTL、 L2 (Redis/Memcached)でL1(インプロセス)-"キャッシュの真実。"パブ/サブ経由の障害。
4) TTL、嵐および一貫性
TTL-Setデータ変更の頻度に近い。ホットキーの場合は、TTL(ジッタ)ランダム化を使用します:'ttl=base ± rand (0。。base0です。1)'-同期アウトフローを削除します。
小犬(雷の群れ):ミスを保護する:- Singleflight:値をオーバージェネレートするプロセスは1つだけです(Luaの例を参照)。
- Soft-TTL+background refresh: 'soft_ttl'の後、古いものを与え、バックグラウンドで更新します。
- セマフォー/ロック:'SETキー:ロック値NX PX=2000'。
- レスポンスAPIの「stale-while-revalidate」(第8節を参照)。
5)キー、名前空間、シリアル化
5.1キーネーミング
テンプレート: '{domain}: {entity}: {id}: {field}'
例:- 'user: profile: 42'カタログ:product: 1001: v2''psp:料金:2025-11-03'
スキーマバージョン(':v2')を追加すると、大量障害が発生します。
5.2 「space version」によるNeimspaces"
キー'ns: catalog=17'を押したままにします。実キー:'カタログ:17: product: 1001'。グローバルディレクトリを無効にする場合は、単に'ns: catalog'をインクリメントするだけです。
5.3シリアル化/圧縮
JSONは便利ですが、重いです。MessagePack/CBORを使用します。
大きなペイロード(>1-2 KB)の圧縮(LZ4/ZSTD)を有効にします。Redis-クライアント側。
6)ホットキーとシャーディング
ホットキー:hit/miss/byteでトップNを監視します。非常にホットキーの場合:- Replicated read pattern:複数のシャードキーの値をhot: k: 1で複製します。N'、読み取り時にランダムを選択します。
- Local L1:障害者購読プロセスを念頭に置いてください。
- Redisクラスタ-ネイティブ(16384ハッシュスロット)。
- Memcachedはクライアント側の一貫したハッシュです。
- Redis'{……}'のハッシュタグは、キーのセットのスロットを修正します。'user: {42}: profile'と'user: {42}: limits'は同じカードになります。
7)プリエンプションポリシーとサイズ
Redis 'maxmemory-policy': 'allkeys-lru'、 'volatile-lru'、 'allkeys-lfu'、 'noeviction'……д.キャッシュの場合、通常は'allkeys-lru'/'allkeys-lfu'です。
Memcached-LRU-item-slab。
キーサイズと値:最大アイテムのサイズを監視します(デフォルトでは1MB、チューニングスラブでMemcached)。
メモリを超えると、アクティブパスの'noeviction'ではなく、予測可能に劣化するはずです。
maxmemory 32gb maxmemory-policy allkeys-lfu hz 50 tcp-keepalive 60
8)嵐の保護パターン-コード
8.1 Redis Luaシングルフライト(擬似)
lua
-- KEYS[1] = data_key, KEYS[2] = lock_key
-- ARGV[1] = now_ms, ARGV[2] = soft_ttl_ms, ARGV[3] = hard_ttl_ms, ARGV[4] = lock_ttl_ms local payload = redis. call("GET", KEYS[1])
if payload then local meta = redis. call("HGETALL", KEYS[1].. ":meta")
local last = tonumber(meta[2] or "0")
if tonumber(ARGV[1]) - last < tonumber(ARGV[2]) then return { "HIT", payload }
end if redis. call ("SET," KEYS [2], "1," "NX," "PX," ARGV [4]) then return {"REFRESH," payload} - one worker updates, the rest give stale end return {"STALE," payload}
end if redis. call("SET", KEYS[2], "1", "NX", "PX", ARGV[4]) then return { "MISS", nil }
end return { "BUSY", nil }
8.2ノード。js cache-aside(簡略化)
js const v = await redis. get(key);
if (v) return decode(v);
const lock = await redis. setNX(key+":lock", "1", { PX: 1500 });
if (lock) {
const fresh = await loadFromDB(id);
await redis. set(key, encode(fresh), { EX: ttl, NX: false });
await redis. del(key+":lock");
return fresh;
} else {
await sleep(60); // short backoff const retry = await redis. get (key) ;//give someone's already filled return decode (retry);
}
9)障害とコヒーレンス
イベントによって:データベースで変更する場合は、'pub/sub'イベント'invalidate: {ns}: {id}'→購読者はキーを削除します。
タイマーで:頻繁にデータを変更するための短いTTL。
バージョン管理:'ns:'キーを参照してください。
Outbox:障害配信保証(ログ/トピックイベント、レトライ)。
キャッシュ操作idempotency:増分には'SETXX/SETNX'、バージョン('etag')、ハッシュフィールドを使用します。
10)レプリケーション、クラスタ、フェイルオーバー
10.1 Redis
Sentinel:自動フェイルオーバマスターレプリカ(stateFUL IP/name)。
クラスタ:シャーディング+自動フェイルオーバー;「MOVED/ASK」リダイレクトをサポートする必要があります。
AOF/RDB:通常キャッシュ'appendfsync everysec'の場合、永続性なしで(純粋なキャッシュのように)可能です。
10.2 Memcached
箱からのレプリケーションはありません。信頼性-マルチサーバーのシャードを介して+repeat 'n'(クライアント側)。
ノードが落ちると、キャッシュのミスと「再訓練」が増加します。
10.3 K8sとネットワーキング
Redis/Memcachedは、ポッドの頻繁な再作成を好まない。StatefulSet+AZアンチコード、固定PVC/POD IPを使用します。
PodDisruptionBudgetとTopologySpreadConstraintsを設定します。
11)トランザクション、スクリプト、原子性(Redis)
INCR/DECR、 HINCRBY-カウンタ、クォータ、レート制限(単に持続を考慮)。
MULTI/EXEC-アトミックコマンドのバンドル。
Lua (EVAL)-レースなしでread-modify-write。
パイプライン-RTT(特にネットワークホップ)を低減します。
lua
-- KEYS[1]=bucket, ARGV[1]=capacity, ARGV[2]=refill_rate_per_sec, ARGV[3]=now_ms
-- Returns 1 if the token is issued, otherwise 0
12)キュー、パブ/サブストリーム(Redis)
パブ/サブ:障害、信号。いいえ保存、オンラインリスナーのみ。
ストリーム:確認イベントキュー(ACK)、コンシューマーグループ、レトライ-書き込み/ファンアウトに便利です。
リスト('BRPOP'):単純なキュー。
バックアップなしで「すべての単一のバス」としてRedisを使用しないでください-これはKafkaではなく、キャッシュ/高速バスです。
13)セキュリティとアクセス
ネットワーク分離/VPC、入力レベルでのmTLS、 ACL/パスワード (Redis 6+では'requirepass'/ACL)。
ACL経由でRedis ('CONFIG'、 'FLUSHALL'、 'KEYS')の危険なコマンドを無効にします。
Memcachedの場合-パブリックインターフェイス'-U 0' (UDPなし)を聞かないでください。プライベートネットワークのみです。
PIIを保存しないでください。必要に応じて-アプリケーションレベルで短いTTL+暗号化。
14)観察可能性および維持
主な指標:- ヒット比/ミス比(名前空間/ルートによる)。
- レイテンシp95/p99 'GET/SET/MGET'コマンド、タイムアウト。
- Evictions・・・・・・・・・・・・・・・・・・・・・・
- レプリケーションラグ(Redis)、クラスタ状態、マイグレート/リハッシュイベント。
- トラフィック/バイト(サンプリング)によるトップNキー。
- ログ:slowコマンド('slowlog')、ネットワークエラー。
- ダッシュボード:一般(CPU/RAM/接続)、コマンド、クラスタースロット、センチネル、Prometheusエクスポーターを通過します。
15)構成と導入-例
15.1 Redisセンチネル(スニペット)
port 6379 protected-mode yes appendonly yes appendfsync everysec maxmemory-policy allkeys-lfu
'sentinel。conf':
sentinel monitor m1 10. 0. 0. 11 6379 2 sentinel auth-pass m1 sentinel down-after-milliseconds m1 5000 sentinel failover-timeout m1 60000
15.2 Redisクラスタ(ヘルム値、簡略化)
yaml cluster:
enabled: true nodes: 6 # 3 masters + 3 replicas persistence:
size: 100Gi resources:
requests: { cpu: "500m", memory: "2Gi" }
15.3 Memcached(展開)
yaml containers:
- image: memcached:1. 6 args: ["-m", "32768", "-I", "2m", "-v", "-t", "8", "-o", "modern"]
ports: [{ containerPort: 11211 }]
15.4読み取りスループロキシとしてのNGINX (APIループ)
nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api:100m max_size=10g inactive=10m;
map $request_uri $cache_key { default "api:$request_uri"; }
location /api/ {
proxy_cache api;
proxy_cache_valid 200 1m;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
proxy_cache_lock on; # singleflight на уровне NGINX proxy_cache_key $cache_key;
proxy_pass http://backend;
}
16)テストおよびゲート
コールド/ウォーム/ホットキャッシュロードプロファイル。
ミスの注入(パージのマス)-起源は「再訓練」に耐えなければなりません。
アラート:ヒット率の急激な低下、ミスレイテンシーの上昇、立ち退きの雪崩、タイムアウトの上昇。
17)アンチパターン
AOF/RDBなし、冗長性なしでRedisに「真実」を保存します。
TTL=0(永久)揮発性データ→永続的不整合。
prod内の「KEYS」のマス。
ジッタ/ソフトTTL→同期停止および嵐がない。
shardings/replicasを含まないすべてのコマンドに対して1つのインスタンス。
アトミシティ/スクリプトを必要とするタスクにMemcachedを使用します。
18)実装チェックリスト(0-45日)
0-10日
テンプレート(cache-aside+L1/L2)を選択し、キー、TTL、名前空間を記述します。
ジッタ/ソフトTTL、シングルフライトを有効にします。基本的なアラート/ダッシュボード。
Redisの場合-ACL、保護モード、スローログ、maxmemory-policyを構成します。
11-25日
シャーディング(Redis Clusterまたはクライアントハッシュ)、レプリカに切り替えます。
パブ/サブまたはneimspaceバージョンによる障害;データベースのoutbox。
キャッシュ「再訓練」負荷テスト;起源を制限します。
26-45日
オートプロモ/カナリTTL、リリース前にウォームアップ。
書き込み後ろ/バックグラウンドの再構成のためのストリーム。
ヒット率、トップキー、メモリコストに関する毎週のレポート。
19)成熟度の指標
ヒット率L2 ≥ 80%(ルート/名前空間の統計)。
GET <2-3ミリ秒(in-DC)をP95すると、<SLOの原点を逃します。
集団障害における0の嵐(テストによって証明された)。
自動障害及びnymspaceのバージョン管理。
Sharding/Replicationは、優れた劣化なしに1ノードの障害をカバーします。
20)結論
強力なキャッシュアーキテクチャは、キーとTTL、嵐の保護、適切なシャーディネス、予測可能なプリエンプションの規律です。Redisは豊かな意味論、持続性、原子性を与えます。Memcached-最大のシンプルさとスピード。観測性、イベント障害、L1+L2を追加し、キャッシュはプラットフォームアクセラレータになり、偶発的なドロップや「神秘的な」バグの発生源ではありません。