Redis Architecture Overview

<< Start Redis Server Redis Server Performance >>

Redis Main Flow

Redis Main Flow

Main Flow

  1. initServerConfig: 서버 구성을 위한 설정값(파라미터)를 디폴트로 넣는다.
  2. loadServerConfig: redis.conf 파일에서 파리미터를 읽어서 넣는다.
  3. initServer: 레디스 서버의 메인 작업으로 Time Event와 File(I/O) Event를 등록한다. 자세한 내용은 아래에 설명한다.
  4. loadDataFromDisk: AOF나 RDB 파일을 읽어 데이터를 넣는다. 이때는 SET/GET같은 데이터 명령은 처리하는 않지만, INFO 같이 정보를 얻기 위한 명령은 실행할 수 있다.

initServer

#define CONFIG_MIN_RESERVED_FDS 32
#define CONFIG_FDSET_INCR (CONFIG_MIN_RESERVED_FDS+96)
initServer() {
    server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);
    aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL)
    aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE, acceptTcpHandler,NULL)
}
  • Time Event: serverCron: 1초에 10번 실행, 10 Hz
  • File(I/O) Event: acceptTcpHandler: Client 요청 처리

serverCron

  • clientsCron: 1초에 10번 실행되며 한번 실행될 때 '클라이언트 수'/10 개수 만큼 처리한다. 따라서 모든 클라이언트가 1초에 한번을 처리된다.
    • clientsCronHandleTimeout: 클라이언트가 timeout 시간(초) 동안 아무 명령을 내리지 않으면 연결을 해제한다.
    • clientsCronResizeQueryBuffer: 클라이언트의 querybuf가 1kb 이상이면 빈 공간을 해제한다.   정확히는 (32kb 초과)이거나 (ideltime 2초 초과하고 1kb를 초과)하면 -> free가능한 space가 1kb 이상이면 sdsRemoveFreeSpace() 동작한다.
  • databasesCron:
    • activeExpireCycle: if (lazyfree_lazy_expire==yes) dbAsyncDelete() else dbSyncDelete();
    • activeDefragCycle:
    • tryResizeHashTables: Resize
    • incrementallyRehash: Rehash: 새 버킷 할당후 rehash 실행 -> Active rehashing uses 1 millisecond every 100 milliseconds of CPU time
  • rdbSaveBackground: 자식 프로세스가 rdb 파일을 만든다.
  • rewriteAppendOnlyFileBackground: 자식 프로세스가 AOF 파일을 다시 만든다.
  • replicationCron: 클론이 Full sync를 요청할 때 startBgsaveForReplication을 실행해서 rdb 파일을 만들어서 클론에게 보낸다.
  • clusterCron: 레디스 서버가 클러스터 노드(cluster-enabled yes)일 때 노드간 확인 작업등을 실행한다.

acceptTcpHandler

  • createClient: 클라이언트 요청(명령)을 처리한다.

createClient

Redis Client Flow
  • c->cmd->proc: 클라이언트 요청(명령)을 처리한다.
  • propagate:
    • feedAppendOnlyFile: 명령을 AOF format올 만든다.
    • replicationFeedSlaves: 명령을 replication backlog(repl-backlog-size)에 넣고 클론에게 보낸다.

beforeSleep

Redis BeforeSleep Flow

Persistence 데이터를 디스크에 저장하는 방법

레디스 주 저장 장치

  • 레디스는 주 저장 장치로 메인 메모리를 사용합니다. 따라서 레디스는 데이터를 잃어 버리지 않도록 디스크에 저장하는 Persistence(영구보관) 기능을 제공합니다.

RDB(Snapshot) 메인 메모리에 있는 모든 레디스 데이터를 디스크에 쓰기

  • RDB는 데이터가 덤프(저장)되는 파일명이 디폴트로 dump.rdb 이기 때문에 RDB라고 합니다.   특정 시점에 주 메모리에 있는 모든 레디스 데이터를 디스크에 쓰기 때문에 기능상으로는 snapshot이라는 용어가 더 맞습니다.   RDB 파일은 binary 형태로 저장됩니다.
  • 저장 조건이 "save 300 10"이면 300초 동안 10번 이상 키가 변경되면 데이터를 디스크에 기록합니다.   save 옵션은 여러 개 사용할 수 있고 or 조건입니다.
  • 자식 프로세스를 생성(fork)해서 디스크 쓰기를 수행합니다. 따라서 원(부모) 프로세스에서 명령을 처리하는데 지장을 주지 않습니다.   하지만 대량의 디스크 I/O가 발생하며 CPU IOwait이 높게 나타납니다.
  • RDB에 대한 자세한 내용은 SAVE, BGSAVE, Format, Loading을 보세요.

