The Mystery of the Redis Read-Only Error in a Single-Node Setup
개요
단일 노드 Redis 설정에서 발생하는 'READONLY' 오류는 실제 복제 상태 변경이 아닌, 인프라스트럭처의 일시적인 불안정성 및 클라이언트 연결 문제로 인해 발생할 수 있습니다.
주요 내용
* 문제 상황: 실시간 애플리케이션에서 Redis가 캐싱 및 실시간 협업에 사용 중, 주기적으로 "READONLY You can't write against a read only replica" 오류와 함께 시스템이 중단되는 현상 발생. Docker 컨테이너 재시작으로 일시 해결되었으나 근본 원인 파악 필요.
* 인프라스트럭처: GCP VM (t2d-standard-1)에 Docker 컨테이너로 Redis 실행, 단일 노드 구성 (Redis Cluster, Sentinel 미사용).
* 초기 진단: redis-cli INFO replication 명령어를 통해 Redis가 마스터 역할이며 연결된 슬레이브가 없음을 확인.
* 배제된 원인:
* Redis Cluster 또는 Sentinel로 인한 자동 페일오버: 해당 기능을 사용하지 않아 가능성 배제.
* Redlock / 분산 락 분할-브레인: 분산 락은 서버의 복제 역할을 변경하지 않음.
* 일반적인 복제 노드 상태: 복제 노드라면 읽기는 가능해야 하나, 읽기/쓰기 모두 실패했으므로 해당 가능성 낮음.
* 메모리 및 리소스 검토: redis-cli INFO memory 결과, 실제 사용 메모리는 매우 낮았고 OOM (Out-Of-Memory) 문제는 아님. 그러나 maxmemory:0 및 maxmemory_policy:noeviction 설정으로 인해 메모리 제한 없이 계속 데이터를 쌓아 쓰기 작업을 거부할 수 있는 잠재적 위험 확인.
* 근본 원인 추정:
* REPLICAOF 명령의 우발적 실행: 스크립트, 자동화 또는 네트워크 문제로 일시적으로 복제 모드 전환.
* 오래된 Node.js 클라이언트 연결: 네트워크 단절 또는 Docker 컨테이너 glitch 발생 시, 클라이언트 연결 풀이 오래된 상태로 유지되어 오류 해석.
* Docker/네트워크 불안정성: 일시적인 네트워크 파티션 또는 디스크 IO 문제 (AOF/RDB 저장 중) 발생 시 Redis가 보호 모드로 진입.
* 결론적으로, 일시적인 Docker/네트워크 중단과 오래된 클라이언트 연결의 조합이 문제의 원인으로 추정됨. 컨테이너 재시작은 오래된 연결을 끊고 새로 연결하여 문제를 해결.
* 해결 방안:
* 메모리 설정 강화: maxmemory 2gb, maxmemory-policy allkeys-lru 설정.
* 위험한 명령어 비활성화: redis.conf에서 REPLICAOF 및 SLAVEOF 명령어 비활성화 (rename-command REPLICAOF "", rename-command SLAVEOF "").
* 디버그 플레이북 생성: 장애 발생 시 즉시 재시작 대신 INFO replication, INFO stats, CONFIG GET replica-read-only, docker logs 등 진단 명령 실행.
* 아키텍처 재고: 단일 노드 대신 Primary + Replica + Sentinel 구성으로 고가용성 확보 및 실시간 협업 부하 분리.
시사점
단일 노드 Redis 환경에서 발생하는 'READONLY' 오류는 실제 복제 상태 변화보다는 클라이언트 연결의 불안정성과 일시적인 인프라스트럭처 문제의 복합적인 결과일 수 있으며, 메모리 설정 강화와 위험 명령어 비활성화, 그리고 고가용성 아키텍처 도입을 통해 안정성을 확보해야 합니다.
댓글
GitHub Discussions