Рубрики
Uncategorized

Прочитайте исходный код с помощью Dabin – Redis 6 – Объекты и типы данных (2)

Автор оригинала: David Wong.

Продолжайте с нашими объектами и типами данных.

В предыдущем разделе мы узнали о строках и списках, за которыми следуют хэши, коллекции и упорядоченные коллекции.

1 Хэш-объект

Необязательными кодами для объектов Hashi являются ziplist и hashtable соответственно.

1.1 Объект Hashi, закодированный ziplist

Объект Hashi, закодированный в ziplist, сжимается с использованием списка в качестве базовой реализации. Всякий раз, когда к хэш-объекту добавляется новая пара ключ-значение, программа сначала сохраняет ее. ключ Сжатые узлы списка перемещаются в конец таблицы, а затем сохраняются значение Узел сжатого списка перемещается в конец таблицы. Так:

  • Два узла, сохраняющие пару ключ-значение, всегда находятся близко друг к другу. Узел, сохраняющий ключ, находится спереди, а узел, сохраняющий значение, – сзади.
  • Пара ключ-значение, добавленная в хэш-объект, сначала копируется как направление заголовка сжатого списка, а затем добавленная пара ключ-значение помещается в хвостовом направлении сжатого списка.

Выполните следующую команду SET, и сервер создаст объект списка в качестве значения ключа профиля, как показано на рисунке 9:

127.0.0.1:6379> HSET profile name "Tom"
(integer) 1
127.0.0.1:6379> HSET profile age "25"
(integer) 1
127.0.0.1:6379> HSET profile career "Programer"
(integer) 1
127.0.0.1:6379> OBJECT ENCODING profile
"ziplist"

Сжатый список, используемый объектом, показан на рисунке 10.

1.2 Закодированная хэш-таблица

Объект Hashi, закодированный в хэш-таблице, реализован со словарем в качестве нижнего слоя. Каждая пара ключ-значение в хэш-объекте сохраняется с помощью пары ключ-значение словаря:

  • Каждый ключ в словаре представляет собой строковый объект, в котором хранятся ключи пар ключ-значение.
  • Каждое значение в словаре представляет собой строковый объект, в котором хранится значение пары ключ-значение.

Если предыдущий ключ профиля использует хэш-объект, закодированный в хэш-таблице, то хэш-объект должен быть показан на рисунке 11.

1.3 преобразование кода

Когда объект Hashi соответствует следующим двум условиям, будет использоваться код ziplist:

  1. Для всех пар ключ-значение, сохраненных хэш-объектами, длина строки ключей и значений составляет менее 64 байт.
  2. Количество пар ключей, сохраненных хэш – объектами, составляет менее 512.

Критические значения в приведенных выше условиях соответствуют конфигурациям в файле redis .conf: хэш-максимальное значение-ziplist-значение и хэш-макс-ziplist-записи

В версии 3.2 при добавлении значения хэш-ключа всегда создается хэш-объект, закодированный в ziplist, а затем выполняется проверка преобразования. Существует две ситуации, когда происходит преобразование кодирования:

  1. При обновлении или добавлении пар значений ключей, если Количество байтов значений больше hash-max-ziplist-значение Он изменится с кодировки ziplist на кодировку хэш-таблицы.
  2. При добавлении новых пар ключ-значение, если логарифм значения ключа больше, чем hash-max-ziplist-записи Он будет преобразован из кодировки ziplist в кодировку хэш-таблицы.

Следует отметить, что ни одно из вышеперечисленных преобразований не произойдет из хэш-таблицы в ziplist, даже если они соответствуют требованиям.

Для функций преобразования кодировки хэша вы можете обратиться к t_hash.c/преобразование типа хэша, которое выглядит следующим образом:

O is the original object, and enc is the target encoding.
void hashTypeConvert(robj *o, int enc) {
    If (o->encoding = = OBJ_ENCODING_ZIPLIST) {// the original code is OBJ_ENCODING_ZIPLIST.
        hashTypeConvertZiplist(o, enc);
    } else if (o->encoding == OBJ_ENCODING_HT) {
        serverPanic("Not implemented");
    } else {
        serverPanic("Unknown hash encoding");
    }
}

2 Объекта Коллекции

Необязательная кодировка объекта коллекции-intset и хэш-таблица.

