ch3. 장애처리

adam2·2021년 10월 20일
0

장애 원인

  • redis는 싱글 스레드이기 때문에 한번에 하나의 명령만 처리. 하나의 명령에서 시간이 많이 걸리면 전체 성능 저하가 일어난다.
  • 실제로 더 빠른 CPU, 더 많은 메모리를 달 수록 성능이 좋아지지만, scale up 하더라도 잘못된 사용 패턴은 장애를 일으킬 수 있다

장애 종류

메모리

  • 메모리 과다 사용(maxmemory 설정)
    maxmemory가 설정되었을 때, maxmemory policy에 따라 더이상 eviction할 수 있는 메모리가 없다면 oom에러를 redis가 전달해 명령이 처리되지 않고 명령이 실패한다.
  • rss관리
    redis에서 실제 물리메로리보다 더 많은 메모리 사용시 swap발생하고, 이에 접근할 때 마다 디스크 페이지에 접근할 수 있어서 성능이 떨어진다. 실제 used memory와 rss사용은 다르다.스왑이 발생하면 해당 스왑된 페이지는 해당 프로세스가 종료되기 전까지는 접근할때마다 계속 디스크를 읽게 됨. 이런경우 redis를 내렸다가 다시 올려야 함. 데이터를 지워주거나 다른 장비로 옮겨야함.

발생 이슈

  • redis 처리 속도가 떨어진다.
  • oom 이슈로 처리가 되지 않고 명령이 실패한다
  • Copy on Write 이슈
    • 현재 cow를 redis에서 해결하는 좋은 방법은 없음. 그래서 절반 이하로 메모리 사용량을 유지하면 최대 2배를 해도 여유로워서 가장 좋긴 하다.

    • fork할 경우 부모와 자식 프로세스가 읽기용 메모리는 공유해서 메모리를 절약 -> process는 두개지만 메모리를 하나를 사용

    • 공유 메모리에 쓰기가 발생하는 프로세스가 해당 메모리를 복사해서 사용하게 됨

    • redis child process는 rdb생성을 담당하기 때문에 읽기만 주로 발생

    • aof에서는 자신의 메모리 페이지에 변경이 발생한 프로세스가 해당 메모리 페이지를 복사(fork)한 뒤에 그곳에 write/delete를 실행한다.

    • 따라서 모든 page에 변경이 일어나게되면 물리 메모리는 최대 2배까지 늘어날 수 있게 된다.

    • redis가 fork하게되는 경우

      • replica가 연결이 되는 순간 데이터 이전을 위한 rdb를 만들면서 fork
      • AOF Rewrite를 하기 위한 경우(bgrewriteof 명령) fork
      • RDB 생성을 위한 경우 (bgsave 명령)

      AOF(Append Only File)?
      레디스는 데이터를 메모리에 저장하기 때문에 레디스가 내려가면 모든 데이터는 유실된다.
      이 유실을 방지하기 위해서 AOF기능과 RDB방식을 제공한다.
      AOF는 CUD명령이 실행될 때 마다 버퍼에 기록 후 주기적으로 appendonly.aof 파일로 동기화된다.
      이 파일이 너무 커지면 데이터 전체를 다시 쓰는 rewrite기능이 있다. rewrite를 하면 aof파일 사이즈가 작아지고, 최종 수정된 마지막 값만 남게 된다.

장애 확인 방법

  • application level에서 확인
    • api별 레이턴시 측정
    • redis관련 호출에서 시간이 얼마나 걸리는지 확인
    • redis응답이 무엇이 오는지 확인
  • redis level에서 확인
    • 메모리 사용량이 얼마인지 확인한다
      • used memory와 rss가 현재 설정된 메모리 크기와 유사할 경우 문제가 있는것임
      • os와 다른 프로세스에서 사용하는 메모리 사이즈가 있으므로 , 4g머신에서 만약 3G이상 쓰고 있다면 문제가 될 수 있다. rss 80% 이상 쓰지 않도록 관리 필요
    • slow log가 남는지 확인
      • 사용자가 느끼는 명령의 시간은 A->D이지만, redis에서는 내가 요청한 명령 이전 명령을 처리하는 시간(B)을 제외하고 실제로 해당 명령이 실행되는 시간(C)으로 slow log를 남기기 때문에 우리가 인지하는 시간과 다를 수 있다.

해결방법

  • scale up 하거나 key를 지워서 메모리 확보
    • key를 지운다고 바로 해결되지 않을 수 있음. 메모리 할당을 jmalloc이 해주기 때문에
    • redis는 개별 key hit, miss를 보여주지 않아서 개별로 관리 해야함.
    • 실제 캐시되는 키가 줄어들어 db부하가 늘어날 수 있다.
    • fragmentation이 너무 많이 발생했을 경우에도 메모리 확보 안될 수 있음
  • redis는 항상 fork의 위험성이 있으므로 메모리가 여유로울 수록 좋다.

설정

  • 기본 설정 사용
    기본설정ㅡ로 사용 시에 save 설정이 1시간에 1개, 5분에 100개, 1분에 10000개가 변경이 되면 디스크에 메모리를 덤프하게 되므로, IO를 과다하게 사용해서 장애가 발생한다. (실서비스에서 1분에 10000개 변경은 항상 일어나는 상황이다)

싱글 스레드

  • 과도한 vaule 크기
    redis는 싱글 스레드이기 때문에 하나의 명령이 긴 시간을 차지하면 결국 redis 성능 저하로 이어진다. Hgetall, havals 등의 collection의 데이터를 과도하게 많이 가져온다면 몇 mb이상의 key나 value를 사용할 경우 문제가 발생한다.
  • O(N) 명령의 사용
    keys나 flushcb/flushall, 큰 크기의 collection을 지우는 등의 문제로 redis의 성능을 떨어트린다.
    keys는 scan으로 변경할 수 있다.

0개의 댓글