반응형
레디스 인코딩에 대해서..
- Redis 는 데이터의 주 저장소로 메모리를 사용함.
- 메모리
- 운영 체제의 관점에서 한정적인 자원이며 매우 비싼 리소스임.
- 메모리
- Redis 개발자는 제한적인 환경에서 데이터를 효율적으로 저장하기 위해서 인코딩을 사용함.
문자열 데이터 인코딩
- 문자열을 저장하기 위해서 3가지 인코딩을 사용함.
- OBJ_ENCODING_INT
- value가 정수임을 나타낸다. 실수(소숫점 포함)는 string으로 분류된다.
- 단, 숫자가 0으로 시작하면 string이다. 예를 들어 123은 int이고 0123은 embstr이다.
- 그리고, 64bit 환경에서 long int형의 max 값(9223372036854775807)을 벗어나면 embstr 임.
- 참고#1) 64bit 환경의 long int형 범위
- -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
- The number 9,223,372,036,854,775,807 is the integer equal to 263 − 1.
- 참고#2) C 언어에 type에 대한 size
- OBJ_ENCODING_EMBSTR
- value가 string이고 44문자 이하임을 나타낸다.
- embedded string, embstr은 3.0부터 표시된다.
- 이전 버전은 raw로 표시되었음.
- OBJ_ENCODING_RAW
- value가 string이고 45문자 이상임을 나타낸다.
- 인코딩 확인 object 명령
- redis> object encoding [key]
-
- 위 예제를 통해서 redis 의 문자열 데이터 인코딩에 대해서 확인 해볼 수 있음.
- thub:key:1 의 값
- Redis는 10000보다 작은 숫자를 미리 공유객체 상수로 등록해 두어 같은 객체를 재사용함.
- 공유객체상수를 쓰면, 동일한 값을 가지는 데이터를 한 번만 저장하므로 메모리 낭비를 막을 수 있음.
- 다시말해서, 1000개의 key에 10000보다 작은 동일한 숫자 1181 를 저장하면, Redis는 1181의 데이터를 별도의 공간에 저장하지 않음.
- 자세한 사항은, 추후에 정리할 "Redis 공유객체" 편에서 자세히 설명하겠습니다. ^^; 잠시만 기둘려주세욤
- thub:key:2 의 값
- long int형의 max 값(9223372036854775807) 을 벗어나지 않았으므로 int 인코딩
- thub:key:3 의 값
- long int형의 max 값(9223372036854775807) 을 벗어났으므로 embstr 인코딩
- thub:key:4 의 값
- 44문자 이하이므로 embstr 인코딩
- thub:key:5 의 값
- 45문자 이상이므로 raw 인코딩
-
- redis> object encoding [key]
- Redis 의 SET 명령 소스
- t_string.c 파일의 setCommand() 함수에서 수행됨.
- setCommand 함수는 명령 수행을 위한 데이터 검증이 완료된 후 tryObjectEncoding()라는 함수를 수행하여 적당한 인코딩을 선택하는 로직으로 구성됨.
- 즉, 입력된 데이터에 대해서 가능한 한 적은 메모리를 사용하는 인코딩을 선택함.
- 참고) tryObjectEncoding() 함수
- 단, object.c 파일에 정의되어 있음
- setCommand 함수는 명령 수행을 위한 데이터 검증이 완료된 후 tryObjectEncoding()라는 함수를 수행하여 적당한 인코딩을 선택하는 로직으로 구성됨.
- t_string.c 파일의 setCommand() 함수에서 수행됨.
robj *tryObjectEncoding(robj *o) {
long value;
sds s = o->ptr;
size_t len;
/* Make sure this is a string object, the only type we encode
* in this function. Other types use encoded memory efficient
* representations but are handled by the commands implementing
* the type. */
serverAssertWithInfo(NULL,o,o->type == OBJ_STRING);
/* We try some specialized encoding only for objects that are
* RAW or EMBSTR encoded, in other words objects that are still
* in represented by an actually array of chars. */
if (!sdsEncodedObject(o)) return o;
/* It's not safe to encode shared objects: shared objects can be shared
* everywhere in the "object space" of Redis and may end in places where
* they are not handled. We handle them only as values in the keyspace. */
if (o->refcount > 1) return o;
/* Check if we can represent this string as a long integer.
* Note that we are sure that a string larger than 20 chars is not
* representable as a 32 nor 64 bit integer. */
len = sdslen(s);
if (len <= 20 && string2l(s,len,&value)) {
/* This object is encodable as a long. Try to use a shared object.
* Note that we avoid using shared integers when maxmemory is used
* because every object needs to have a private LRU field for the LRU
* algorithm to work well. */
if ((server.maxmemory == 0 ||
!(server.maxmemory_policy & MAXMEMORY_FLAG_NO_SHARED_INTEGERS)) &&
value >= 0 &&
value < OBJ_SHARED_INTEGERS)
{
decrRefCount(o);
incrRefCount(shared.integers[value]);
return shared.integers[value];
} else {
if (o->encoding == OBJ_ENCODING_RAW) sdsfree(o->ptr);
o->encoding = OBJ_ENCODING_INT;
o->ptr = (void*) value;
return o;
}
}
/* If the string is small and is still RAW encoded,
* try the EMBSTR encoding which is more efficient.
* In this representation the object and the SDS string are allocated
* in the same chunk of memory to save space and cache misses. */
if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT) {
robj *emb;
if (o->encoding == OBJ_ENCODING_EMBSTR) return o;
emb = createEmbeddedStringObject(s,sdslen(s));
decrRefCount(o);
return emb;
}
/* We can't encode the object...
*
* Do the last try, and at least optimize the SDS string inside
* the string object to require little space, in case there
* is more than 10% of free space at the end of the SDS string.
*
* We do that only for relatively large strings as this branch
* is only entered if the length of the string is greater than
* OBJ_ENCODING_EMBSTR_SIZE_LIMIT. */
trimStringObjectIfNeeded(o);
/* Return the original object. */
return o;
}
- 설명
- redis.conf 환경설정 파일에 maxmemory 설정이 지정되어 있지 않으면, 지정하려는 값이 레디스 공유 객체 상수의 숫자범위안에 포함되는지 검사함.
- 미리 지정되어 있는 숫자상수의 범위는 0 ~ 9999
- server.h 에 아래가 정의되어 있음.
- #define OBJ_SHARED_INTEGERS 10000
- 즉, maxmemory 설정을 지정하지 않으면 시스템에서 제공하는 메모리를 최대한 사용함.
- 결과적으로 redis.conf 환경설정에 메모리 사용 제한이 되어 있지않으면서, 10000보다 크거나 같은 수를 저장하면 별도의 메모리 공간을 할당하여 OBJ_ENCODING_INT 인코딩으로 저장함.
- 10000보다 작은 숫자는 동일한 객체를 참조하기 때문에 추가적인 저장공간을 사용하지 않고 10000보다 크더라도 long 범위 안에 포함되는 숫자면 OBJ_ENCODING_INT 인코딩을 사용하여 저장하기 때문에 더 효율적인 메모리 사용량을 보이게됨.
- 소스의 주요 요지는 효율적인 메모리 사용을 위한 인코딩을 Redis 는 지향한다임.
결론
- Redis 는 문자열 데이터를 3가지 방법으로 인코딩해서 사용함.
- OBJ_ENCODING_INT
- OBJ_ENCODING_EMBSTR
- OBJ_ENCODING_RAW
- 인코딩을 확인하는 명령어를 지원함.
- object encoding [key]
- 소스에 구현된 주요 내용에 대해서 말하자면,
- Redis 는 효율적인 메모리 사용을 위한 인코딩을 지향하고 그렇게 구현되어 있음.
- 오늘의 명언 한마디
- 내가먼저 적극적인 관심과 인간적인 모습을 보이고, 상대방에게 도움이 될 사람이라는 것을 어필해야한다. -신형강(부룡)지음, "부동산 투자 이렇게 쉬웠어?" 중에서...
- 오늘의 영어 한마디
- 질문) Sorry, I'm late!
- 늦어서 미안해.
- 대답) We were afraid you wouldn't make it on time!
- 걱정했자나..
- 해설
- sorry 는 "미안" 이라고 해석함.
- "We were afraid ~" 는 직역하면, "네가 시간에 맞추지 못할 것 같아 걱정했다."
- be afraid 는 "걱정하여(염려하여, 두려워하여)" 임.
- make it 은 "성공하다" 라는 의미이지만, 시간을 주제로 할 땐 "제시간에 맞추다"라는 의미가 됨.
- 질문) Sorry, I'm late!
728x90
300x250
'좋아하는 것_매직IT > 9.redis' 카테고리의 다른 글
21.Redis, 레디스 인코딩 중 셋 데이터 인코딩 에 대해서 알아볼께요.^^ (0) | 2021.01.14 |
---|---|
20.Redis, 레디스 인코딩 중 리스트 데이터 인코딩 에 대해서 알아볼께요.^^ (0) | 2021.01.14 |
18.Redis, 레디스 객체(Redis Object)에 대해서 알아볼까요? (0) | 2021.01.14 |
17.Redis, 제디스(Jedis) 사용한 간단한 프로그램 예시를 코딩해 볼께요.^^ (0) | 2021.01.14 |
16.Redis, 송/수신 프로토콜에 대해서 알아볼께요.^^ (0) | 2021.01.14 |