본문 바로가기

Tech/데이터베이스

[Database] Redis 찍먹

Redis란

  • 공식 사이트 소개
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

Redis는 데이터베이스, 캐시 및 메시지 브로커로 사용되는 오픈 소스(BSD 라이선스), 인메모리 데이터 구조 저장소입니다. Redis는 문자열, 해시, 목록, 집합, 범위 쿼리가 있는 정렬된 집합, 비트맵, 하이퍼로그 로그, 지리 공간 인덱스 및 스트림과 같은 데이터 구조를 제공합니다. Redis에는 복제, Lua 스크립팅, LRU 축출, 트랜잭션 및 다양한 수준의 디스크 지속성이 내장되어 있으며 Redis Sentinel 및 Redis 클러스터를 통한 자동 파티셔닝을 통해 고가용성을 제공합니다.
  • 주목할만한 특징은 다음과 같았다.
    • In-memory : 기존 RDBMS는 데이터를 디스크에 저장하는 방식이기 때문에 느리다는 단점이 있었음. Redis는 메모리상에 데이터를 관리하기 때문에 빠른 속도로 데이터 접근이 가능(데이터 영속화를 위해 디스크에 저장하는 작업을 수행하기도 함 → 추가적인 학습 필요)
    • key-value 구조 : 별도의 쿼리 없이도 key를 통해 데이터를 간단히 가져올 수 있음.
    • single-thread : race condition을 피해 데이터의 정합성을 보장하기 쉬움
    • 다양한 자료구조 지원 : RDBMS와 다르게 다양한 자료구조를 제공함
    • ...

 

Redis 사용 사례

운영 중인 웹 서버에서 key-value 형태의 데이터 타입을 처리해야 하고, I/O가 빈번히 발생해 다른 저장 방식을 사용하면 효율이 떨어지는 경우에 주로 사용

  • DB 캐싱 : 많은 요청이 db로 접근하게 되면 db서버에 무리가 갈 수 밖에 없음. redis를 캐시 서버로 사용한다면 요청된 결과를 미리 저장해두었다가 제공하게 되기 때문에 빠르고 서버에 무리가 가지 않게 운영할 수 있다.
  • API 캐싱 : db캐싱과 유사. 동일한 api 요청에 대한 응답을 저장해두었다가 빠르게 응답할 수 있다.
  • 세션 스토어 : 분산 네트워크 환경에서 서버마다 연결된 세션 정보가 다를 수 있음. 각 서버가 세션을 관리하는 것이 아니라 redis가 세션 관리를 전담하여 분산 환경에서 사용자 세션 동기화를 효과적으로 가능하게 한다.
  • 메세지 큐잉 : Redis는 Message Broker 용도로도 사용 가능하다. Redis의 자료구조 중 List를 이용하여 Queue 구현이 가능하다.
  • ...

 

Redis 자료 구조

Redis는 아래의 자료구조를 공식적으로 지원함.

  • Strings : Vinary-safe한 기본적인 key-value 구조
  • Lists : String element의 모음, 순서는 삽입된 순서를 유지하며 기본적인 자료구로 Linked List를 사용
  • Sets : 유일한 값들의 모임인 자료구조, 순서는 유지되지 않음
  • Sorted sets : Sets 자료구조에 score라는 값을 추가로 두어 해당 값을 기준으로 순서를 유지
  • Hahses : 내부에 key-value 구조를 하나더 가지는 Reids 자료구조
  • Bit arrays(bitMaps) : bit array를 다를 수 있는 자료구조
  • HyperLogLogs : HyperLogLog는 집합의 원소의 개수를 추정하는 방법, Set 개선된 방법
  • Streams : Redis 5.0 에서 Log나 IoT 신호와 같이 지속적으로 빠르게 발생하는 데이터를 처리하기 위해서 도입된 자료구조

 

Redis 유의 사항

