괴발나라

[Redis] 운영 팁 본문

DB/Redis

[Redis] 운영 팁

괴발맨 2023. 5. 14. 20:52
해당 글은 강대명님의 "우아한레디스" 강연을 참조해 쓴 글입니다. (https://www.youtube.com/watch?v=mPB2CZiAkKM&t=2051s)
내용에 오류가 존재할 수 있으니 참고 바라며 건설적인 지적은 정말 환영하겠습니다 😀

Redis

Redis는 메모리를 사용하는 키-값 데이터 저장소이다.

싱글쓰레드로 동작하기 때문에 연산에 Atomic함이 보장된다.

여러 활용 방안이 있다고 하는데, 현재 필자가 개발중인 서비스에서는 캐싱을 위해 사용한다.

Redis 활용 시 크게 세가지를 주의해야 한다고 한다.

1. 메모리 관리

   - Redis는 인메모리 데이터 저장소이기 때문에, 메모리 관리가 중요하다.

2. O(N) 명령어 주의

   - Redis는 싱글쓰레드로 동작하기 때문에 실행 시간이 긴 명령어 사용 시 주의해야한다.

   - 만약 1초가 걸리는 명령어를 실행했다면, 그동안 온 요청들은 모두 기다려야한다. 

3. Replication.

   - Redplication은 Redis의 데이터를 거의 실시간으로 다른 Redis 노드에 복사하는 작업  

     - 출처: http://redisgate.kr/redis/configuration/replication.php

   -  이 부분은 잘 이해가 안되어서.. 좀더 공부하고 글을 작성할 예정.

따라서 이 글에서는 메모리 관리와 O(N) 명령어 관련 내용만 다룬다.

 

메모리 관리

1. 피지컬 메모리를 초과해 사용하지 않도록 주의해야 한다.

   - 스왑을 사용한다면, 해당 메모리 페이지 접근시마다 성능이 저하된다.

   - 스왑을 사용하지 않는다면, OOM이 발생할 수 있다.

2. Maxmemory 설정 시 Redis는 설정한 최대 메모리를 초과해 사용할 수 있음에 주의해야 한다.

  - Maxmemory 설정은 Redis가 설정한 메모리를 초과해 사용하게 되면 랜덤하게 key를 삭제하거나, TTL이 걸린 key를 삭제하여 메모리를 확보하게 해준다.

  - Redis는 자신이 사용하고 있는 메모리를 정확히 알 수 없다. (jmalloc이라는 메모리 얼로케이터를 사용하는데 예를 들어 1바이트를 할당해달라고 하면, 더 큰 사이즈를 할당해 줄 수 있기 때문이라고 한다)

  - 큰 메모리를 가진 인스턴스 하나보다, 작은 메모리를 가진 인스턴스 여러개를 사용하는게 안전하다.

    -> Redis가 fork() 할때 Read 연산은 문제가 없지만, Write 시 메모리의 최대 두배까지 사용할 수 있기 때문임 

    -> 60~75% 메모리를 사용하고 있다면 메모리가 더 많은 장비로 옮기거나 데이터를 삭제하는 등의 방법으로 메모리 확보 필요. (이때 스왑 사용중이면 프로세스 재시작해야함)

   - Hash, SortedSet, Set 컬렉션은 메모리를 많이 사용한다.

     - Ziplist라는 컬렉션이 있는데, 위 컬렉션들이 내부적으로 Ziplist 을 사용하도록 해주는 설정이 있음

     - Ziplist는 성능은 상대적으로 조금 안좋지만 메모리를 2~30% 덜 사용함.

 

O(N) 명령어 주의

- 단순 get/set은 CPU 성능에 따라 10만 TPS 처리 가능하다.

- Redis는 패킷들을 받아 커맨드를 완성한 뒤 커맨드를 실행시키는데, 이때 한 커맨드가 너무 오래걸리면 다른 패킷들이 계속 쌓이는 문제가 발생한다.

- O(N) 명령어들

  - KEYS: 모든 키를 순회

    - scan 명령어로 대체 or 커맨드 자체를 disable 시킨다. (AWS ElasticCache 는 기본적으로 disabled 임)

  - FLUSHALL (모든 데이터베이스의 키들을 삭제), FLUSHDB(현재 데이터베이스의 키들을 삭제)

  - Delete Collections

    - 100만개일 경우 1~2초 소요

  - Get All Collections 

    - 일부만 조회 or 여러개의 Collection으로 나눠 저장해야함

- Spring Security OAuth -> RedisTokenStore

   -> 이전 버전에서는 AccessToken 저장 시 List를 사용해 검색, 삭제 시 모든 item을 매번 조회했으나, 최신버전에서는 Set을 사용해 O(1)이 걸린다고 한다.

 

Replication

- Async Replication이기 때문에 Lag 발생할 수 있음.

  -> 예를 들어, 마스터에는 데이터가 있는데 슬레이브에는 데이터가 없는 경우가 있을 수 있음.

- Statement Replication. 즉 커맨드가 복사되기 떄문에 now()같은 연산이 마스터와 슬레이브에 다르게 저장될 수 있음. 

  -> 일반적으로 문제가 없지만 Lua스크립트 사용 시 문제 생길 수 있다.

- Repication 시 fork 발생하기 때문에 OOM 발생할 수 있다. (이부분은 아예 이해가... 😅)

  -> AWS나 타 클라우드 서비스의 Redis는 좀 더 안정적이라고 한다...

 

권장 설정

- Maxclient -> 50000으로 설정

  - 값이 낮으면 요청이 실패할 수 있기 때문에 큰 값이 좋음

- RDB/AOF 설정 OFF

  - RDB : 백업 시 전체 데이터를 바이너리 형태로 저장

   - AOF : 백업 시 커맨드를 파일 형태로저장.