2.1 объекты кодированной коллекции intset

Объекты коллекции с кодировкой интенсивности используют целочисленные наборы в качестве базовых реализаций, и все элементы, содержащиеся в объекте коллекции, хранятся в целочисленном наборе.

Чтобы выполнить следующую команду SADD, мы создадим объект коллекции с кодировкой intset, показанный на рисунке 12:

127.0.0.1:6379> SADD numbers 1 3 5
(integer) 3
127.0.0.1:6379> OBJECT ENCODING numbers
"intset"

2.2 объекты кодированной коллекции с хэш-таблицей

Объект коллекции, закодированный в хэш-таблице, реализован со словарем в качестве нижнего слоя. Каждый ключ в словаре является строковым объектом, и каждый строковый объект содержит элемент коллекции, в то время как значение словаря имеет значение NULL.

Чтобы выполнить следующую команду SADD, мы создадим объект кодированной коллекции с хэш-таблицей, показанный на рисунке 13:

127.0.0.1:6379> SADD fruits "apple" "banana" "cherry"
(integer) 3
127.0.0.1:6379> OBJECT ENCODING fruits
"hashtable"

2.3 преобразование кода

Когда объект набора удовлетворяет одновременно двум следующим условиям, объект использует кодировку intset:

  1. Все элементы, сохраненные объектом коллекции, могут быть представлены в виде целых значений с помощью длинного двойника.
  2. Объекты коллекции содержат не более 512 элементов.

Критические значения в приведенных выше условиях соответствуют конфигурациям в файле redis.conf: set-max-intset-записи

Для объекта коллекции при добавлении первой пары ключ-значение проверяется значение пары ключ-значение. Если задано целочисленное значение, создается объект коллекции с кодировкой intset. В противном случае создается объект коллекции, закодированный в хэш-таблице.

Существует две ситуации, когда происходит преобразование кодирования:

  1. При обновлении или добавлении пар значений ключей, если значение
  2. Он не может быть представлен длинным двойным и будет преобразован из кодировки intset в кодировку хэш-таблицы. При добавлении новой пары ключ-значение, если пара ключ-значение находится в наборе Значение ключа логарифмическое число больше set-max-intset-записи

Аналогично, преобразование из хэш-таблицы в набор intset не выполняется, даже если оно соответствует критериям.

Для функций преобразования хэш-кодирования вы можете обратиться к преобразованию типа t_set.c/set. Исходный код выглядит следующим образом:

Setobj is the original object, and enc is the target encoding.
hvoid setTypeConvert(robj *setobj, int enc) {
    setTypeIterator *si;
    serverAssertWithInfo(NULL,setobj,setobj->type == OBJ_SET && setobj->encoding == OBJ_ENCODING_INTSET);
    If (enc == OBJ_ENCODING_HT) {// can only be converted to OBJ_ENCODING_HT encoding
        int64_t intele;
        dict *d = dictCreate(&setDictType,NULL);
        robj *element;
        /* Presize the dict to avoid rehashing */
        dictExpand(d,intsetLen(setobj->ptr));
        /* To add the elements we extract integers and create redis objects */
        si = setTypeInitIterator(setobj);
        while (setTypeNext(si,&element,&intele) != -1) {
            element = createStringObjectFromLongLong(intele);
            serverAssertWithInfo(NULL,element,
                                dictAdd(d,element,NULL) == DICT_OK);
        }
        setTypeReleaseIterator(si);
        setobj->encoding = OBJ_ENCODING_HT;
        zfree(setobj->ptr);
        setobj->ptr = d;
    } else {
        serverPanic("Unsupported set conversion");
    }
}

3 Упорядоченных Набора Объектов

Необязательная кодировка объектов упорядоченного набора-это список ziplist и список пропусков.

3.1 объекты упорядоченного набора, закодированные в ziplist

Объекты коллекции в кодировке Intset используют сжатый список в качестве базовой реализации. Каждый элемент коллекции сохраняется с помощью двух компактных узлов списка, расположенных рядом друг с другом. Первый узел содержит элемент элемента, а второй элемент содержит оценку элемента.

Элементы набора в сжатом списке отсортированы по баллам от малого до большого. Элементы с меньшими баллами размещаются в направлении заголовка, в то время как элементы с большими баллами размещаются в направлении ближе к концу таблицы.

