[Большой класс] Принцип базовой структуры данных Hash, Set, Zset в Redis

Redis

Привет, одноклассники, на прошлом уроке мы подробно представили базовую структуру хранения данных строк и списков в Redis, а сегодня мы сосредоточимся на принципах структуры hash, set и zset в Redis.

Redis — хеш-объект (хэш)

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

  • Длина строк ключа и значения, хранящихся в хеш-объекте, меньше 64 байт.
  • Количество пар ключ-значение, хранящихся в хеш-объекте, меньше 512. Структура хранилища ziplist выглядит следующим образом

Как видно на рисунке выше, когда количество данных относительно невелико, мы будем рассматривать все ключи и значения как один элемент и хранить их в ziplist для формирования заказа.

Структура хранилища хеш-таблиц

В чем разница между заданным значением ключа и хешем строк

  1. Срок действия, хэш не имеет срока действия
  2. Существует проблема с добавлением постоянного значения set.Один из атрибутов в dict — dictht ht[2], который в основном используется для расширения.Если ключ постоянно добавляется, необходимо расширить общую память Redis, а расширение должен быть основан на исходной памяти.Двойное потребление памяти

Объект Redis-коллекции (набор)

Set — это неупорядоченный, автоматически дедуплицированный тип данных коллекции.Нижний уровень Set хранится в двух структурах данных: одна — хэш-таблица, а другая — вставка.

Ключ хеш-таблицы — это значение элемента в наборе, а значение равно null.

Вставку можно понимать как массив, и использование структуры данных вставки должно соответствовать следующим двум условиям:

  • Количество элементов не менее значения по умолчанию 512
  set-max-inset-entries 512
  • Элементы могут быть представлены как целые числа

Базовая структура intset

typedef struct intset {
    
    // 编码类型
    uint32_t encoding;

    // 集合包含的元素数量
    uint32_t length;

    // 保存元素的数组
    int8_t contents[];

} intset;

Метод запроса обычно использует двухточечный метод поиска, фактическая сложность запроса также является журналом (N)

Redis — отсортированный набор объектов (zset)

zset упорядочен (ограниченный порядок оценок, и элементы находятся в лексикографическом порядке, если оценки одинаковы), тип данных набора с автоматической дедупликацией, и его основная реализация представляет собой словарь (dict) + список пропуска (skiplist), когда данные относительно мал, используйте хранилище структуры кодировки ziplist.

Следующие два условия выполняются одновременно для использования хранилища ziplist:

  • Количество элементов, хранящихся в отсортированном наборе, меньше значения по умолчанию, равного 128.
  • Длина всех элементов, хранящихся в отсортированном наборе, меньше значения по умолчанию, равного 64 байтам.

метод хранения ziplist

Когда ziplist используется в качестве базовой структуры хранения zset, каждый элемент набора хранится с использованием двух сжатых узлов списка рядом друг с другом, первый узел содержит элементы элемента, а второй элемент содержит оценку элемента.

Способ хранения словарь (dict) + скиплист (skiplist)

Базовая структура хранения zset включает в себя ziplist или skiplist. ziplist используется, когда одновременно выполняются следующие два условия, а skiplist используется в других случаях. Эти два условия следующие:

Количество элементов, хранящихся в отсортированном наборе, меньше 128. Длина всех элементов, содержащихся в отсортированном наборе, меньше 64 байт.

пропустить структуру данных таблицы

Во-первых, давайте разберемся, что такое таблица пропуска.Это видно из того же вида, что мы запрашиваем от высшего уровня к более низкому уровню путем градации, и эффективность повышается, а его временная сложность logn (аналогично бинарному поиску)

Окончательная структура хранения dict+skiplist выглядит следующим образом.

Основываясь на приведенном выше рисунке, давайте посмотрим на структуру данных нескольких ключевых объектов в skiplist, которая удобна для понимания всем.

zset

  /*
 * 有序集合
 */
typedef struct zset {

    // 字典,键为成员,值为分值
    // 用于支持 O(1) 复杂度的按成员取分值操作
    dict *dict;

    // 跳跃表,按分值排序成员
    // 用于支持平均复杂度为 O(log N) 的按分值定位成员操作
    // 以及范围操作
    zskiplist *zsl;

} zset;

Видно, что одна из них представляет собой структуру dict, основной ключ — ее элемент set, а значение — соответствующую оценку, а zkiplist используется как таблица переходов, отсортированная по оценке, что удобно для поиска членов.

zskiplist

  /*
 * 跳跃表
 */
typedef struct zskiplist {

    // 表头节点和表尾节点
    struct zskiplistNode *header, *tail;

    // 表中节点的数量
    unsigned long length;

    // 表中层数最大的节点的层数
    int level;

} zskiplist;

zskiplistNode

  /*
 * 跳跃表节点
 */
typedef struct zskiplistNode {

    // 成员对象
    robj *obj;

    // 分值
    double score;

    // 后退指针
    struct zskiplistNode *backward;

    // 层
    struct zskiplistLevel {

        // 前进指针
        struct zskiplistNode *forward;

        // 跨度
        unsigned int span;

    } level[];

} zskiplistNode;

Указатель robj в zskiplistNode указывает на определенный элемент.Обратите внимание, что этот указатель и указатель ключа в dict указывают на один и тот же элемент, а обратный указатель ноги удобен для возврата.

Суммировать

В этом разделе в основном объясняется основной принцип Hash, SET, ZSET в REDIS, где в конце Hash используются два типа: Ziplist и Hashtable, а также два hashtable и INSET соответственно, где INSET также можно понимать как массивы, ZSET Нижний уровень – Ziplist и Dict + Skiplist, и мы видим превосходный дизайн с точки зрения экономии памяти и повышения эффективности запросов. Они могут быть использованы в качестве ценного опыта в нашем будущем проектировании и разработке. Мы перейдем к следующему разделу. Возможности REDIS в безопасность данных и защита производительности, выходите из класса!