AOF(Append Only File) 변경된 데이터를 디스크에 쓰기

  • AOF는 조회 명령을 제외하고 데이터를 입력/수정/삭제 명령을 디스크에 기록합니다. 디스크 기록 시점에 대해서 세 가지 옵션을 제공합니다.
  • always: 명령마다 디스크에 기록합니다. 이 옵션을 사용하면, 문제가 발생했을때 데이터를 안전하게 보관할 수는 있지만, 메모리 DB를 사용하는 것이 의미가 없을 정도로 성능이 떨어집니다.
  • everysec: 1초 마다 디스크에 기록합니다. 데이터 유실을 최소화하면서 성능를 보장하는 최선의 옵션입니다.   이때 1초 마다 하는 디스크 기록은 별로 쓰레드가 수행합니다.   따라서 메인 쓰레드에서 명령을 처리하는데 지장을 주지 않습니다. 대부분의 경우에 권장하는 옵션입니다.
  • no: 디스크에 기록하는 것을 OS(리눅스)가 합니다. 일반적으로 리눅스의 디스크 기록 간격은 30초입니다.
  • AOF에 대한 자세한 내용은 내부구조, Rewrite, Roading, AOF fsync is taking too long, AOF Backup Script, BGREWRITEAOF를 보세요.

Persistence 선택하기



레디스 HA(High Availability) 무중단 서비스 구성

Standalone: No HA, 마스터

  • 레디스 서버 1대로 구성한다. 이것을 마스터 노드라고 한다. 서버 다운 시 AOF 또는 RDB 파일을 이용해서 재 시작한다.

이중화: Half HA, 마스터-슬레이브

  • 레디스 서버 2대(마스터-슬레이브)로 구성한다. 슬레이브는 마스터의 데이터를 실시간으로 전달받아 보관한다.
  • 마스터 다운 시 슬레이브 서버를 이용해서 서비스를 계속할 수 있다. 하지만 이때는 수동으로 슬레이브 서버를 마스터로 변경시켜야 하고, 애플리케이션이 새로운 마스터에 접속해서 서비스를 계속할 수 있도록 구현해야 한다. 그래서 Half HA라고 이름 붙혔다.
  • 한 마스터에 슬레이브를 여러 대 구성할 수 있다. 슬레이브에 또 다른 슬레이브를 둘 수도 있다.
  • 이중화 또는 복제(replication) 대한 자세한 내용은 복제(replication)을 보세요.

이중화 + 센티널 Sentinel: HA, 무중단 서비스 가능

  • 마스터-슬레이브 구성에 센티널을 추가해서 각 서버를 감시하도록 한다. 센티널은 마스터 서버를 감시하고 있다가 다운되면 슬레이브를 마스터로 승격시킨다. 레디스 클라이언트(애플레케이션)은 새로운 마스터로 접속해서 서비스를 계속한다.
  • 다운되었던 마스터가 다시 시작하면 센티널이 슬레이브로 전환시킨다.
  • 센티널은 데이터 처리는 하지 않는다.
  • 일반적으로 센티널을 3대로 구성한다. 이것은 센티널 자체의 다운을 고려한 것이다.
  • 센티널에 대한 자세한 내용은 센티널(Sentinel), Data Structure, 리더 선출을 보세요.

레디스 클러스터 Redis Cluster: HA, 무중단 서비스 가능

  • 샤딩: 클러스터는 샤딩(sharding) 방법을 제공하는 것이다. 클러스터 마스터가 3대이면 데이터가 3대에 나누어 저장된다. 예를 들어, 100개의 데이터가 있다면 1번 마스터에 33개, 2번 마스터에 다른 33개, 3번 마스터에 나머지 34개가 저장되는 방식이다.
  • Hash 함수: 데이터를 나누는 방식은 키에 hash 함수를 적용해서 값을 추출하고, 이 값을 각 마스터 서버에 할당한다. 예를 들어, 1~100까지 나오는 hash 함수가 있고, 클러스터 마스터 서버가 3대이면 1번 서버에 1~33까지, 2번 서버에 34~66까지, 3번 서버에 67~100까지 할당한다.   이것은 클러스터 구성 시에 각 마스터 서버에 할당된다.
  • 16384 슬롯: 레디스에서 hash 값의 개수는 16384(0~16383)이고 이것을 슬롯(slot)이라고 한다.
  • 레디스 클라이언트: 클라이언트는 서버와 동일한 hash 함수를 가지고 있으며, 마스터 서버에 접속해서 각 서버에 할당된 슬롯 정보를 가지고 있다.   키가 입력되면 hash 함수를 적용해서 어느 마스터에 저장할지 판단해서 해당 마스터에 저장한다.
  • 데이터 서버 + 센티널: 각 마스터 서버는 데이터의 처리와 센티널의 역할을 같이 수행한다. 예를 들어, 1번 마스터 서버가 다운되면 나머지 살아있는 마스터들 중에서 리더를 선출해서 리더가 1번 마스터의 슬레이브를 마스터로 승격시킨다.
  • 최소 3대: 마스터 서버는 최소 3대로 구성하고 각각은 슬레이브를 가질 수 있다.
  • 마스터를 관리하는 마스터(master of master)는 없다. 마스터의 마스터가 있으면 단일 장애점(Single point of failure)가 된다.
  • 샤딩(Sharding): 대량의 데이터를 처리하기 위해 여러 개의 데이터베이스에 분할하는 기술이다. 즉 DBMS안에서 데이터를 나누는 것이 아니고 DBMS 밖에서 데이터를 나누는 방식이다. 그러므로 샤드 수에 따라 여러 대의 DBMS를 설치해야 한다.   레디스 클러스터는 샤딩방식이다.
  • 파티셔닝(Partitioning): 대량의 데이터를 처리하기 위해 DBMS 안에서 분할하는 방식이다. 즉 한 대의 DBMS만 설치하면 된다.
  • 클러스터에 대한 자세한 내용은 레디스 클러스터을 보세요.

