Redis) 이것이 레디스다 9 - 레디스 내부 구조 1

레디스 객체

레디스는 데이터를 관리하기 위해 redisObject 객체를 사용한다.

1
2
3
4
5
6
7
8
9
// redis.h에 선언되어있다.
typeof struct redisObject {
unsigned type:4; // 레디스에 저장된 객체의 데이터 형
unsigned notused:2; // 사용되지 않는 필드
unsigned encoding:4; // 저장된 데이터의 인코딩 타입
unsigned lru:22; // LRU 시간 정보 : 데이터가 처음 생성되거나 변경된 시간이 기록된다.
int refcount; // 객체가 참조된 횟수 정보
void *prt; // 실제 데이터가 저장된 위치 정보를 가리키는 포인터
} robj

:는 C 언어 구조체에서 사용하는 비트 표기 방식으로
비트필드는 주어진 크기의 데이터를 비트 단이로 잘라서 사용할 수 있기 때문에 제한된 공간에 여러 가지 정보를 저장할 수 있다.

debug object 명령은 지정된 키의 상세 정보를 출력한다.

1
2
127.0.0.1:6379> debug object key1
Value at:0x7f2e0e1903f0 refcount:1 encoding:embstr serializedlength:5 lru:13425835 lru_seconds_idle:27

레디스 인코딩

운영체제 관점에서 메모리는 한정적인 자원이며 매우 비싼 리소스에 해당한다.
제한적인 환경에서 데이터를 효율적으로 저장하기 위해서 인코딩을 사용한다.

문자열 데이터 인코딩

  • REDIS_ENCODING_RAW: 전혀 가공되지 않은 원본 데이터
  • REDIS_ENCODING_INT: 숫자 데이터 인코딩

10,000 보다 작은 숫자를 공유객체 상수로 등록해두어 객체를 재사용하여 메모리 낭비를 줄임

또한 redis.conf 파일에 maxmemory 설정을 해두면 10,000 이상의 수를 저장하면 별도의 메모리 공간을 할당하여 REDIS_ENCODING_INT 인코딩으로 저장한다.

1
2
3
4
127.0.0.1:6379> set key 10001
OK
127.0.0.1:6379> debug object key
Value at:0x7f2e0ab2b780 refcount:1 encoding:int serializedlength:3 lru:13440306 lru_seconds_idle:8

리스트 데이터 인코딩

  • REDIS_ENCODING_ZIPLIST : 리스트 데이터를 저장할 때 더 적은 메모리를 사용
  • REDIS_ENCODING_LINKEDLIST : 일반 Linked List 구조와 동일하다.

REDIS_ENCODING_ZIPLIST 인코딩은 리스트 데이터를 저장할 때 더 적은 메모리를 사용하지만 REDIS_ENCODING_LINKEDLIST 인코딩에 비해 더 많은 CPU를 사용한다.

처음 인코딩은 zip list이지만 이후 element가 추가되면서 linked list로 인코딩이 변경되는데
이는 redis.conf의 list-max-ziplist-entrieslist-max-ziplist-value가 인코딩이 변경되는 경계조건이다.

입력된 데이터가 설정값을 넘어가는 순간 리스트 객체의 인코딩을 변경하려 시도한다.
이때 새로운 리스트를 생성하고 데이터를 복사하는데 이 경계조건이 크다면 새로운 리스트에 복사해야할 데이터양이 많아지게 되서 CPU의 사용량과 소요시간 또한 증가한다.

적절한 설정값은 직접 테스트를 하면서 조율하는 것이 좋다.


현재는 인코딩을 확인하면 quicklist로 나온다.

Quick List는 zip list의 linked list로
linked list의 각 노드의 데이터가 zip list 가지고 있는 데이터타입이다.

참고: http://redisgate.kr/redis/configuration/internal_quicklist.php


셋 데이터 인코딩

Set 데이터는 O(1)의 시간 복잡도를 제공하기 위해서 내부적으로 해시 테이블 구조로 구현되어있다.

  • REDIS_ENCODING_HT : Set 데이터의 기본 인코딩
  • REDIS_ENCODING_INTSET : 숫자 데이터만을 다룰 때 메모리를 절약하기 위한 인코딩

REDIS_ENCODING_INTSET 인코딩은 입력되는 데이터 갯수에 대한 설정인 set-max-intset-entries 설정에서 지정된다.
하나의 설정값만이 존재하는 이유는 INTSET은 숫자 데이터에 대해서만 적용되기 때문이다.

1
2
3
4
5
6
7
8
127.0.0.1:6379> sadd set 200
(integer) 1
127.0.0.1:6379> object encoding set
"intset"
127.0.0.1:6379> sadd set set
(integer) 1
127.0.0.1:6379> object encoding set
"hashtable"
Share