Redis 2.8 새로 깔면서 RDB, AOF, 둘 다 중 뭘 고를지 꽤 오래 고민. 정리해둔다.
RDB는 포인트-인-타임 스냅샷. save 900 1, save 300 10 같은 조건 만족하면 bgsave 트리거. 내부적으로 fork() 떠서 자식 프로세스가 Copy-On-Write로 메모리 스냅샷을 dump.rdb로 덤프. 장점은 파일이 작고(LZF 압축) 복구가 매우 빠름. rdb 로드는 메모리에 순차 write라 10GB도 몇 분이면 올라온다. 단점은 마지막 스냅샷 이후 분 단위 데이터가 날아갈 수 있다는 점.
AOF는 모든 쓰기 커맨드를 파일에 append. 복구할 땐 서버 시작 시 커맨드를 재생해서 상태 복원. appendfsync가 핵심.
always: 매 커맨드마다 fsync. 안전하지만 느림. SSD여도 TPS가 2~3배 떨어짐everysec: 초당 한 번. 장애 시 최대 1초 손실. 기본값이고 실용적no: fsync는 OS가 알아서. 빠르지만 데이터 손실 범위가 불명확(수십 초 가능)
AOF 파일은 시간이 갈수록 커지니까 BGREWRITEAOF로 현재 메모리 상태를 복원하는 최소 커맨드 집합으로 압축 재작성. 2.4부터 들어간 기능인데 2.8에서는 조건부 자동 rewrite(auto-aof-rewrite-percentage)가 안정화. 이 rewrite 역시 fork 떠서 자식이 수행.
2.8 신기능: RDB + AOF 병행. 원래도 둘 다 켤 수 있었는데 AOF를 우선 로드하는 규칙이 명확해짐. 재시작 시 appendonly.aof → dump.rdb 순. 더 안전한 쪽(AOF)이 기본 선택.
우리 서비스는 캐시 + 세션 저장소. 세션은 날아가도 재로그인으로 복구 가능하고, 캐시는 정의상 휘발성. 대신 재시작 부팅 시간이 민감해서 RDB만 선택. AOF는 끈다.
save 900 1 save 300 10 save 60 10000 rdbcompression yes rdbchecksum yes stop-writes-on-bgsave-error yes dir /var/lib/redis/ dbfilename dump.rdb appendonly no # 2.8에서 유용한 옵션 repl-diskless-sync no # 마스터→슬레이브 풀싱크를 디스크 경유 maxmemory 12gb maxmemory-policy allkeys-lru
stop-writes-on-bgsave-error yes — 디스크 풀이면 bgsave 실패하는데, 이 옵션 on이면 redis가 client의 쓰기를 거부함. 알림 안 걸어놓으면 서비스 전체가 죽은 것처럼 보인다. 모니터링에 rdb_last_bgsave_status 체크 걸기 필수.
fork + COW 함정. bgsave 시작할 때 fork() 떠서 자식이 RDB 쓰기를 수행. 부모는 계속 요청 처리. COW라 실제 복사는 "수정된 페이지"만 일어나는데, 쓰기 트래픽이 높으면 짧은 시간에 메모리 점유량이 순간 2배 근처까지 튄다. 피크 메모리 여유가 없으면 OOM killer한테 잡히거나 swap 타면서 latency 급등.
대응: vm.overcommit_memory=1 커널 파라미터 필수(안 켜면 fork 실패). 스왑은 끄는 쪽이 낫고(장애로 swap 타면 차라리 빨리 죽는게 나음) Transparent Huge Pages도 꺼 둔다(echo never > /sys/kernel/mm/transparent_hugepage/enabled). THP가 켜져 있으면 2MB 페이지 단위라 COW 증폭 효과가 커진다.
모니터링용 INFO 값 메모.
rdb_changes_since_last_save: 마지막 저장 이후 쓰기 건수rdb_bgsave_in_progress: 현재 bgsave 중인지rdb_last_bgsave_time_sec: 지난 bgsave 소요 시간. 이게 10초 넘으면 슬레이브 replication에 영향used_memory_peakvsused_memory: fork 피크 추정
일단 이 설정으로 하루 돌려보고, 문제없으면 슬레이브 한 대 붙여서 복제 구성까지 붙일 예정. slave-read-only yes로 두고.
댓글 없음:
댓글 쓰기