클러스터 구성 Case 1

  • 머신(Box) 3대, 마스터 3대, 슬레이브 3대 구성
  • Redis Cluster 3 nodes
  • 머신(Box)3 다운 시: 서비스 가능
  • Redis Cluster 3 nodes

클러스터 구성 Case 2

  • Case 1의 단점을 보완하기 위해 마스터당 슬레이브를 2대 씩 둔다.
  • 머신(Box) 3대, 마스터 3대, 슬레이브 6대 구성
  • Redis Cluster 3 nodes
  • 머신(Box)3 다운 시: 서비스 가능
  • Redis Cluster 3 nodes
  • 추가로 머신(Box)2 다운 시: 서비스 가능
  • Redis Cluster 3 nodes


5 Data Types

레디스는 5개 데이터 타입 중에서 하나만 key-value 방식이고, 다른 4개는 키 하나에 여러 개 값을 관리하는 방식이다.   소트 기능, 필드-값 기능도 있으므로 key-value만 제공하는 다른 key-value 데이터베이스보다 활용도가 높다.

Strings 문자열

  • key-value 방식으로 저장한다.
  • Redis strings
  • SET: 데이터를 저장한다. 키가 이미 있으면 기존 데이터를 지우고 새 데이터를 넣는다.
  • GET: 데이터를 가져(조회)온다.
  • DEL: 데이터(키)를 삭제한다.
  • INCR: 값이 숫자일 경우 1 증가한다.
  • 문자열에 대한 자세한 내용은 Strings Intro를 보세요.

Lists 리스트

  • 키 하나에 여러 개의 값을 저장할 수 있다. 값(element)은 중복 가능하다. 입력된 순서를 유지한다.
  • Redis lists
  • PUSH: 리스트의 맨 앞 또는 맨 뒤에 값을 넣는다.
  • POP: 리스트의 맨 앞 또는 맨 뒤에서 값을 꺼내온다.
  • 리스트에 대한 자세한 내용은 LISTS Intro를 보세요.

Sets 셋

  • 키 하나에 여러 개의 값을 저장할 수 있다. 값(member)을 중복할 수 없다. 입력 순서와 상관없다.
  • Redis sets
  • SADD: 셋(집합)에 값을 추가한다.
  • SREM: 셋(집합)에서 값을 제거한다.
  • SUNION: 합집합을 구한다.
  • 셋에 대한 자세한 내용은 SETS Intro를 보세요.

SortedSets 소트셋

  • 키 하나에 여러 개의 값을 저장할 수 있다. 스코어로 소트된다. 스코어가 같으면 값으로 소트된다. 값(member)을 중복할 수 없다.
  • Redis sortedsets
  • ZADD: 셋(집합)에 스코어, 값을 추가한다.
  • ZREM: 셋(집합)에서 값을 제거한다.
  • ZUNIONSTORE: 합집합을 구한다.
  • ZRANK: 순서(인덱스)를 구한다.
  • 소트셋에 대한 자세한 내용은 SORTED SETS Intro를 보세요.

Hashes 해시

  • 키 하나에 필드명, 값으로 여러 개를 저장할 수 있다.
  • Redis hashes
  • HSET: 필드명, 값을 저장한다.
  • HGET: 필드명으로 값을 가져온다.
  • HDEL: 필드명으로 값을 제거한다.
  • HGETALL: 키에 속한 모든 필드명과 값을 가져온다.
  • 해시에 대한 자세한 내용은 HASHES Intro를 보세요.


Redis Clients




<< Start Redis Server Architecture Overview Redis Server Performance >>

질문하거나 댓글을 보려면 클릭하세요.  댓글수 :    조회수 :

Email 返事がかかってなれば、メールでお知らせします。