레디스에서 제공하는 자료구조
- Strings
- 단순한 insert 문을 대체하기 위해 사용
- key : Value 형태로 저장하며 모든 종류의 문자열 데이터를 저장할 수 있다.
- 예시: 유저 token 저장, JPEG 이미지를 저장하거나, HTML fragment 를 캐싱 등
- List
- 일반적인 Linked List와 같은 구조로 되어 있어 데이터를 앞에서 넣거나 뒤에서 넣어도 소모되는 시간은 동일하다.
- LPUSH, RPUSH, LPOP, RPOP을 통해 양쪽에 데이터를 넣거나 꺼낼 수 있다. 순차적으로 처리를 해야할 때 유용하다.
- 예시: Job Queue, Pub-Sub 패턴(발행-구독 패턴) 생산자가 아이템을 만들어서 list에 넣으면 소비자가 꺼내와서 액션을 수행하는 식으로 동작합니다.
- 트위터의 타임라인에 있는 트윗을 보여주기 위해 위와 같은 패턴으로 동작합니다.
- Set
- String과 마찬가지로 Key : Value 형태로 저장되지만 Value의 중복된 값을 저장할 수 없는 Set의 형태
- 주로 객체간의 관계를 표현할 때 좋다. (ex: Flow한 유저 목록, 내가 북마크한 게시물 등)
- Sorted Set
- 가장 많이 사용되는 자료구조 중 하나로 <Key><Score><Value> 형태로 저장되며 스코어를 기준으로 정렬되어 저장된다.
- Score는 정수형이 아닌 실수형으로 저장되기 때문에 특정 인터프리터 언어에 표현이 안될 수 있다.
- 유저 랭킹 보드나 상품 랭킹과 같은 특정 데이터로 정렬해야 하는 경우 사용이 된다.
- Hash
- Key : Value안에 Key : Value가 있는 구조로 이중 String 형태이다.
- RDMS의 테이블과 비슷한 형태여서 객체의 상세한 정보를 저장할 때 유용하게 사용될 수 있다.
Collection 주의 사항
- 하나의 Collection 안에 너무 많은 데이터를 넣지 않도록 한다.
- 레디스는 싱글 스레드로 동작하기 때문에 하나의 컬렉션의 많은 데이터를 넣으면 더 많은 리소스와 시간을 소모하게 된다.
- 레디스의 성능에 지장을 주기 때문에 하나의 컬렉션에는 10000개 이하의 데이터를 넣도록 하자
- Expire는 Collection Item에 개별적으로 걸리는 것이 아니다.
- 10000개의 Item을 가진 Collection에 Expire를 걸게 되면 10000개를 가진 Collection이 삭제 되는 것이다.
레디스 운영
운영하면서 주의해야되는 4가지
- 메모리 관리를 잘하자.
- O(n) 명령어는 주의하자.
- Replication
- 권장 설정 TIP
메모리 관리
레디스는 In-memory형 데이터 베이스이다. 이것은 디스크에 정보를 저장하는 RDBMS(MySQL, Oracle)와 다르게 RAM에 데이터를 저장하여 읽기와 쓰기를 할 때 더 빠른 결과를 제공하는 것입니다.
Physical Memory 이상을 사용할 때 Swap 발생
Swap은 유용하지만 인메모리에 대한 대체로 여겨져서는 안됩니다. Swap Space는 디스크에 저장되어 사용되어 지기 때문에 해당 키가 Swap Space에 저장된다면 그만큼 속도가 느려지게 되는 것이기 때문입니다. 그렇다고 Swap을 사용하지 않는다면 OOM발생. 요약하자면 인메모리의 장점이 사라지게 됩니다.
Swap Space
물리적 메모리 (RAM)의 용량이 가득 차게될 경우 사용되는 여유 공간을 말합니다. 적은 RAM 환경에서 유용하다.
OOM(Out Of Memory)
메모리 부족 현상은 대량의 애플리케이션 구동으로 인해 시스템 메모리가 부족할 때 뜨는 현상. OS에 의해 애플리케이션이 다운된다
Max Memory 설정
레디스에 Max Memory를 설정해놓으면 랜덤한 Key를 지우거나 Expire 목록에 있는 데이터를 지우고 메모리를 확보해주는 옵션이다. 레디스는 jmalloc을 통해 메모리를 관리를 해주는데 jmalloc은 실제 우리가 1 Byte만 사용한다 하더라도 4096Byte를 할당해주는데 이유는 페이지 단위로 할당을 해주기 때문입니다. jmalloc에서 메모리를 해제 했다고 하지만 실제로 메모리를 잡고 있는 경우도 있다.
그렇기 때문에 우리는 실제로 사용하고 있는 메모리보다 많이 사용하고 있는 경우가 많습니다. 그래서 RSS(레디스가 사용중인 Physical 메모리값)를 모니터링 해야합니다.
페이징 기법
가상 기억장치를 모두 같은 크기의 블록으로 편성하여 운용하는 기법이다.
하나의 큰 인스턴스 < 여러개의 작은 인스턴스레디스에서 Fork를 하게 되면 메모리를 더 할당하게 됩니다. read만 한다면 상관 없지만 write를 하게 된다면 최대 2배의 메모리를 더 사용하게 될 수 있다고 한다. 그 이유는 Copy On Write 때문이라고 합니다.
Copy On Write
부모 프로세스가 자식 프로세스를 생성(fork)한 직후 프로세스와 메모리 모습이다. 여기서 부모 프로세스가 Page C를 복사할 때 아래의 그림과 같이 Page C를 복사하여 사용한다. 4Byte만 수정하더라도 페이지 단위가 10KB라면 10.004Byte를 더 사용하게 되는 것 입니다. heavy한 Write인 경우 더 많은 메모리를 사용하게 되는 것입니다.
그렇기 때문에 24GB에 메모리의 인스턴스를 사용하는 것 보다 여러개의 작은 8GB 인스턴스를 사용하는 것이 관리하기는 까다롭지만 운영적으로 더 안정적으로 운영할 수 있는 것 입니다.
메모리 관리 정리
- Redis는 메모리 파편화가 자주 일어난다.
- 실제로 사용되는 메모리양이 더 많은 경우가 많다.
- 다양한 사이즈를 가진 데이터보다는 일정한 사이즈를 가진 데이터를 사용하는 것이 메모리 파편화를 줄일 수 있다.
메모리가 적을 경우
- 메모리가 많은 장비로 Migration
- 메모리가 빡빡하다면 문제가 생길 수도 있다. (위와 같은 현상 때문에 80~100%가 아닌 60~75% 정도 사용될 때 하는 것을 권장)
- 데이터 줄이기
- 다만 Swap이 이미 일어난 후라면 프로세스를 재시작하도록 한다.
메모리를 줄이기 위한 방법
- 메모리를 적게 사용하는 Collection 사용
- Hash -> HashTable을 하나 더 사용
- Sorted Set -> Skip List, Hash Table 사용
- Set -> HashTable을 사용
- Ziplist 사용
- 인메모리 특성상 특정 알고리즘을 사용하지 않은 선형 자료구조 여도 빠르다.
- Redis 내부적으로 자료구조를 Ziplist 형태를 사용할 수 있는 옵션이 있다.
O(n) 관련 명령어 사용 주의
- redis는 싱글 스레드 기반으로 동작
- 단순한 get/set은 초당 10만 TPS 처리가 가능
- 하나만 1초만 걸리는 요청을 처리하게 된다면 나머지 요청은 그 요청을 처리할 때까지 대기
O(n) 명령어
- KEYS : 모든 키 조회
- FLUSHALL, FLUSHDB : 데이터 전부 삭제
- Delete Collections : 데이터가 몇십만개 있는 Collection인 경우 시간이 걸림
- Get All Collections : 데이터가 몇십만개 있는 Collection인 경우 시간이 걸림
O(n) 명령어 사례
- KEY가 몇 백만개 있는데 KEYS를 사용하는 경우
- 몇만개의 데이터를 가진 컬렉션의 모든 데이터를 가져 오는 경우
- Spring Security Oauth Redis Store
O(n) 명령어 대체
- KEYS -> SCAN
- Sorted Set에서 일부만 가져와서 사용
- 큰 컬렉션을 작은 컬렉션으로 나누어서 사용
- Spring Security Oauth Redis Store는 List를 통해 데이터를 관리 했었다. 현재는 Set으로 바뀜
Redis Replication
레디스의 데이터를 거의 실시간으로 다른 레디스 노드에 복사하는 작업입니다. 따라서 서비스를 제공하던 첫 번째 레디스 노드가 다운되더라도, 데이터를 받은 두 번째 레디스 노드가 서비스를 계속 할 수 있습니다. 레디스에서는 첫 번째 노드를 마스터라고 하고 두 번째 노드를 복제(replica)라고 합니다.
Async Replication
레디스는 쓰기(write) 명령이 입력되면 실행하고 슬레이브가 있으면 명령어를 복사한다. 내부적으로 명령어 복사를 감지하여 이어서 복사된 명령을 슬레이브 노드에 전달한다. 하지만 이과정에서 Replication Lag가 발생할 수 있다. 이런 경우 다시 커넥션을 끊고 다시 연결하여 작업하기 때문에 굉장히 부하가 많이 일어난다.
Replication Lag
실제 명령어를 통해 데이터를 복제하는 과정에서 데이터가 유실되어 총 스트림이 차이가 나는 경우.
Replication 주의 사항
- Replication 과정에서 Fork를 발생하기 때문에 메모리 부족이 일어날 수 있다.
- redis-cli --rdb도 동일하다.
- AWS나 클라우드 Redis에서의 Replication은 우리가 알던 것과 다르게 동작하기 때문에 안정적이다.
- 많은 대수의 Redis 서버가 많은 개수의 Replica(Slave)를 두고 있다면 동시에 옮기지 않도록 주의 한다. 한번에 많은 네트워크 처리로 인한 이슈개 생길 수 있기 때문이다.
Redis Conf.d 권장 설정
- Max Client 50000 설정 (Max Client 설정만 네트워크에 접속할 수 있기 때문에 Client가 부족하지 않도록 많이 설정)
- RDB/AOF OFF (http://redisgate.kr/redis/configuration/persistence.php 참조)
- 특정 커맨드 Disable(ex: Keys), Elastic Cache같은 클라우드 인프라는 자동으로 설정되어 있음
- 전체 장애는 Default save 옵션이나 Keys 명령어가 대부분이니 그만큼 주의해야 한다.
- 적절한 Ziplist 설정
참조
http://redisgate.kr/redis/configuration/copy-on-write.php
'데이터베이스 > Redis' 카테고리의 다른 글
우아한 Redis 정리(1) (0) | 2022.06.29 |
---|---|
Docker를 통한 Redis 환경 구축하기 (0) | 2022.06.06 |