레디스 운영 잘하는 법

이 포스팅은 지난 12.4일에 있었던KOSSCON강대명님의 레디스 운영 잘하는 법 을 듣고 발표자료와 발표내용을 종합하여 작성한 포스팅으로 대부분 발표자료에 있는 내용입니다. 글로 보고싶으신 분들 및 세션 내용 정리를 위해 겸사겸사 정리했습니다.

Redis 운영잘하는 법 정리

발표자료 : PPT링크
발표자 : 강대명님

Redis 소개

  • In Memory data structure store
  • 오픈소스
  • data structure 지원
    • Strings, set, hash, list
    • sorted-set(랭킹시스템 할때 좋음)
      • 그러나 데이터 100만건 넘어가면 느려짐(초당 백만건 순회)
    • Hyperlog, bitmap, geospatial index
    • Stream

Redis 운영

  • 메모리 관리를 잘하자! 99.999퍼 중요!

    • physical memory 이상을 사용하면 swap 메모리를 사용하게됨
    • swap 사용하면 메모리 page 접근시마다 읽고 쓰기 때문에 엄청 느려짐
    • 보통 레디스 갑자기 느려졌다 하면 이 이유임
    • max 메모리를 설정하더라도 이보다 더 사용하게됨(다른 프로세스들도 메모리를 사용하기 때문)
    • RSS 값을 모니터링 해야함
    • 적은 메모리 사용하는 instance 여러개가 안전
      • redis 는 싱글 쓰레드이기 때문
      • 따라서 여러개의 인스턴스가 좋다
      • 큰 메모리일시 elastic cache 쓰면 상관없음(걔가 알아서 관리해줌)
    • 메모리 파편화
      • 실제로 메모리 파편화가 많이 발생함
      • jemlloc 버전에 따라서 다르게 파편화가 발생
        • jemlloc 4.x 대 부터 메모리 파편화 줄이기 위한 jemalloc에 힌트를 주는 기능이 들어감
        • jemlloc 3.x 버전은 used memory 2GB라고 나오지만 실제론 11GB RSS를 사용하는 경우가 자주 발생함
      • 다양한 사이즈를 가지는 데이터보단 유사크기의 데이터를 가지는 경우가 유리함
    • 메모리 부족시?
      • 장비 마이그레이션
        • 메모리 빡빡하면 마이그레이션중 문제생길수도 있다 넉넉하게 하자
      • 있는 데이터 줄이기
        • 특정 데이터를 줄일때 이미 swap 사용중이라면 프로세스 재시작 해야됨
      • 메모리를 줄이기위한 설정
        • Collection
          • Hash -> HashTable 하나 더 사용
          • Sorted Set -> Skiplist와 HashTable 이용
          • Set -> HashTable 사용
          • 위의 자료구조들은 메모리 많이 사용함
        • Ziplist 이용
          • 인메모리 특성상 적은 개수(100만개 이하)라면 선형탐색이 정말 빠름
          • 게다가 ziplist는 기존 자료구조보다 메모리를 적게 먹음!
          • 그러니 List, hash, sorted set 등을 ziplist로 대체하자
            • hash-max-ziplist-entries, hash-max-ziplist-value
            • list-max-ziplist-size, list-max-ziplist-value
            • zset-max-ziplist-entries, zset-max-ziplist-value
          • 만약 설정갯수 오버하면 원래 설정 구조로 바뀌게됨(n개 이상이면 원래 hash로 돌아감.. 이런식)
  • O(n) 관련 명령어 조심하자!

    • 레디스는 싱글 쓰레드
      • 레디스는 동시에 여러개의 명령을 처리할 수 없음 그러니 오래걸리는 일 시키면 안됨
      • 단순한 get/set의 경우 초당 10만 TPS 이상 가능
    • 오래걸리는 대표적인 O(N) 명령들
      • KEYS
      • FLUSHALL, FLUSHDB
      • Delete Collections
      • Get All Collections
    • 대표적인 실수 사례
      • Key가 백만개 이상인데 Key 명령을 사용하는 경우
      • 아이템이 몇만개 든 hash, sorted set, set에서 모든 데이터를 가져오는 경우
      • spring security oauth redis tokenStore 문제
    • 대안
      • KEYS -> Scan
        • scan 명령으로 하나의 긴 명령을 짧은 여러번의 명령으로 바꿈
      • Collection의 모든 아이템을 가져와야 할때
        • Collection 일부만 가져오거나
        • 큰 Collection을 작은 여러개의 Collection으로 나눠서 저장
        • Userranks -> Userrank1, Userrank2, Userrank3
        • 개당 몇천개 안쪽으로 저장하는게 좋음
      • Spring security oauth RedisTokenStore 이슈
        • 스프링 시큐리티 레디스 토큰조회를 O(N) 으로 하고있었음
        • 100만개 넘어가면 검색/삭제 한번 하는데에 1초씩 걸렸음
        • O(N) -> O(1) 로 고쳐짐, 따라서 지금은 괜찮음

