채팅 재접속, 마지막 메시지 ID만 넘기면 끝일까?
채팅 클라이언트가 마지막 메시지 ID로 이어 받는 방식이 깨지는 경우를 Python WebSocket 서버와 Redis 8.10으로 재현합니다. 채우는 동안 도착한 메시지의 빠짐과 중복, MAXLEN으로 잘린 ID에 resume ok를 보내며 340건을 건너뛰는 현상, XADD IDMP로 막는 재전송 중복을 봅니다.

채팅 클라이언트가 마지막 메시지 ID로 이어 받는 방식이 깨지는 경우를 Python WebSocket 서버와 Redis 8.10으로 재현합니다. 채우는 동안 도착한 메시지의 빠짐과 중복, MAXLEN으로 잘린 ID에 resume ok를 보내며 340건을 건너뛰는 현상, XADD IDMP로 막는 재전송 중복을 봅니다.

Valkey 9.1 클러스터에서 요청의 88%가 키 하나로 가면 그 키의 노드만 CPU를 다 쓰고 나머지 노드는 노는 모습을 valkey-benchmark로 재현합니다. valkey-cli --hotkeys(LFU 필요)로 핫 키를 찾고, 키를 복사본으로 나누면 노드별 명령 수와 전체 처리량이 어떻게 바뀌는지 측정합니다.
Valkey 9.1에서 BGSAVE 도중 쓰기가 몰리면 copy-on-write로 컨테이너 메모리가 maxmemory와 상관없이 데이터 크기만큼 늘어 OOM으로 죽는 과정과, 디스크가 가득 차 저장이 실패하면 쓰기와 PING까지 MISCONF로 거부되는 과정을 재현합니다.
질문을 임베딩해 이전 질문과 충분히 가까우면 저장해 둔 답을 돌려주는 시맨틱 캐시에서, 같은 뜻 질문과 말만 비슷한 다른 뜻 질문으로 기준값별 적중과 잘못된 적중을 잽니다. Redis의 RedisVL 기본값을 그대로 쓰면 무슨 일이 생기는지도 확인합니다.

Redis 8.10과 Valkey 9.1을 나란히 띄우고 같은 Python 클라이언트로 같은 명령 79개를 보내 응답이 어디까지 같은지 확인합니다. 한쪽에만 있는 명령과, Redis가 만든 RDB 파일을 Valkey에 넣으면 읽히는지도 확인합니다.
WebSocket 연결은 처음 붙은 서버에 계속 머물기 때문에, 채팅 서버를 두 대로 늘리면 다른 서버에 붙은 사용자에게는 메시지가 가지 않습니다. Python WebSocket 서버 두 대와 NGINX, Redis 8.10으로 이 문제를 재현하고, Pub/Sub로 서버 간에 전달할 때 구독이 끊긴 사이 메시지가 사라지는 과정과 Streams로 바꿔 놓친 메시지를 다시 채우는 방법을 확인합니다.

INCR과 EXPIRE로 만든 고정 윈도우 제한은 간단하지만 윈도우 경계에서 한도의 두 배까지 통과시키고, 서버 여러 대가 확인과 증가를 따로 하면 한도를 넘깁니다. Redis 8.10에서 고정 윈도우, 슬라이딩 로그, 토큰 버킷을 같은 경계 패턴으로 비교하고, Lua로 원자성을 지키는 방법을 확인합니다.
Redis는 메모리에 데이터를 두지만 RDB 스냅숏과 AOF로 디스크에 남길 수 있고, 어느 방식을 고르느냐에 따라 강제 종료 뒤 남는 데이터가 달라집니다. Redis 8.10에서 쓰기 도중 프로세스를 SIGKILL로 죽여 RDB와 appendfsync 설정별로 남은 키를 셉니다.
maxmemory에 닿은 Redis는 maxmemory-policy에 따라 쓰기를 거부하거나 키를 골라 지우는데, 어떤 키를 지우느냐에 따라 같은 메모리에서도 hit ratio가 크게 달라집니다. Redis 8.10에서 핫 키가 있는 접근 패턴으로 정책별 hit ratio를 재고, 한 번 훑는 조회가 섞일 때와 근사 LRU의 샘플 수까지 확인합니다.
Redis의 `SET NX PX` 락은 TTL이 지나면 풀리기 때문에, 작업 중에 멈췄다 깨어난 서버와 새로 락을 잡은 서버가 같은 데이터를 함께 고칠 수 있습니다. Redis 8.10과 PostgreSQL 17로 락 만료 뒤 갱신 손실과 watchdog 연장의 한계를 재현하고, 펜싱 토큰으로 늦게 온 쓰기를 DB에서 거절합니다.
Cache Aside에서 캐시를 채우고 지우는 것은 Redis가 아니라 애플리케이션입니다. Redis 8.10과 PostgreSQL 17로 쓰기 뒤 캐시 삭제 실패와, DEL이 성공해도 늦은 읽기가 옛값을 다시 넣는 경쟁 조건을 직접 재현해 옛값이 어디서 나가는지 확인합니다.
Redis 자료구조는 그 키로 가장 자주 하는 연산을 기준으로 고릅니다. Redis 8.10에서 큰 프로필을 JSON String과 Hash로 저장해 필드 하나를 바꿀 때의 차이와 동시 수정으로 사라지는 변경, 워커가 죽은 List 큐와 Stream 컨슈머 그룹을 직접 재현합니다.
Redis가 빠른 이유는 메모리만이 아닙니다. Redis 8.10에서 명령을 실행하는 스레드 수, 느린 명령 하나가 다른 클라이언트를 붙잡는 시간, 큰 키를 DEL로 지울 때 생기는 지연 스파이크를 직접 재고 SLOWLOG와 LATENCY로 원인을 찾습니다.