предисловие
- Почему производительность Redis такая хорошая? Чем он отличается от другого промежуточного ПО для кэширования?
- Какие структуры данных использует базовый Redis для поддержки такой эффективной производительности?
- Почему базовые расширенные типы данных реализованы с использованием как минимум двух структур данных? Кто они такие?
- Можно ли использовать Redis с максимальной пользой, если использовать его разумно?
После изучения предыдущих глав о структурах данных и объектах в «Проектировании и реализации Redis» можно ответить на поставленные выше вопросы. Вы также можете понять, что автор Redis кропотливо разработал так много богатых структур данных, чтобы оптимизировать память. Изучив это содержимое, в процессе использования Redis он также будет использоваться разумно, чтобы адаптироваться к его внутренним характеристикам. Конечно, новая версия Redis поддерживает больше и более богатые функции.Книга основана на версии Redis3 и не охватывает это содержание.
Книга «Проектирование и внедрение Redis» очень проста для понимания, автором является г-н Хуан Цзяньхун, родившийся в 1990-х годах. Кроме того, он также является переводчиком «redis Combat».
Другой может ссылаться на«Проектирование и реализация Redis» 2 — Реализация базы данных
Обзор
Функции
- Разработка языка C, отличная производительность, чистая работа с памятью, может обрабатывать более 10 Вт чтения и записи в секунду (QPS)
- Разнообразие структур данных, единый максимальный лимит может составлять до 1 ГБ (memcached поддерживает только строки, максимум 1 МБ)
- Ограниченный физической памятью, он не может читать и записывать массивные данные. Подходит для высокопроизводительных операций и операций с небольшими объемами данных
- Сопровождение сделки, постоянство
- Однопоточная модель (memcached многопоточная)
Поддерживаемые типы данных
- Sring
- List
- Set
- SortedSet
- hash
- Bitmap
- Hyperloglogs
- Geo
- pub/sub
Почему Redis такой быстрый
- Чистая работа с памятью, без диска io
- Однопоточная обработка запросов, отсутствие накладных расходов на переключение потоков, условий гонки и проблем с блокировкой
- Модель мультиплексирования epoll, неблокирующий ввод-вывод (мультиплексирование: несколько сетевых подключений; мультиплексирование: мультиплексирование одного и того же потока) Технология мультиплексирования позволяет одному потоку эффективно обрабатывать несколько запросов на подключение.
- Структура данных проста, и обработка данных также проста. Также сделал собственную оптимизацию структуры данных
Почему Redis однопоточный?
- Один поток уже очень быстр, что снижает нагрузку на сеть, вызванную многопоточностью, операцией блокировки
- Последующие версии 4.0 учитывают многопоточность.
- Single thread означает, что при обработке сетевых запросов работает только один поток, а не только один поток redis-сервера. При сохранении он выполняется путем разветвления дочернего потока.
- Недостаток: Команды, занимающие много времени, приведут к снижению параллелизма, например ключей *
Стратегия утилизации Redis
- volatile-lru: выбрать наименее использованные данные из набора данных с истекшим сроком действия server.db[i].expires
- volatile-ttl: выберите данные с истекшим сроком действия из набора данных с истекшим сроком действия server.db[i].expires для устранения
- volatile-random: выберите произвольные данные для удаления в server.db[i].expires
- allkeys-lru: выбрать данные из набора данных (server.db[i].dict), которые использовались реже всего.
- allkeys-random: Случайный выбор данных из набора данных (server.db[i].dict) для исключения
- no-enviction: запретить удаление данных
Будьте осторожны
- Один поток Redis не может обеспечить производительность многоядерного процессора, его можно улучшить, открыв несколько экземпляров Redis на одном компьютере.
- Redis реализует распределенные блокировки: сначала используйте setnx (установите, если он не существует), чтобы конкурировать за блокировки.После захвата, expire устанавливает время истечения срока действия, чтобы не забыть снять.
- Redis реализует подписку на сообщения «один ко многим»: структура данных sub/pub
- Redis реализует очередь сообщений с задержкой: когда метка времени zadd используется в качестве оценки, операция запроса выполняется в соответствии с меткой времени + временем задержки.
Введение основных версий
Новые функции в версии redis5:
- zpopmax zpopmin и варианты блокировки: возвращает максимальное и минимальное количество данных в коллекции для заданной оценки.
Новые функции в версии reids4:
- Функция модуля, предоставляющая способ, аналогичный подключаемому модулю, самостоятельно разработать модуль .so и установить его. Сам автор предоставляет модуль нейронной сети. Дополнительные модули можно найти на redis-modules-hub. Функциональность модуля позволяет пользователям использовать Redis в качестве инфраструктуры и создавать дополнительные функции поверх нее, что открывает бесчисленные новые возможности для Redis.
- PSYNC: устранены некоторые несоответствия в репликации старых версий Redis.
- Оптимизация стратегии очистки кэша Добавлено последнее часто используемое Оптимизация существующих стратегий
- неблокирующий DEL FLUSHDB FLUSHALL Решена проблема блокировки при выполнении этих команд до Flushdb async, flushall async, unlink (заменяет del)
- Добавлен swapdb: база данных подкачки
- Формат сохраняемости гибридного RDB-AOF
- Добавить команду использования памяти: MEMORY
структура данных
- Каждая пара ключ-значение в Redis состоит из объектов
- Ключ всегда является строковым объектом,
- Значение может быть одним из следующих объектов:
- строковый объект
- объект списка
- хэш-объект
- объект коллекции
- упорядоченное сочетание объектов
Простая динамическая строка SDS
структура данных
struct sdshdr {
uint8_t len; /* used,使用的字节数 */
uint8_t alloc; /* excluding the header and null terminator,预分配总字节数,不包括结束符\0的长度 */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[]; /*c风格的字符,包括结束符\0*/
};
- Находится в файле sds.h
- SDS следует соглашению о том, что строки C заканчиваются на \0 и хранятся в buf (в отличие от базовой реализации nginx, которая не сохраняет последний \0 в реализации)
- Но не считайте длину последнего символа в len
- Преимущество сохранения buf в стиле c заключается в том, что вы можете повторно использовать некоторые функции библиотеки c.
Стратегии распределения и освобождения
предварительное выделение пространства
- Используется для оптимизации операций роста строки SDS, чтобы уменьшить количество перераспределений памяти, необходимых для выполнения последовательных операций роста.
- При расширении пространства SDS сначала проверьте, достаточно ли неиспользуемого пространства.Если его достаточно, используйте его напрямую.Если нет, не только выделите достаточно места, но и предварительно выделите некоторое пространство.
- Стратегия предварительного распределения:
- Измененная длина SDS (значение len)
- Измененная длина SDS (значение len) >= 1 МБ, предварительно выделено 1 МБ места
Выпуск инертного пространства
- Используется для оптимизации операций сокращения символов SDS.
- При сокращении пространства SDS не сразу выполняет перераспределение памяти для освобождения места, а записывает количество свободных байт
- SDS предоставляет соответствующие API-интерфейсы, чтобы действительно освободить место, когда это необходимо.
Преимущества перед струнами C
- Временная сложность получения длины строки снижена с O(N) до O(1)
- Избегайте переполнения буфера
- Уменьшите количество перераспределений памяти при изменении строк. Выделение памяти включает сложные алгоритмы и может потребовать системных вызовов, которые отнимают много времени.
- Двоичная безопасность: терминатор языка c ограничивает его сохранением только текстовых данных, а не двоичных данных, таких как изображения и аудио.
связанный список
структура данных
Находится в файле adlist.h
typedef struct listNode {
struct listNode *prev; // 前置节点
struct listNode *next; // 后置节点
void *value;//节点值
} listNode;
typedef struct list {
listNode *head; // 表头节点
listNode *tail; // 表尾节点
void *(*dup)(void *ptr); // 节点值复制函数
void (*free)(void *ptr); // 节点值释放函数
int (*match)(void *ptr, void *key); // 节点值对比函数
unsigned long len; // 节点数量
} list;
Функции
- Двусторонняя очередь, вы можете получить передний узел и задний узел узла, сложность O (1)
- Ациклический
- Сложность получения верхнего и нижнего колонтитула O (1)
- С длиной сложность получения длины связанного списка составляет O (1)
- Полиморфизм: используйте void* для сохранения значений узлов, которые могут сохранять значения разных типов.
Словарь
структура данных
находится в файле dict.h
хеш-таблица
// 哈希表
typedef struct dictht {
dictEntry **table; // 一个数组,数组中每个元素都是指向dictEntry结构的指针
unsigned long size; // table数组的大小
unsigned long sizemask; // 值总数size-1
unsigned long used; // 哈希表目前已有节点(键值对)的数量
} dictht;
хеш-узел
// 每个dictEntry都保存着一个键值对,表示哈希表节点
typedef struct dictEntry {
void *key; // 键值对的键
// 键值对的值,可以是指针,整形,浮点型
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next; // 哈希表节点指针,用于解决键冲突问题
} dictEntry;
Тип словаря
Каждый тип словаря содержит набор функций для управления парами ключ-значение определенного типа.
typedef struct dictType {
// 计算哈希值的函数
uint64_t (*hashFunction)(const void *key);
// 复制键的函数
void *(*keyDup)(void *privdata, const void *key);
// 复制值的函数
void *(*valDup)(void *privdata, const void *obj);
// 对比键的函数
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
// 销毁键的函数
void (*keyDestructor)(void *privdata, void *key);
// 销毁值的函数
void (*valDestructor)(void *privdata, void *obj);
} dictType;
Словарь
// 字典
typedef struct dict {
dictType *type; // 不同键值对类型对应的操作函数
void *privdata; // 需要传递给对应函数的参数
dictht ht[2]; // ht[0]用于存放数据,ht[1]在进行rehash时使用
long rehashidx; /* rehashing not in progress if rehashidx == -1,目前rehash的进度*/
unsigned long iterators; /* number of iterators currently running */
} dict;
хеш-алгоритм
- Redis использует алгоритм MurmurHash2 для вычисления хеш-значения ключа.
- Хеш-значение объединяется с помощью ИЛИ с маской размера, чтобы получить хеш-индекс.
- Коллизия хэшей (два или более ключа назначаются одному и тому же индексу в массиве хэш-таблицы): метод цепной адресации разрешает коллизию
rehash
- Расширьте или уменьшите хеш-таблицу, чтобы коэффициент загрузки хэш-таблицы оставался в разумных пределах.
- Коэффициент загрузки = количество сохраненных (используемых) узлов / размер хеш-таблицы (размер)
Шаги перефразирования включают
- Выделить место для хеш-таблицы ht[1] словаря, размер которой зависит от выполняемой операции и количества пар ключ-значение, которое ht[0] содержит в данный момент.
- Операция расширения: размер ht[1] равен первой n степени числа 2, большей или равной ht[0].used, умноженной на 2.
- Операция сжатия: размер ht[1] равен первой n степени числа 2, больше или равной ht[0].used
- Перехешировать все пары ключ-значение, хранящиеся в ht[0], в ht[1]: пересчитать хеш-значение и значение индекса ключа.
- Когда все пары ключ-значение ht[0] будут перенесены в ht[1], освободите ht[0], установите для ht[1] значение ht[0] и создайте новый хеш ужасов как ht[1]
Условия автоматического расширения
- Сервер не выполняет команду BGSave или команду GBRewriteAOF, а коэффициент загрузки хеш-таблицы >= 1.
- Сервер выполняет команду BGSave или команду GBRewriteAOF, а коэффициент загрузки хэш-таблицы >= 5.
- Когда используется команда BGSave или GBRewriteAOF, серверу необходимо создать дочерний процесс текущего серверного процесса, который будет потреблять память.Улучшите коэффициент загрузки, чтобы избежать записи и экономии памяти.
условие автоматического сжатия
- Автоматически сжимать, когда коэффициент загрузки хэш-таблицы меньше 0,1.
прогрессивная перефразировка
- Переиндексация данных ht[0] в ht[1] не выполняется централизованно за один раз, а выполняется несколько раз постепенно (чтобы избежать проблем с производительностью, когда хеш-таблица слишком велика).
Подробные шаги прогрессивного перефразирования
- Выделить место для ht[1] для автоматического одновременного хранения двух хеш-таблиц.
- Rehashidx в словаре установлен в 0, что означает запуск выполнения rehash (значение по умолчанию -1)
- Во время повторного хэширования каждый раз, когда над словарем выполняется операция, все пары ключ-значение в индексе rehashidx хэш-таблицы ht[0] повторно хэшируются в ht[1]
- Когда все перефразирование завершено, rehashidx устанавливается равным -1.
будь осторожен
- Все операции перехеширования будут выполняться в двух хеш-таблицах
- Новые добавленные значения всегда помещаются в ht[1], чтобы гарантировать, что данные будут только уменьшаться, а не увеличиваться.
стол для прыжков
- Таблица переходов — это упорядоченная структура данных, которая обеспечивает быстрый доступ к узлам за счет поддержки нескольких указателей на другие узлы в каждом узле.
- Временная сложность: худшее O(N), среднее O(logN)
- В большинстве случаев эффективность сопоставима с эффективностью сбалансированного дерева, но его проще реализовать, чем сбалансированное дерево.
- Одна из базовых реализаций отсортированных наборов
структура данных
находится в файле server.h
// 跳跃表节点
typedef struct zskiplistNode {
sds ele; // 成员对象
double score; // 分值,从小到大排序
struct zskiplistNode *backward; // 后退指针,从表尾向表头遍历时使用
struct zskiplistLevel {
struct zskiplistNode *forward; // 前进指针
unsigned long span; // 跨度,记录两个节点之间的距离
} level[]; // 层,是一个数组
} zskiplistNode;
// 跳跃表相关信息
typedef struct zskiplist {
struct zskiplistNode *header, *tail; // 表头和表尾
unsigned long length; // 跳跃表长度(包含节点的数量)
int level; // 跳跃表内层数最大那个节点的层数(不包括表头节点层数)
} zskiplist;
- Размер массива уровней генерируется случайным образом каждый раз, когда создается новая таблица переходов, и находится в диапазоне от 1 до 32.
- Операция обхода использует только прямой указатель, диапазон используется для вычисления ранга, а сумма всех промежутков слоя, посещенных на этом пути, является рангом узла.
- Несколько узлов могут содержать одну и ту же ветвь, но каждый объект-член узла уникален.
коллекция целых чисел
- intset — одна из базовых реализаций ключей коллекции.
- Когда набор содержит только целочисленные элементы и их число невелико, целочисленный набор используется в качестве базовой реализации.
структура данных
Находится в файле intset.h
typedef struct intset {
uint32_t encoding; // 编码方式
uint32_t length; // 长度
int8_t contents[]; // 内容,数组内容类型取决于encoding属性,并不是int8_t。按照大小排序,没有重复
} intset;
Обновить
- Когда мы хотим добавить новый элемент в коллекцию целых чисел, а тип нового элемента длиннее, чем все существующие типы элементов коллекции целых чисел, перед добавлением новых данных необходимо обновить коллекцию.
- Процедура обновления состоит из трех шагов:
- В соответствии с типом, расширить размер, выделить место
- Преобразуйте базовые данные массива в новый тип и измените правильное местоположение.
- Новые элементы добавляются в базовый массив
- Добавление элементов может привести к обновлениям, поэтому добавление новых элементов имеет мировую сложность O (N)
- Даунгрейд не поддерживается, новый тип данных всегда будет поддерживаться после обновления
Преимущества обновления
- Повышение гибкости
- сохранить память
Сжатый список
- ziplist — одна из низкоуровневых реализаций ключей списка и хэш-ключей.
- Последовательная структура данных, разработанная Redis для экономии памяти.
- Когда ключ списка содержит только несколько элементов списка, и каждый элемент списка представляет собой либо небольшое целое число, либо короткую строку, используйте ziplist в качестве базовой реализации ключа списка.
- При переходе по сжатому списку возврат от эпитопа к заголовку
- ziplist не имеет специальной структуры для представления
Состав сжатого списка
Атрибуты | тип | длина | использовать |
---|---|---|---|
zlbytes | uint32_t | 4 байта | Количество байтов памяти, занимаемых всем сжатым списком |
zltail | uint32_t | 4 байта | Сколько байт занимает хвостовой узел от начального адреса сжатого списка, и хвостовой узел можно получить без обхода |
zllen | uint16_t | 2 байта | Количество узлов. Если оно меньше 65535, это фактическое значение. Когда оно превышает 65535, его необходимо пройти для расчета |
entryN | узел списка | неопределенный | Каждый узел включен |
zlend | uint8_t | 1 байт | Специальное значение 0xFF, конечный маркер |
Состав узлов сжатого списка
- previos_entry_length: длина предыдущего узла, используемого для возврата от хвоста к голове
- Если длина предыдущего узла меньше 254 байт, длина preivos_entry_length представлена 1 байтом.
- Если длина предыдущего узла меньше 254 байт, длина preivos_entry_length представлена 5 байтами, первый байт равен 0xFE (254), а следующие четыре байта представляют фактическую длину.
- Кодировка: Запишите тип и длину содержимого.Кодировка разделена на две части: старшие два бита и оставшиеся цифры.Значения старших двух цифр следующие:
Два самых высоких значения Представляет тип данных байты кодирования оставшиеся биты максимальная дальность 00 массив символов байт 6bit 63 бит 01 массив символов два байта 14bit 2^14-1 10 массив символов пять байтов 4*8, оставшиеся 6 бит первого байта остаются пустыми 2^32-1 бит 11 целое число 1 байт 000000 целое число типа int16_t 11 целое число 1 байт 010000 целое число типа int32_t 11 целое число 1 байт 100000 целое число типа int64_t 11 целое число 1 байт 110000 24-битное целое число со знаком 11 целое число 1 байт 111110 8-битное целое число со знаком 11 целое число 1 байт xxxxxx Без содержимого xxxx сам по себе представляет целое число от 0 до 12. - содержимое: содержит значение узла
обновление цепочки
- Несколько последовательных узлов размером около 254 узлов вызывают непрерывное выделение памяти из-за расширения. Однако в случае со временем такая ситуация встречается относительно редко.
объект
Обзор
- Redis не использует напрямую предыдущую структуру данных для реализации базы данных пар ключ-значение, а создает объектную систему на основе структуры данных, и каждый объект использует хотя бы одну из предыдущих структур данных.
- Каждый объект представлен структурой redisObject.
//server.h
typedef struct redisObject {
unsigned type:4; //类型
unsigned encoding:4; // 编码
// 对象最后一个被命令程序访问的时间
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount; // 引用计数
void *ptr; // 指向底层的数据结构指针
} robj;
Преимущества использования объектов
- Перед выполнением команды оцените, может ли объект выполнить данную команду в соответствии с типом объекта.
- Для разных производителей объект Wie устанавливает различные реализации структур данных для оптимизации эффективности.
- Реализован механизм рециркуляции памяти на основе подсчета ссылок, объекты которые больше не используются, память будет автоматически освобождаться
- Подсчет ссылок реализует механизм совместного использования объектов, несколько баз данных совместно используют один и тот же объект для экономии памяти.
- Объект с информацией о накоплении времени, используемой для расчета времени простоя
объект в редисе
- строковый объект
- объект списка
- хэш-объект
- объект коллекции
- упорядоченное сочетание объектов
Тип объекта и кодировка
тип объекта
объект | Свойство типа объекта | вывод команды типа |
---|---|---|
строковый объект | REDIS_STRING | string |
объект списка | REDIS_LIST | list |
хэш-объект | REDIS_HASH | hash |
объект коллекции | REDIS_SET | set |
упорядоченный объект коллекции | REDIS_ZSET | zset |
кодировка объекта
- Кодировка определяет тип данных, на который указывает ptr, указывая, какой тип данных используется в качестве базовой реализации.
- Используйте как минимум две разные кодировки для каждого типа объекта.
- Благодаря кодированию Redis может устанавливать разные кодировки в соответствии с разными сценариями, что значительно повышает гибкость и эффективность.
константа кодирования | соответствующая структура данных | Вывод команды OBJECT ENCODING |
---|---|---|
REDIS_ENCODING_INT | Целое число длинного типа | "инт" |
REDIS_ENCODING_EMBSTR | Простая динамическая строка, закодированная с помощью embstr | "эмбстр" |
REDIS_ENCODING_RAW | простая динамическая строка | "сырой" |
REDIS_ENCODING_HT | Словарь | "хеш-таблица" |
REDIS_ENCODING_LINKEDLIST | Двусторонний связанный список | "связанный список" |
REDIS_ENCODING_ZIPLIST | Сжатый список | "зиплист" |
REDIS_ENCODING_INTSET | коллекция целых чисел | "вставка" |
REDIS_ENCODING_SKIPLIST | Таблицы перехода и словари | "скиплист" |
строковый объект
- Кодировка строкового объекта может быть
- int
- raw
- embstr
- Числа с плавающей запятой также хранятся в Redis как строковые объекты, и при выполнении вычислений они сначала преобразуются обратно в числа с плавающей запятой.
Содержимое строкового объекта | длина | тип кодирования |
---|---|---|
целочисленное значение | - | int |
строковое значение | менее 32 байт | embstr |
строковое значение | больше 32 байт | raw |
Кодировка embstr — это оптимизированный метод кодирования, специально используемый для сохранения коротких строк. Эта кодировка, как и исходная кодировка, использует структуру redisObject и структуру sdshdr для представления объектов. Разница в том, что:
- Необработанное кодирование дважды вызывает функцию выделения памяти для создания структур redisObject и sdrhdr соответственно.
- embstr вызывает функцию выделения памяти один раз, чтобы создать непрерывное пространство, которое включает в себя redisObject и sdrhdr.
преобразование кода
Когда объекты с кодировкой int и embstr удовлетворяют условиям, они будут автоматически преобразованы в строковые объекты с необработанным кодированием.
- объект кодирования int, при выполнении команды объект больше не будет целым числом, он будет преобразован в необработанный объект
- Кодировка embstr не имеет соответствующей функции выполнения и является кодировкой только для чтения. Когда задействована модификация, она будет преобразована в необработанный объект.
строковая команда
Все ключи в Redis являются строковыми объектами, поэтому все команды для ключей созданы для строковых ключей.
- set
- get
- append
- incrbyfloat
- incrby
- decrby
- strlen
- strrange
- getrange
объект списка
- Кодировка объекта списка может быть
- ziplist
- linkedlist
преобразование кода
Два условия для использования кодировки ziplist следующие, а те, которые не выполняются, кодируются в linkedlist (эти два условия можно изменить в файле конфигурации):
- Все сохраненные строковые элементы имеют длину менее 64 байт.
- Количество элементов в списке меньше 512
команда списка
- lpush
- rpush
- lpop
- rpop
- lindex
- llen
- linsert
- lrem
- ltrim
- lset
хэш-объект
Кодирование хеш-объекта может быть
- ziplist
- hashtable
преобразование кода
- Для использования ziplist необходимо выполнить два условия, если нет, то используется хеш-таблица (эти два условия можно изменить в файле конфигурации)
- Все пары ключ-значение имеют строки ключа и значения длиной менее 64 байт.
- Количество пар ключ-значение меньше 512.
хэш-команда
- hset
- hget
- hexists
- hdel
- hlen
- hgetall
объект коллекции
Кодировка объекта коллекции может быть:
- intset: все элементы хранятся в наборе целых чисел
- hashtale: значение словаря равно null
преобразование кода
Коллекция использует intset для выполнения двух условий, если нет, используйте hashtable (параметры можно изменить через файл конфигурации)
- Все сохраненные элементы являются целыми значениями
- Количество элементов не превышает 512
установить команду
- sadd
- scard
- sismember
- smembers
- srandmember
- spop
- srem
упорядоченное сочетание объектов
Кодирование отсортированного набора может быть
- ziplist: каждый элемент представлен двумя узлами рядом друг с другом, первый представляет участника, а второй представляет счет. Маленькие баллы располагаются ближе к началу таблицы, а большие — ближе к концу таблицы.
- skiplist: используйте zset в качестве базовой реализации.Структура zset включает в себя как словарь, так и список пропусков, которые используются для поиска оценки и сортировки оценки или запроса диапазона в соответствии с ключом соответственно.
// 两种数据结构通过指针共享元素成员和分值,不会浪费内存
typedef struct zset {
zskplist *zsl; //跳跃表,方便zrank,zrange
dict *dict; //字典,方便zscore
}zset;
преобразование кода
При выполнении следующих двух условий используйте кодировку ziplist, в противном случае используйте Skiplist (можно изменить в файле конфигурации)
- Количество сохраненных элементов меньше 128
- Длина элемента меньше 64 байт.
упорядоченная команда установки
- zadd
- zcard
- zcount
- zrange
- zrevrange
- zrem
- zscore
Проверка типов и полиморфизм команд
Команды Redis можно разделить на две категории:
- Может быть выполнен на любом типе ключа, например
- del
- expire
- rename
- type
- object
- Может выполняться только для определенных типов ключей, например, предыдущие команды для различных объектов. Это реализовано через атрибут type объекта redisObject.
восстановление памяти
Redis записывает информацию о счетчике ссылок на объект через атрибут refcount объекта и автоматически освобождает объект для восстановления памяти, когда это необходимо.
совместное использование объектов
- Объекты, содержащие одно и то же значение, значение ключа указывает на один и тот же объект для экономии памяти.
- При инициализации redis создается 10 000 строковых объектов, включая все целочисленные значения от 0 до 9999. Когда эти значения потребуются, сервер будет делиться этими объектами вместо создания новых.
- Количество может быть изменено через файл конфигурации
- Объекты, которые не содержат строк, в настоящее время являются общими, так как сравнение строк на предмет их совпадения по своей сути вызовет проблемы с производительностью.
Время простоя объекта
- Продолжительность бездействия = текущее время - redisObject.lru, lru записывает время последнего доступа к объекту
- Когда Redis настроен на максимальный объем памяти (maxmemory), когда алгоритм восстановления определяет, что объем памяти превышает это значение, для восстановления памяти первыми будут освобождены те, у которых больше времени простоя.
Справочная команда
# 设置字符串
set msg "hello world"
rpush numbers 1 2 3 4 5
llen numbers
lrange numbers 0 5
# 获取键值使用的底层数据结构
object encoding numbers
# 查看对象的引用计数值
object refcount numbers
# 对象空转时长: value=now-object.lru
object idletime numbers
использованная литература
- «Проектирование и реализация Redis»