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-entries 512
    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

data structure ziplist hashes
    그림 1-1   Data structure Zip list of Hashes

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 functions ziplist of hashes
    그림 1-2   HSET functions Zip list of Hashes

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 functions ziplist of hashes
    그림 1-3   HGET functions Zip list of Hashes

이제 필드 값을 가져오는 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 >>
Email 답글이 올라오면 이메일로 알려드리겠습니다.


레디스 엔터프라이즈 서버로 Active-Active 이중화를 구성해보세요.

SQL SELECT로 레디스 key, value를 조회해보세요.

궁금하신 사항이 있으면 여기로 redisgate@gmail.com 메일 주세요.
 
close
IP를 기반으로 보여집니다.