이 포스팅은 지난 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로 돌아감.. 이런식)
- Collection
- 장비 마이그레이션
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) 로 고쳐짐, 따라서 지금은 괜찮음
- KEYS -> Scan
- 레디스는 싱글 쓰레드
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 정보를 다시 호출 하지 않는 경우도 존재
- VIP
- Redis Cluster 의 사용
모니터링
- Monitoring Factor
- Redis Info를 통한 정보
- RSS
- Used Memory
- Connection 수
- 초당 처리 요청 수
- System
- CPU
- Disk
- Network rx/tx
- Redis Info를 통한 정보
- 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에서만 구동