[입 개발] Redis Internals : sds
몇일 전에 Redis의 아이템 하나의 메모리 한계가 512MB 라고 말씀드렸습니다. 그러면, 오늘은 왜 그런가와 이걸 수정하려고 하면 Redis에서 어떤 부분이 바뀌어야 할 것인지에 대해서 설명을 하려고 합니다. 그리고 그러기 위해서 우리는 sds 라는 Redis에서 사용하는 string 구조체를 알 필요가 있습니다. 사실 sds 는 그냥 char * 입니다. 실제로 정의는 다음과 같이 sds.h 에 존재합니다.
typedef char *sds;
그리고 이를 관리하기 위해서 sdshdr 이라는 구조체를 사용하는 데 다음과 같습니다. len, free, buf 세 개의 변수를 가지고, len 현재 sds의 길이 free는 sds의 남은 용량, buf는 실제 버퍼를 가리키는 pointer 입니다. 즉 최초에 sdshdr을 하나 할당하고, 다시 거기에 buf를 할당해서 buf만 돌려주는게 sds의 핵심입니다. (잡담하나, 이런 구조를 만드시면 memory alignment에 신경을 써야 합니다. 예전에 이런 형태에 앞에 len을 2 bytes로 잡아서 처리한 적이 있는데, 일반 윈도우 장비에서는 문제가 없다가 ARM인지 하드디스크 드라이버가 특이한 곳에 갔더니, 데이터가 전부 0으로 들어오는 버그가 ㅋㅋ, 그냥 이렇게 4byte 단위로 alignment 되는 크기를 잡으시면 됩니다.)
그래서 이 sds 관련 함수들은 이 sdshdr 을 적절히 핸들링하게 됩니다. 예를 들어 sds의 길이를 알고 싶다면 strlen을 써도 되지만, 다음과 같이 sdslen 함수를 이용하면 훨씬 빠르게 됩니다. 이미 len을 가지고 있어서 그렇습니다.
static inline size_t sdslen(const sds s) {
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
return sh->len;
}
그럼 이게 왜 문제가 되는가하면? 32bit에서는 메모리 한계가 2G 이므로, 더 이상의 메모리 할당이 안됩니다. 즉 기존의 char *형태로 사용하는 sds 는 2G 이상을 처리하지 못한다는 결론이 나옵니다.(32bit 에서만), 즉 아이템의 크기 제한을 없애기 위해서는 간단하게 64bit 만 사용하게 하든지, 아니면 내부적으로 사용하는 이 sds 형태를 완전히 새롭게 뜯어고쳐야 합니다. redis 내부적으로 sds를 상당히 많이 사용하므로, 전체적인 구조 조정이 될것 같습니다. 그럼 sds 에 대한 설명을 마칩니다.
Posted on February 1, 2013, in Cloud, redis. Bookmark the permalink. 2 Comments.

글이 안올라가서;; 다시 글을 올립니다. 글 재미있게 읽었습니다. 몇가지 질문이 있습니다.
첫번째는 512MB밖에 쓸수없다고 하신 이유에 대해서는 안나온 것 같은데 맞나요? (그 이유를 추측컨데 32bit 시스템의 물리적 제한 때문에 512MB일 듯 합니다.) 두번째 질문은 sds가 binary버퍼라면 strlen을 못쓰지 않나요?? strlen은 Null문자까지의 길이까지만 측정할 수 있다고 알고 있습니다.
512MB밖에 쓰지 못하는 이유는 http://charsyam.wordpress.com/2013/01/31/%EC%9E%85-%EA%B0%9C%EB%B0%9C-redis-%EC%9D%98-%EC%95%84%EC%9D%B4%ED%85%9C%EC%9D%98-%ED%81%AC%EA%B8%B0-%EC%A0%9C%ED%95%9C%EC%9D%80-512mb%EC%9E%85%EB%8B%88%EB%8B%A4/ 이 글을 보시면 될 듯합니다. 32bit 는 메모리가 2G까지 할당이 되는데, Redis 자체적으로 512MB 이상은 패킷 처리단에서 에러로 처리하기 때문입니다. 그리고 binary 라면 strlen은 말씀하셨듯이 못씁니다. char *도 이건 마찬가지지요. 그러나 sdslen의 경우는 실제 메모리를 사용한 만큼 len값이 설정이 되므로, 이런 이슈는 없습니다.