Redis Replication

  • Async Replication
    • Replication Lag 이 발생할 수 있다.
  • “Replicaof’(>= 5.0.0) or ‘slaveof’ 명령으로 설정 가능
    • Replicaof hostname port
  • DBMS로 보면 statement replication가 유사
  • Replication 설정 과정
    • Secondary에 replicaof or slaveof 명령을 전달
    • Secondary는 Primary에 sync 명령 전달
    • Primary는 현재 메모리 상태를 저장하기 위해
      • Fork
    • Fork 한 프로세서는 현재 메모리 정보를 disk에 dump
    • 해당 정보를 secondary 에 전달
    • Fork 이후의 데이터를 secondary에 계속 전달
  • Redis Replication 시 주의할 점
    • Replication 과정에서 fork 가 발생하므로 메모리 부족 발생할 수 있다.
    • Redis-cli –rdb 명령은 현재 상태의 메모리 스냅샷을 가져오므로 같은 문제를 발생시킴
    • AWS나 클라우드의 Redis는 좀 다르게 구현되어서 좀더 해당 부분이 안정적
    • 많은 대수의 Redis 서버가 Replica를 두고 있다면
      • 네트웍 이슈나, 사람의 작업으로 동시에 replication이 재시도 되도록 하면 문제가 발생할 수 있음.
      • ex) 같은 네트웍안에서 30GB를 쓰는 Redis Master 100대 정도가 리플리케이션을 동시에 재시작하면 어떤 일이 벌어질 수 있을까?

권장 설정

  • redis.conf 권장 설정 Tip
    • Maxclient 설정 50000
    • RDB/AOF 설정 off
    • 특정 commands disable
      • Keys
      • AWS의 ElasticCache는 이미 하고 있음.
    • 전체 장애의 90% 이상이 KEYS와 SAVE 설정을 사용해서발생.
    • 적절한 ziplist 설정

Redis Cluster

  • Hash 기반으로 Slot 16384 로 구분
    • Hash 알고리즘은 CRC16을 사용
    • Slot = crc16(key) % 16384
    • Key가 Key{hashkey} 패턴이면 실제 crc16에 hashkey가 사용된다.
    • 특정 Redis 서버는 이 slot range를 가지고 있고, 데이터 migration은 이 slot 단위의 데이터를 다른 서버로 전달하게 된다.(migrateCommand 이용)
  • Redis Cluster의 장점/단점
  • 장점
    • 자체적인 Primary, Secondary Failover.
    • Slot 단위의 데이터 관리.
  • 단점
    • 메모리 사용량이 더 많음
    • Migration 자체는 관리자가 시점을 결정해야 함.
    • Library 구현이 필요함.

Redis Failover

  • Coordinator 기반 Failover
    • Zookeeper, etcd, consul 등의 Coordinator 사용
    • 장점
      • Coordinator 기반으로 설정을 관리한다면 동일한 방식으로 관리가 가능.
    • 단점
      • 해당 기능 이용을 위한 개발(라이브러리)이 필요함
  • VIP/DNS 기반 Failover
    • VIP
    • DNS
      • 아마존은 이 방식을 사용하고 있음
    • 장점
      • 클라이언트에 추가적인 구현이 필요없다.
      • VIP 기반은 외부로 서비스를 제공해야 하는 서비스 업자에 유리(예를 들어 클라우드 업체)
    • 단점
      • DNS 기반은 DNS Cache TTL을 관리해야 함.
      • 사용하는 언어별 DNS 캐싱 정책을 잘 알아야 함
      • 툴에 따라서 한번 가져온 DNS 정보를 다시 호출 하지 않는 경우도 존재
  • Redis Cluster 의 사용

모니터링

  • Monitoring Factor
    • Redis Info를 통한 정보
      • RSS
      • Used Memory
      • Connection 수
      • 초당 처리 요청 수
    • System
      • CPU
      • Disk
      • Network rx/tx
  • CPU가 100% 칠 경우
    • 처리량이 매우 많다면
      • 좀 더 CPU 성능이 좋은 서버로 이전
      • 실제 CPU 성능에 영향을 받음
        • 그러나 단순 get/set은 초당 10만 이상 처리가능
    • O(N) 계열의 특정 명령이 많은 경우.
      • Monitor 명령을 통해 특정 패턴을 파악하는 것이 필요
      • Monitor 잘못쓰면 부하로 해당 서버에 더 큰 문제를 일으킬 수도 있음.(짧게 쓰는게 좋음)

결론

  • 기본적으로 Redis는 매우 좋은 툴
  • 그러나 메모리를 빡빡하게 쓸 경우, 관리하기가 어려움
    • 32기가 장비라면 24기가 이상 사용하면 장비 증설을 고려하는 것이 좋음.
  • Write가 Heavy 할 때는 migration도 매우 주의해야함.
  • Client-output-buffer-limit 설정이 필요.

레디스를 캐시로 쓴다면

  • Cache 일 경우는 문제가 적게 발생
    • Redis 가 문제가 있을 때 DB등의 부하가 어느정도 증가하는 지 확인 필요.
    • Consistent Hashing도 실제 부하를 아주 균등하게 나누지는 않음. Adaptive Consistent Hashing 을 이용해 볼 수도 있음.

레디스를 Persistent Store로 쓴다면

  • 무조건 Primary/Secondary 구조로 구성이 필요함
  • 메모리를 절대로 빡빡하게 사용하면 안됨.
    • 정기적인 migration이 필요.
    • 가능하면 자동화 툴 을 만들어서 이용
  • RDB/AOF가 필요하다면 Secondary에서만 구동