В C строка заканчивается нулевым байтом
\0. Из-за этого strlen() каждый раз проходит весь буфер, а хранить произвольные бинарные данные становится неудобно.Поэтому Redis использует собственную структуру SDS — Simple Dynamic Strings.
В памяти она выглядит примерно так:
[len][alloc][flags][данные...\0]
↑
sds
Перед самими данными Redis хранит метаданные:
-
len — текущую длину;-
alloc — размер выделенной памяти;-
flags — тип заголовка.Благодаря этому длина строки определяется за
O(1), а свободное место известно заранее. При добавлении данных Redis не обязан каждый раз заново вычислять размер и перевыделять память.SDS также остаётся совместимой со многими функциями C: указатель ведёт прямо на буфер, а в конце всё равно находится
\0.Но Redis не зависит от этого терминатора — длина хранится отдельно. Поэтому внутри строки могут находиться нулевые байты, изображения, сериализованные объекты и другие бинарные данные.
Важный нюанс: структура
sdshdr из старых примеров сегодня упрощена. Современный Redis выбирает компактный заголовок sdshdr5, sdshdr8, sdshdr16, sdshdr32 или sdshdr64 в зависимости от размера строки.Небольшой заголовок перед буфером решил сразу три проблемы: быстрое получение длины, безопасную работу с бинарными данными и эффективное расширение строк.
Источник:
https://redis.io/docs/latest/operate/oss_and_stack/reference/internals/internals-sds/
https://github.com/redis/redis/blob/unstable/src/sds.h