메모리 관리를 잘하자

  • Redis는 In-Memory Data Store이기 때문에 Physical Memory 이상을 사용할 수 없다.
    • 만약 Swap이 있다면 Swap을 이용해 사용 가능하다.
    • Swap은 메모리 page를 디스크에 저장해두고 필요시 로딩시키고 다른 것 내려놓고... → swap이 발생할 때마다 디스크를 읽는 작업이 필요해지기 때문에 인메모리로 인한 빠른 접근이 가능하다는 redis의 장점이 사라짐
    • swap이 없다면 OOM 발생
  • Max memory를 설정하더라도 이보다 더 사용할 가능성이 큼
    • Max memeory : Redis가 아는, 자기가 사용하는 메모리
    • Redis는 메모리풀을 사용하는 것이 아닌 jemalloc이라는 Memory Allocate 사용. 따라서 Memory Allocate 구현에 따라서 성능이 좌우됨
    • 메모리 페이지 사이즈가 4096 일때, 우리가 1byte 만 달라고 요청하더라도 실제로 jemalloc 은 4096 byte 를 가져와야한다. jemalloc 은 메모리를 페이지 단위로 반환하기 때문이다. 따라서 만약 여기서 또 내가 + 4096 byte 를 더 달라고 요청하면? 나는 실제로는 4097 만 쓰고있지만, 8K 만큼을 할당받아서 사용하고 있는 꼴이 된다.
  • 메모리 파편화를 완화시키려면
    • 큰 메모리를 사용하는 instance 하나보다는 적은 메모리를 사용하는 instance 여러개가 안전함
      • Redis는 Master-slave 구조에서 자식 프로세스를 생성(fork)하는 경우 copy-on-write 방식을 따름.
      • 해당 페이지를 복사한 다음 수정하기 때문에 write 작업에서 최대 메모리를 두배까지 사용하게 됨.
      • 24GB 인스턴스에서 fork를 하려면 48GB가 필요한데, 8GB 인스턴스 3개를 사용하고 그중 하나가 fork를 수행하게되면 16GB만 필요하게 된다.
      • 관리가 귀찮지만 안전하다.
    • 다양한 사이즈를 가지는 데이터보다는 유사한 크기의 데이터를 가지는 경우가 유리하다.
  • 메모리가 부족할 때는?
    • Cache is Cash(돈이 쵝오)
      • 좀 더 메모리가 많은 장비로 Migration
      • 메모리가 빡빡하면 Migration 중에 문제가 발생할 수도 있음. 60~75% 사용하면 Migration하는 것을 추천
    • 있는 데이터 줄이기.
      • 데이터를 일정 수준에서만 사용하도록 특정 데이터를 줄임.
      • 단, 이미 swap을 사용중이라면, 프로세스를 재시작해야함.

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

  • Redis는 Single Thread이기 때문에 Redis가 동시에 처리할 수 있는 명령 갯수는 한번에 1개
  • 그렇다고 느리지는 않음. 단순한 get/set의 경우 초당 10만개를 처리할 수 있다고 함.
  • 주의해야 할 점은 single Thread이기 때문에 처리 시간이 긴 명령어가 들어오면 그 뒤 명령어들은 전부 대기가 필요하다.
  • Redis의 프로세스 처리 과정

    1. 패킷 하나가 들어오면 processInputBuffer 에서 패킷을 하나의 command 로 만든다.
    2. command 가 완성됐는지 확인하고
    3. command 가 완성되었으면 processCommandAndReset 이라는 걸 해서 다시 타고 들어온 후
    4. 그 시점에 완성된 command 하나를 그냥 실행시켜버린다.
    → 이런 상황에서 해당 패킷 하나가 처리되는 동안 뒤의 패킷은 아무것도 못하고 그냥 쌓이는 것
  •  
  • 이러한 동작 과정에서 알 수 있듯 Redis는 한번에 하나의 명령만 실행할 수 있기 때문에 긴 처리시간을 요하는 명령어를 쓰면 불리함.
  • 대표적인 O(N) 명령어
    • KEYS : 모든 아이템을 순회하는 명령. 아이템이 많아지면 서버에서 exception 트리거함
    • FLUSHALL, FLUSHD : 데이터를 다 날림
    • Delete Collections : Collection 내 아이템을 전부 삭제.
    • Get All Collections : Collection 내 아이템을 전부 불러옴.
  • 대처 방법
    • KEYS 대신 scan 명령을 사용하는 것으로 하나의 긴 명령을 짧은 여러번의 명령으로 바꿀 수 있음
    • Collection의 모든 아이템을 다 가져와야할 때는 일부만 가져오거나, 큰 컬렉션을 다른 여러개의 컬렉션으로 나누어 저장한다.

 

(정리는 했지만 여전히 부족한 내용이다. 뼈대를 세웠다 생각하고 이를 배경지식 삼아 하나하나 채워나갈 계획)

 

나중에 볼만한 자료 -> [우아한테크세미나] 191121 우아한레디스 by 강대명님

레디스 명령어 -> [Redis] Redis 설치 및 간단한 사용 방법 (Mac)

[참고]

 

반응형