캐싱 아키텍처: Redis, Memcached
캐싱 아키텍처: Redis, Memcached
1) 언제 그리고 왜 캐시
목표: 대기 시간을 줄이고 DB/PSP/외부 API를 오프로드하며 피크를 완화하십시오.
캐시 레이어는 종종 다단계입니다. 프로세스 중 (L1) → 서비스 레벨 (Redis/Memaccashed L2) → edge/CDN입니다. 내부 캐시는 핫 읽기 속도를 높이고 L2는 서비스에 일반적이며 엣지는 공개 콘텐츠에 사용됩니다.
2) Redis vs Memaccashed-브리프
규칙: 복잡한 데이터 구조, 지속성, 펍/하위/스트림/스크립트가 필요한 경우 Redis를 사용하십시오. 내구성이없는 매우 단순하고 빠르며 저렴한 KV 캐시 레이어가 Memcashed되면.
3) 캐싱 패턴
3. 캐시 제외 1 개 (게으른)
응용 프로그램은 캐시에서 읽습니다 → 데이터베이스에서 미스 → 읽기 → TTL이있는 캐시에 넣습니다.
간단한 TTL 제어, 캐시 독립성. - 누락시 가능한 "폭풍".
3. 2 읽기
클라이언트/프록시 자체가 원산지에서 빠져 나와 캐시에 넣습니다.
중앙 집중식 논리. -보다 복잡한 인프라.
3. 3 쓰기/쓰기 뒤에
쓰기: 먼저 캐시에 기록한 다음 데이터베이스에 기록합니다.
쓰기 뒤에: 대기열에 쓰기, 데이터베이스에서 비동기식 플래시 (충돌시 잠재적 손실-로그가 필요함).
3. 4 2 계층 (L1 + L2)
짧은 TTL 및 소프트 TTL, L2 (Redis/Memcashed) 가있는 L1 (프로세스 중) - "캐시 진실. "펍/서브를 통한 장애.
4) TTL, 폭풍 및 일관성
데이터 변경 빈도에 가까운 TTL- 세트. 핫 키의 경우 TTL (jitter) 무작위 화를 사용하십시오: 'ttl = base λrand (0.. base0. 1) '-동기 유출을 제거합니다.
Dogpile (천둥 무리): 미스를 보호하십시오:- 싱글 플라이트: 하나의 프로세스 만 값을 과도하게 생성합니다 (Lua 예 참조).
- Soft-TTL + 배경 새로 고침: 'soft _ ttl' 이후에는 오래되고 배경으로 업데이트하십시오.
- 세마포어/잠금: 'SET 키: 잠금 값 NX PX = 2000'.
- 부실: 응답 API에 대한 '부실한 상태' (섹션 8 참조).
5) 키, 네임 스페이스, 직렬화
5. 1 키 이름 지정
템플릿: '{domain}: {엔터티}: {id}: {field}'
예:- '사용자: 프로필: 42' '카탈로그: 제품: 1001: v2' psp: 요금: 2025-11-03 '
스키마 버전 (': v2') 을 추가하면 대량 장애가 발생합니다.
5. "공간 버전" 을 통한 2 개의 공간
키 'ns: catalo = 17' 을 유지하십시오. 실제 키: '카탈로그: 17: 제품: 1001'. 글로벌 디렉토리 장애의 경우 간단히 'ns: catalo' 를 증가시킵니다
5. 3 직렬화/압축
JSON은 편리하지만 무겁습니다. MessagePack/CBOR을 사용하십시오.
큰 페이로드 (> 1-2 KB) 에 압축 (LZ4/ZSTD) 을 사용하십시오. Redis-클라이언트 측.
6) 뜨거운 키와 샤딩
핫 키: 적중/미스/바이트로 톱 N을 모니터링합니다. 매우 뜨거운 키의 경우:- 복제 된 읽기 패턴: 여러 파편 키의 핫: k: 1에 값을 복제합니다. N ', 읽을 때 무작위로 선택하십시오.
- 지역 L1: 장애 가입 절차를 염두에 두십시오.
- Redis Cluster-네이티브 (16384 해시 슬롯).
- Memcashed는 클라이언트 측 일관된 해시입니다.
- Redis '{...}' 의 해시 태그는 키 세트에 대한 슬롯을 수정합니다. 'user: {42}: prolife' and 'user: {42}: limites' 는 동일한 카드에 있습니다.
7) 선점 정책 및 규모
Redis 'maxmemory-policy': 'allkeys-lru', 'whalemous-lru', 'allkeys-lfu', 'nodeasition' 3626) д. 캐시의 경우 일반적으로 'allkeys-lru '/' allkeys-lfu' 입니다.
Memcashed - LRU не항목 슬래브.
키 크기 및 값: 최대 항목 크기 (기본값 1MB, 튜닝 슬래브) 를 참조하십시오.
초과 메모리는 예측 가능하게 저하되어야합니다. 활성 경로에서 'noverse' 가 아닙니다.
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 캐시 제외 (단순화)
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) 장애와 일관성
이벤트 별: 데이터베이스를 변경할 때 '펍/하위' 이벤트 '무효화: {ns}: {id}' → 가입자는 키를 삭제합니다.
타이머 별: 데이터를 자주 변경하려면 짧은 TTL.
검증: 'ns:' 키를 참조하십시오.
미리 보기: 장애 전달 보증 (로그/주제 이벤트, retrai).
캐시 작업 demempotency: 'SETXX/SETNX', 버전 ('etag') 및 해시 필드를 증분하여 사용하십시오.
10) 복제, 클러스터, 장애
10. 1 리디스
Sentinel: 자동 실패 마스터 복제본 (stateFUL IP/이름).
클러스터: 샤딩 + 자동 장애; 고객은 'MOVED/ASK' 리디렉션을 지원해야합니다.
AOF/RDB: 캐시의 경우 일반적으로 'appendfsync everysec' 의 경우 지속성없이 (순수한 캐시와 같이) 가능합니다.
10. 메모리 캐시
상자에서 복제하지 않습니다. 신뢰성-멀티 서버 샤드 + 반복 'n' (클라이언트 측) 을 통한.
노드가 떨어지면 캐시의 미스 및 "재교육" 이 증가합니다.
10. 3 K8 및 네트워킹
Redis/Memcashed는 포드의 빈번한 재생성을 좋아하지 않습니다. 고정 PVC/POD IP 인 StatefulSet + AZ 대류를 사용하십시오.
PodDisruptionBudget 및 TopologySpreadConstraints 설정.
11) 거래, 스크립트 및 원자 (Redis)
INCR/DECR, 힌크로-카운터, 할당량, 요율 제한 (지속을 고려하십시오).
MULTI/EXEC-원자 명령 묶음.
Lua (EVAL) -경주없이 읽기 수정 쓰기.
파이프 라인-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), 소비자 그룹, Retrai-쓰기/팬 아웃에 편리합니다.
목록 ('BRPOP'): 간단한 대기열.
백업없이 Redis를 "모든 것의 단일 버스" 로 사용하지 마십시오. 이것은 Kafka가 아닌 캐시/고속 버스입니다.
13) 보안 및 액세스
네트워크 격리/VPC, 진입 레벨의 mTLS, ACL/암호 (Redis 6 + 의 '요구 사항 '/ACL).
ACL을 통해 Redis ('CONFIG', 'FLUSHALL', 'KEYS') 에서 위험한 명령을 사용하지 않습니다.
Memcashed 의 경우 공개 인터페이스 인 '-U 0' (UDP없이) 을 듣지 마십시오. 개인 네트워크 만 있습니다.
PII를 저장하지 마십시오. 필요한 경우-응용 프로그램 수준에서 짧은 TTL + 암호화.
14) 관찰 및 유지 보수
주요 지표:- 적중 비율/미스 비율 (네임 스페이스/경로 별).
- 대기 시간 p95/p99 'GET/SET/MET' 명령, 타임 아웃.
- 퇴거: OOM 오류.
- 복제 지연 (Redis), 클러스터 상태, 마이그레이션/재 해시 이벤트.
- 트래픽/바이트 (샘플링) 별 Top-N 키.
- 로그: 느린 명령 ('slowlogg'), 네트워크 오류.
- 대시 보드: 일반 (CPU/RAM/연결), 명령, 클러스터 슬롯, 센티넬, Prometheus 수출 업체를 통과합니다.
15) 구성 및 배포-예
15. 1 Redis Sentinel (스 니펫)
port 6379 protected-mode yes appendonly yes appendfsync everysec maxmemory-policy allkeys-lfu
'센티넬. (PHP 3 = 3.06
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 메모리 캐시 (배포)
yaml containers:
- image: memcached:1. 6 args: ["-m", "32768", "-I", "2m", "-v", "-t", "8", "-o", "modern"]
ports: [{ containerPort: 11211 }]
15. 읽기 프록시 (API 루프) 로 NGINX 4 개
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 (영구).
대량 'KEYS' in prod.
지터/소프트 -TTL → 동기 정전 및 폭풍의 부재.
샤딩/복제본이없는 모든 명령에 대한 하나의 예.
원자/스크립트가 필요한 작업에 Memcashed를 사용하십시오.
18) 구현 점검표 (0-45 일)
0-10 일
템플릿 (캐시 제외 + L1/L2) 을 선택하고 키, TTL, 네임 스페이스를 설명하십시오.
지터/소프트 -TTL, 단일 비행 사용; 기본 경고/대시 보드.
Redis의 경우-ACL, 보호 모드, 느린 로그, 최대 메모리 정책 설정.
11-25 일
샤딩 (Redis Cluster 또는 Client hash), 복제본으로 전환하십시오.
펍/서브 또는 네임 스페이스 버전을 통한 장애; 데이터베이스의 아웃 박스.
캐시 "재교육" 로드 테스트; 원점 제한.
26-45 일
자동 프로모/카나리아 TTL, 출시 전 예열.
쓰기/배경 재 조립을위한 스트림.
히트 비율, 최고 키, 메모리 비용에 대한 주간 보고서.
19) 성숙도 지표
적중 비율 L2는 80% 이상입니다 (경로/네임 스페이스에 대한 통계).
P95 GET <2-3 ms (in-DC), <SLO 원점을 놓칩니다.
대량 장애로 인한 폭풍 0 건 (검사로 입증).
자동 장애 및 님스 페이스 버전.
샤딩/복제는 눈에 띄는 저하없이 1 개의 노드 고장을 포함합니다.
20) 결론
강력한 캐시 아키텍처는 키 및 TTL, 폭풍 방지, 적절한 예리함 및 예측 가능한 선점의 분야입니다. Redis는 풍부한 의미론, 지속성 및 원자 성을 제공합니다. Memcashed - 최대 단순성과 속도. 관찰 가능성, 이벤트 장애, L1 + L2를 추가하면 캐시는 우발적 인 낙하 및 "신비한" 버그가 아닌 플랫폼 가속기가됩니다.