나의 브을로오그으

#1. [우아한 테크 세미나 191121] 우아한레디스 보고 정리-2부 본문

DB/Redis

#1. [우아한 테크 세미나 191121] 우아한레디스 보고 정리-2부

__jhp_+ 2022. 8. 8. 08:57

[Redis 운영]

- 메모리 관리를 잘하자!

- O(N) 관련 명령어는 주의하자!

 

[메모리 관리를 잘하자!]

- Redis는 In-Memory Data Store이기 때문에 Physical Memory이상을 사용하면 문제가 발생함.

  * Swap이 있으면 Swap 사용으로(Paging) 해당 메모리 Page 접근시 마다 늦어짐.

(Swap이 일어난 페이지는 계속 Swap이 일어날 수 있음. 만약 원하는 Key가 Swap에 의해 Disk에 저장된 페이지라면, 데이터를 읽어올 때마다 Disk에 접근해야함. 성능이 확 떨어짐.)

- Redis의 장점은 In-Memory라서 빠른건데, 디스크에 접근하게 되면 이러한 장점을 잃게됨. 

- 갑자기 느려진다면 이부분을 고려해봐야 함.

- MaxMemory를 설정하더라도 이보더 더 사용할 가능성이 큼.

만약 MaxMemory를 설정했는데 이를 초과한 경우 Redis가 Random하게 key를 지우거나 expire목록을 통해 메모리 확보후에 사용할 때 쓰는 옵션이 MaxMemory이다. 

메모리 Allocator로 제이말록(?)을 사용하는데 이게 성능이 왔다갔다한다.

메모리를 지울 때 지웠다고 제이말록에서 말하지만 실제로는 그 메모리를 아직 가지고 있는 경우도 있을 수 있다.

이런것 때문에 Redis는 자기가 사용하는 메모리의 실제양을 말 할 수가 없다.

 

- 메모리 페이지 사이즈가 4096 byte이라면, 우리가 1byte를 할당하고 싶을 때 얼마를 할당해달라고 해야 할까? 메모리 할당 시 1byte할당 후에 4096byte를 또 할당해 달라고 한다면 어떻게 될까? 제이말록은 

이때 새로운 페이지(4096)크기 만큼 또 메모리를 할당하게 된다. 

나는 4097byte만 쓰지만 실제 할당된 크기는 8K가 된다. 이런일이 계속 발생한다면???

Redis입장에서는 1M밖에 안쓰고 있는데 실제 할당된 크기가 12M일 수 있다.

이런 메모리 파편화가 발생 할 수도 있다. 따라서 MaxMemory를 설정하더라도 메모리 관리를 잘 해야 한다.

 

[메모리 관리]

- 많은 업체가 현재 메모리를 사용해서 Swap을 쓰고 있다는 것을 모를때가 많음.

  * 그래서 사실 모니터링을 해야함.

- 큰 메모리를 사용하는 instance 하나보다는 적은 메모리를 사용하는 instance 여러개가 안전함.

- CPU 4 Core, 32GM Memory의 경우

24GB Instance로 사용하기 보다는 8GB Instance 3개로 쓰는게 안전함.

- Redis는 메모리 파편화가 발생할 수 있음. 4.x 대부터 메모리 파편화를 줄이도록 jemlloc에 힌트를 주는 기능이 들어갔으나, jemalloc 버전에 따라서 다르게 동작할 수 있음.

- 3.x대 버전의 경우

  * 실제 used memory는 2GB로 보고가 되지만 11GB의 RSS를 사용하는 경우가 자주 발생함.

- 다양한 사이즈를 가지는 데이터 보다는 유사한 크기의 데이터를 가지는 경우가 유리!!(메모리 파편화를 덜 일어나게 하는 방법)

 

[메모리가 부족할 때는?]

- Cache is Cash!!

  * 좀 더 메모리 많은 장비로 migration

  * 메모리가 빡빡하면 Migration 중에 문제가 발생할수도....

- 있는 데이터 줄이기.

  * 데이터를 일정 수준에서만 사용하도록 특정 데이터를 줄임.

  * 다만 이미 Swap을 사용중이라면, 프로세스를 재시작해야함.

 

