Redis 운용하기
Redis 운용하기
스터디에서 Redis를 영구 저장하도록 save 설정을 켜두면 사용한다면 겪게 될 문제들에 관한 얘기를 나눠보았다. 나눈 얘기에 대한 요약본이다.
영구적으로 컴퓨터를 껐다 켜도 복원되도록 사용하면 주의해야 할 점이 몇 가지 있다.
용어
Redis
간단하게 Redis는 in-memory, single thread, key-value database이다.
- in-memory이기에 디스크 저장하는 기능을 꺼두면 기본적으로 껐다켰을 때 올라간 메모리가 휘발되어 데이터가 비어있다.
- 재시작해도 데이터가 유지가 됐다면 영구적으로 하드에 백업되고 있다는 말이다. (기본값)
Save(snapshot을 생성)할 때 동작
Redis에서 RDB(기본값), 혹은 AOF persistence를 켜두면 fork
를 사용해서 백업을 한다. (참고)
기본값으로 RDB가 설정되어 있기 때문에 필요 없으면 꺼야 한다. 설정한 주기로 Snapshot을 저장하는 RDS 방식을 예로 들어서 설명해 보겠다.
snapshot을 저장하는 것은 데이터 자체를 통째로 dump 떠서 백업을 Disk에 저장하는 것이다.
싱글 스레드인 Redis는 이때 fork를 써서 메모리에 있는 파일을 저장한다.
참고
fork()
: CoW(Copy on Write) - 일단은 할당 X, 복사는 write 할 때 일어난다.
- write가 계속 발생한다면 이론적으로 약 2배 정도 추가 할당 가능
RSS
- RSS(Resident Set Size): 해당 프로세스에 할당되고 RAM에 있는 메모리 양 (실제 OS가 보는 Physical Memory)
주의할 것
OOM Killer
Out Of Memory란?
- 사이드 프로젝트로 "AWS t2.micro"처럼 작은 거에 억지로 도커나 Redis 깔면 자주 발생
- OS는 메모리가 부족할 경우 특정 프로세스를 강제로 종료할 수 있다.(참고)
maxmemory를 2배 정도 여유롭게 한다면?
Redis는 jemalloc을 사용해서 메모리를 할당한다. 이걸로 메모리 파편화가 줄어들었지만 당연히 완전히 없애진 못한다.
* jemalloc: general purpose malloc implementation that emphasizes fragmentation avoidance and scalable concurrency support
OOM을 대비해서 maxmemory를 2배 증설하더라도 OOM Kill 발생 가능!
- 어쩔 수 없이 OS단에서 자원이 해제되지 않는 경우도 있다
- 1byte 필요 → 실제로 4kB(1 페이지) 할당
- 왜? OS는 “Page 단위 할당”
- 4byte 사용 후 2byte 삭제 → fragmentation
- 엄청 오래 띄워두면 더 파편화될 가능성도 높다
rss
: 32kb ← memory: 4kb
해결법
- Swap memory: swap에 페이지 생성 시 엄청 느려질 수 있음
- 아예 shutdown 되는 것은 막을 수 있지만 성능을 위해 끄는 경우도 있음
- Persistent 하게 쓰지 않기: save 기능을 끄고 cache로만 쓰면 fork를 걱정할 일 없음
그럼 어느 정도로 사용하면 좋을까요?
실제 사용량을 모니터링해야 한다!
Persistent Store로 쓰는 경우 Disk save에 Save
- Read가 강하면 30% ~ 60%
- Write가 강하면 30% ~ 40%
여유롭게 벗어나면 마이그레이션 해야 하지 않을까?
이런 기준점은 서비스 성격에 맞춰서 여러 실험도 하고 모니터링을 해봐야지 알 수 있을 것이다.
문제의 상황 생각해 보기
현재 Redis의 상황
- 서버의 RAM의 70%를 쓰고 있다
- 서비스 특성상 Write가 자주 발생한다
- 느려질까봐 swap을 꺼뒀다
상상해 보기
Redis 인스턴스를 설치해서 2달 동안 사용하고 있다. 혹시 모를 경우를 대비해서 자동 백업을 켜뒀다. 일부러 여유롭게 Redis의 maxmemory를 현재 ram의 40% 정도만 쓰도록 설정했다. 하지만 자꾸 OOM(Out of Memory)이 발생해서 죽는다.
왜 그럴까?
이런 일을 방지하려면 어떤 값을 모니터링해야 할까?