ds_ziplist_hashes
Redis ZIP List of HASHES
레디스 내부구조 교육 |
레디스 정기점검/기술지원 Redis Technical Support |
레디스 엔터프라이즈 서버 Redis Enterprise Server |
---|
ZIP LIST 메모리 절약 데이터 구조
Parameters
Hashes는 내부적으로 두 가지 데이터 타입을 사용한다.
필드 개수가 적거나 또는 값의 길이가 작을 때는 짚 리스트(Zip list)를 사용하고,
필드 개수가 많거나 또는 값의 길이가 클 때는 해시 테이블(Hash table)을 사용한다.
두 개중 하나의 조건만 만족해도 데이터 타입을 변경한다.
정확하게 설명하면 redis.conf에 ADVANCED CONFIG 섹션이 있는데,
여기에 Hashes의 내부 데이터 타입을 결정할 두 개의 파라미터가 있다.
hash-max-ziplist-value 64
필드 개수는 hash-max-ziplist-entries로 정한다.
필드 수가 512개 이하면 짚 리스트에 저장되고 513개부터는 해시 테이블에 저장된다.
값(스트링)의 크기는 hash-max-ziplist-value로 정한다.
스크링의 바이트수가 64바이트 이하면 짚 리스트에 저장되고,
65바이트 부터는 해시 테이블에 저장된다.
물론 이 파라미터의 값은 파일에 있으므로 바꿀 수 있다.
해시(Hashes)의 주 데이터 타입은 해시 테이블(Hash table)이다.
해시 테이블은 메모리를 많이 사용하기 때문에,
성능이 크게 떨어지지 않는 범위 내에서 메모리 사용이 적은 짚 리스트를 사용한다.
그 적정 값이 필드 수는 512개, 값 바이트 수는 64바이트로 본 것이다.
메모리가 부족하다고 생각되면 이 파라미터를 적절히 조절해서 메모리를 적게 사용하게 할 수 있다.
Data Structures
Zip list
redisServer와 redisClient는 동일한 redis Database를 가리킨다.
위 그림에서 A 부분이 표시하는 redis DB는 키를 관리하는 Hash table이다.
dictEntry의 value 부분은 redisObject를 가리키고, redidObject의 ptr은 Zip list를 가리킨다.
Hash는 field와 value가 있으므로 Zip list의 첫 번째 entry는 field name이 들어가고,
두 번째 entry에 value가 들어간다.
이런 방식으로 field와 value가 반복해서 저장된다.
Functions
HSET Command
hset command는 주요한 세 개의 function이 수행된다.
- key를 찾고, 만약 키가 없으면 필요한 object를 생성하는 hashTypeLookupWriteOrCreate()
- 값의 길이를 검사해서 설정된 것보다 크면 Zip list를 Hash table로 변환하는 hashTypeTryConversion()
- 필드 수를 검사해서 설정된 값보다 크면 Zip list를 Hash table로 변환하고, 아니면, Zip list에 필드와 값을 저장하는 hashTypeSet()
하나씩 자세히 살펴보겠습니다.
- hashTypeLookupWriteOrCreate()
- lookupKeyWrite()는 lookupKey()을 호출해서 이미 키가 있는지 검사한다. 이미 키가 있으면 robj value를 리턴한다. 이미 키가 있는데 타입이 해시(HASH)가 아니면 에러를 리턴한다.
- 키가 없으면 createHashObject()를 호출해서 ziplist와 robj value를 생성한다.
- dbAdd()를 호출해서 dictEntry를 생성하고 dictEntry->val에 robj value를 저장하고, robj->ptr은 ziplist를 저장한다. 그림 1-1의 dictEntry, robj value, Zip list와 비교해서 보기 바랍니다.
- 새로운 키일 때 redis.conf의 hash-max-ziplist-entries, value 값과 관계없이 일단 짚 리스트를 생성한다. 다음에 해당 파라이터 값을 검사해서 조건에 맞으면 해시 테이블로 변환한다.
- hashTypeTryConversion()
- server.hash_max_ziplist_value(값의 길이)를 검사해서 이 값보다 크면 hashTypeConvert(HT)를 호출해서 짚 리스트를 해시 테이블로 변환한다. 필드 개수에 대한 검사는 다음에 한다.
- hashTypeSet()
- server.hash_max_ziplist_entries(필드 개수) 검사해서 이 값보다 크면 hashTypeConvert(HT)를 호출해서 짚 리스트를 해시 테이블로 변환한다.
- 이제부터는 짚 리스트 일 때 저장 흐름을 설명한다.
- ziplistIndex()로 짚 리스트의 시작 포인트를 가져온다.
- ziplistFind(field)로 해당 필드가 있는지 검사한다.
- 해당 필드가 이미 있으면, 다음 엔트리가 값이므로 ziplistNext()를 호출해서 다음 엔트리로 이동한다. ziplistDelete(value)로 기존 값을 지우고, ziplistInsert(value)로 새 값을 저장한다.
- 해당 필드가 없으면 새로 입력해야 하므로 ziplistPush(field)로 필드 이름을 저장하고, ziplistPush(value)로 값을 저장한다.
HGET Command
이제 필드 값을 가져오는 HGET command로 짚 리스트에서 값을 가져오는 것을 설명한다.
- lookupKeyReadOrReply()를 호출해서 키가 있는지 확인한다. 키 확인은 lookupKey()를 거쳐 dictFind()로 키를 찾고, dictGetVal()로 robj value를 구한다.
- addHashFieldToReply() -> hashTypeGetFromZiplist()를 거쳐서 ziplistFind(field)로 필드를 찾고, ziplistNext()로 다음 엔트리로 이동한 다음, ziplistGet(value)로 값을 가져온다.
<< SKIP List of ZSETS | ZIP List of HASHES | HASH Table of HASHES >> |
---|