[메모리를 줄이기 위한 설정]

- 기본적으로 Collection들은 다음과 같은 자료구조를 사용

  * Hash -> HashTable을 하나 더 사용

  * Sorted Set -> Skiplist와 HashTable을 이용.

  * Set -> HashTable 사용

  * 해당 자료구조들은 메모리를 많이 사용함.

(이렇게 컬렉션을 동시에 사용하는 건, 값을 찾을 때 인덱스나, 키로 찾을 수 도 있기 때문)

이렇게 사용하면 사실 실제 사용메모리보다 더 많이 씀.

- Ziplist를 이용하자.

 

[O(N)관련 명령어는 주의하자]

- Redis는 Single Threaded.

  * 그러면 Redis가 동시에 여러 개의 명령을 처리할 수 있을까? 1개 (single threaded니까!)

  * 참고로 단순한 get/set의 경우 ,초당 10만 TPS 이상 가능(CPU 속도에 영향을 받는다.)

그런데, 초당 10만개인데 만약 어떤 하나의 트랜잭션이 1초가 걸린다면?

9만9999개의 트랜잭션은 1초동안 대기해야 한다. 보통 타임아웃으로 300ms, 200ms로 잡아놓으면

9만9999개가 거부되면서 서비스가 펑!

- 이런 이슈가 제일 많이 실수하는 이슈다!

 

[Redis의 동작하는 방식이 뭘까?]

- Packet이 들어오면 ProcessInputBuffer에 쌓이고 

들어온 Packet에 해당하는 Command가 완성되면 이를 ProcessCommand에서 그냥 실행하는 구조이다.

따라서 대기중인 Packet은 계속 대기상태이며, 현재 처리중인 Command가 처리되어 loop를 탈출해야 그다음

packet을 처리 할 수 있다. get/set이런 처리는 정말 빠르기 때문에 그냥 쑥~ 10만개까지 처리가 되는건데

1개라도 오래걸리는 작업이 생겨버리면 문제가 생기게 된다.

 

[Single Threaded의 의미]

- 그래서 한번에 하나의 명령어를 처리하기 때문에

  * 절대로!!! 오랜 작업이 필요한 명령을 쓰면 않된다!!!!!

 

[대표적인 O(N) 명령들]

* KEYS는 모든 key를 순회하는 명령어(아이템이 몇십만개이상이 되면 이 명령어를 쓸때마다

Redis 서버가 스파이크를 치면서 각종 서버들이 인셉션을 낸다.)

* FLUSHALL, FLUSHDB는 데이터를 전부 날리는 작업인데..... 일단은 참고

* Delete Collections : 데이터가 엄청나게 많은 상태의 Collection을 지운다면 1~2초 정도 걸린다.

지우는 동안에는 아무것도 못하게 된다.

* Get All Collections : 몇십만개의 데이터를 가져오라고 한다면??? 이것도 굉장히 오래 걸린다.

 

[대표적인 실수 사례]

- Key가 백만개 이상인데 확인을 위해 KEYS 명령을 사용하는 경우

  * 모니터링 스크립트가 일초에 한번씩 KEYS를 호출하는 경우도....

- 아이템이 몇만개 든 hash, sorted set, set에서 모든 데이터를 가져오는 경우

- 예전의 Spring security oauth Redis TokenStore

 

- KEYS는 scan명령으로 대체 짧게짧게 key 값들을 로드,

다시 로드하는데 중간 term 동안에 get/set등의 명령어가 동작하므로 큰 문제가 없이 동작함.

- Collection의 모든 item을 가져와야 할 때?

  * 큰 Collection을 작은 여러개의 Collection으로 나눠서 저장.

 

[Redis Replication]

- Async Replication

  * Replication Lag이 발생할 수 있다.

- 'Replicaof(>=5.0.0) or 'slaveof' 명령으로 설정 가능

  * Replicaof hostname port

- DBMS로 보면 statement replication가 유사

'DB > Redis' 카테고리의 다른 글

#1. [우아한 테크 세미나 191121] 우아한레디스 보고 정리-1부  (0) 2022.08.08
#0. Redis가 뭐지?  (0) 2022.06.21