Чтобы выполнить следующую команду SADD, мы создадим объект коллекции с кодировкой ziplist, показанный на рисунке 14:

127.0.0.1:6379> ZADD price 8.5 apple 5.0 banana 6.0 cherry
(integer) 3
127.0.0.1:6379> OBJECT ENCODING price
"ziplist"

Базовая структура ziplist показана на рисунке 15.

3.2 объекты кодированной коллекции скиплиста

Объекты коллекции, закодированные в скиплистах, реализуются с использованием набора в качестве базовой реализации. Структура набора содержит как словарь, так и таблицу переходов. Структура исходного кода выглядит следующим образом:

# server.h
typedef struct zset {
    dict *dict;
    zskiplist *zsl;
} zset;

Таблица переходов ZSL в структуре Zset сохраняет все элементы набора от малого до большого по баллам, и каждый узел таблицы переходов сохраняет элемент набора.

Атрибут объекта узла таблицы переходов сохраняет элементы элемента, в то время как атрибут оценки узла таблицы переходов сохраняет ветви элемента. * * Программа использует эту таблицу переходов для выполнения операций с диапазонами для упорядоченных наборов. Например, такие команды, как ZRANK и ZRANGE, реализованы на основе API таблицы переходов.

Кроме того, словарь dict в структуре Zset создает сопоставление элементов с оценками для упорядоченных наборов. Каждая пара ключ-значение в словаре содержит элемент набора: ключ в словаре содержит элементы элемента, в то время как значение в словаре содержит оценку элемента. С помощью этого словаря программа использует сложность O (1), чтобы найти оценку данного участника.

Члены каждого элемента в упорядоченном наборе являются строковым объектом, а оценка каждого элемента представляет собой число с плавающей запятой двойного типа. Это стоит упомянуть что, хотя структура Zset использует как таблицы переходов, так и словари для хранения элементов упорядоченных наборов, обе структуры данных совместно используют элементы и значения одних и тех же элементов через указатели, поэтому повторяющиеся элементы и значения не генерируются и дополнительная память не тратится впустую.

Если предыдущий ключ цены создан вместо объекта упорядоченной коллекции с кодировкой ziplist вместо кодировки skiplist, то объект упорядоченной коллекции будет показан на рисунке 16, а результат Zset, используемый объектом, будет показан на рисунке 17.

На рисунке 17 элементы и оценки каждого элемента показаны несколько раз для удобства представления. Фактически, они являются членами и ценностями общих элементов.

3.3 Преобразование Кодирования

Когда упорядоченные агрегированные объекты одновременно удовлетворяют следующим двум условиям, объект кодируется с помощью ziplist:

  1. Упорядоченные объекты коллекции содержат не более 128 элементов.
  2. Длина всех элементов, хранящихся в упорядоченном наборе, составляет менее 64 байт.

Критические значения в приведенных выше условиях соответствуют конфигурациям в файле redis.conf: zset-max-ziplist-записи и zset-max-ziplist-значение

Для объекта коллекции при добавлении нового значения ключа проверяются значения элементов коллекции и пар значений ключей. Если условия выполнены, создается объект коллекции с кодировкой ziplist, в противном случае создается объект коллекции с кодировкой skiplist. Соответствующий исходный код выглядит следующим образом:

# t_zset.c/zaddGenericCommand
...
zobj = lookupKeyWrite(c->db,key);
if (zobj == NULL) {
    if (xx) goto reply_to_client; /* No key + XX option: nothing to do. */
    if (server.zset_max_ziplist_entries == 0 ||
        server.zset_max_ziplist_value < sdslen(c->argv[scoreidx+1]->ptr))
    {
        # The number of object elements is 0, or
        zobj = createZsetObject();
    } else {
        zobj = createZsetZiplistObject();
    }
    dbAdd(c->db,key,zobj);
} else {
    if (zobj->type != OBJ_ZSET) {
        addReply(c,shared.wrongtypeerr);
        goto cleanup;
    }
}

резюме

  1. Хэш-объектами являются ziplist и хэш-таблица
  2. Код. Объекты коллекции имеют вставку и хэш-таблица
  3. Код. Упорядоченные объекты набора имеют ziplist и шкипер

Оригинал: “https://developpaper.com/read-the-source-code-with-dabin-redis-6-objects-and-data-types-2/”