Разные Redis
Когда дело доходит до Redis, о чем каждый должен думать?
Высокий уровень параллелизма, хранилище KV, база данных в памяти, богатая структура данных, один поток (до версии 6)
Затем, далее, я отвечу на вышеперечисленные вещи один за другим и покажу вам прелесть Redis.Статья будет длинной и с какой-то ерундой, пожалуйста, пропустите ее, спасибо! ~
Почему возникает кэш?
Как правило, данные находятся в базе данных, а прикладная система непосредственно управляет базой данных. Когда количество посещений исчисляется десятками тысяч и увеличивается нагрузка на базу, что делать?
Небольшой партнер скажет, суб-библиотека подсуди, отдельный чтение и запись. Действительно, это действительно относительно высокие решения трафика, однако, если больше посещений, 100 000, 1 миллион из него? Как разделить его, похоже, не решает проблему, поэтому нам нужно использовать другие способы решения высокой базы данных параллелизма, приносит давление.
В это время появляется кеш. Кэш, как следует из названия, должен сначала кэшировать данные в памяти. При доступе мы сначала получим доступ к данным в памяти. Если данные в памяти не существуют, в на этот раз мы прочитаем его снова.Выберите базу данных, а затем создайте резервную копию данных в базе данных в памяти, чтобы в следующий раз, когда придет запрос на чтение, к нему сначала обращались непосредственно из памяти, а данные будут возвращены непосредственно после доступа к данным в памяти. Это отлично снижает нагрузку на базу данных.Может приходит 100 000 запросов, и все они обращаются к данным, зарезервированным в памяти, не обращаясь к базе данных, или только небольшое количество запросов обращается к базе данных, что действительно значительно сокращается. давление на базу данных, а это также улучшает реакцию системы. Подумайте об этом, скорость чтения и записи памяти намного быстрее, чем скорость чтения и записи жесткого диска. Память, считанная запросом, может быть намного быстрее, чем чтение жесткого диска.Удобство пользователя также будет высоким.
Что такое кеш?
Кэш изначально относится к высокоскоростной памяти на ЦП.Он обменивается данными с ЦП перед памятью, и скорость очень высокая.
Теперь обычно относится к набору копий исходных данных, хранящихся на компьютере для быстрого доступа.
В интернет-технологиях кэш-память является одной из ключевых технологий для быстрого отклика системы.
Кэшированный режим чтения-записи
Есть три режима чтения-записи кеша
Шаблон кэширования в сторону (обычно используется)
Cache Aside Pattern (побочный кеш), самый классический кеш + режим чтения и записи базы данных
При чтении сначала прочитайте кеш, если кеша нет, прочитайте базу, затем выньте данные и поместите их в кеш, и заодно верните ответ.
При обновлении сначала обновить базу, а потом удалить кеш
Зачем удалять кеш вместо обновления кеша?
1. Кэшированное значение представляет собой структуру, хеш, список и обновление данных, которые необходимо пройти.
2. Ленивая загрузка, кеш обновляется по мере использования, либо кеш может заполняться асинхронно
Три случая большого количества одновременных грязных чтений
1. Сначала обновите базу данных, затем обновите кеш.
Между обновлением и фиксацией, если кеш обновляется, а фиксация не удалась, БД несовместима с кэшированными данными.
2. Сначала удалите кэш, затем обновите базу данных.
Между обновлением и фиксацией происходит новое чтение, кеш пуст, данные БД считываются в кеш, данные старые
БД - это новые данные после фиксации
Тогда БД несовместима с кешированными данными
3. Сначала обновить базу, а потом удалить кеш (рекомендуется)
Между обновлением и фиксацией происходит новое чтение, кеш пуст, данные БД считываются в кеш, данные старые
БД - это новые данные после фиксации
Тогда БД несовместима с кешированными данными
Используйте стратегию отложенного двойного удаления
Read/Write Through Pattern
Приложение работает только с кешем, кеш управляет базой данных
Read-Through (режим проникающего чтения/режим прямого чтения): приложение читает кеш, в кеше его нет, кеш возвращается источнику в базу данных, а кеш записывается
Сквозная запись (режим сквозной записи/режим сквозной записи): приложение записывает в кеш, а кеш записывает в базу данных. В этом режиме необходимо предоставить обработчик для базы данных, а разработка более сложная.
Write Behind Caching Pattern
Приложение только обновляет кеш
Кэш обновляет данные пакетами или объединяет их с БД асинхронно.
Невозможно синхронизировать все время, да еще и данные теряются
А что такое Редис?
Redis — это высокопроизводительная NoSQL (нереляционная база данных) с открытым исходным кодом, написанная на языке C, также называемая кэш-базой данных, где данные хранятся в памяти. Redis хранится в форме ключ-значение, которая отличается от традиционных реляционных баз данных. Эти основные требования традиционных баз данных не обязательно соблюдаются. Например, не следуйте стандарту SQL, транзакциям, структуре таблиц и т. д. Redis имеет очень богатые типы данных, такие как String, list, set, zset, hash и т. д.
Что может Редис?
-
Вышеупомянутое может снизить нагрузку на базу данных, увеличить параллелизм и улучшить время отклика системы.
-
Разделить сеанс
Традиционный сеанс поддерживается и управляется его собственным котом. В случае кластеризации и распределения разные коты должны управлять разными сеансами, а репликация сеанса может выполняться только между каждым котом через сеть и ввод-вывод, что влияет на производительность системы.
Redis решает эту проблему и сохраняет информацию о сеансе после успешного входа в Redis, чтобы несколько котов могли обмениваться информацией о сеансе.
-
Сделать распределенную блокировку
Как правило, блокировки в Java являются многопоточными блокировками, которые находятся в процессе. Несколько процессов также вызовут проблемы, если они выполняются одновременно, и время также должно контролироваться. В настоящее время Redis можно использовать для распределенных блокировок, используя Команда Redis setnx для достижения
У использования Redis в качестве кэша так много преимуществ, но много ли соответствующих недостатков?
-
Дополнительные расходы на оборудование
Кэширование — это технология пространства-времени в программных системах, которая требует дополнительного дискового пространства и памяти для хранения данных.
-
Инвалидация кеша с высоким параллелизмом
В случае высокого параллелизма инвалидация кеша (проникновение кеша, лавина кеша, поломка кеша и т. д.) вызовет мгновенное увеличение доступа к базе данных или даже сбой, поэтому эти проблемы необходимо решать.
-
Синхронизация данных кэша и базы данных
Кэш и база данных не всегда могут синхронизировать данные
-
Соревнование по параллельному кэшированию
Проблема параллелизма, вызванная порядком выполнения, когда несколько клиентов Redis одновременно устанавливают значение ключа.
Установка Redis здесь обсуждаться не будет. В Интернете есть множество руководств по установке на Mac, Windows и Linux. Вы можете найти их в Интернете и следить за ними. Это относительно просто. Далее я предлагаю вам проанализировать некоторые из них. Общие типы данных Redis.
Структура данных Redis
Redis — это система хранения «ключ-значение», а тип ключа — строка.
В Redis существует пять распространенных типов данных значений: строка, список, хеш, набор, zset.
строка тип строки
Строка подходит для кеша с одним значением, кеша объектов, распределенной блокировки и т. д.
Имя команды | формат команды | описание команды |
---|---|---|
set | set key value | назначать |
get | get key | ценность |
getset | getset key value | принять значение и присвоить |
setnx | setnx key value | использовать присваивание, когда значение не существует установить значение ключа NX PX 3000 атомарной операции, px устанавливает количество миллисекунд |
append | append key value | добавить значение в конец |
strlen | strlen key | получить длину строки |
incr | incr key | Увеличение числа |
incrby | incrby key increment | Увеличить указанное целое число |
decr | decr key | Уменьшение числа |
decrby | decrby key decrement | Уменьшить указанное целое число |
mset | mset key value key value | массовое присвоение |
mget | mget key key | стоимость партии |
Далее мы выполняем эти команды для Redis ниже
установить команду:
127.0.0.1:6379> set name liuxixi
OK
получить команду:
127.0.0.1:6379> set name liuxixi
OK
127.0.0.1:6379> get name
"liuxixi"
команда getset:
127.0.0.1:6379> getset name lixixi
"liuxixi"
127.0.0.1:6379> get name
"lixixi"
команда setnx:
127.0.0.1:6379> setnx age 12
(integer) 1 //第一次返回1代表设置成功
127.0.0.1:6379> setnx age 13
(integer) 0 //第二次返回0代表没有设置成功
Применение команды:
127.0.0.1:6379> append name xi
(integer) 8 //返回的8是value的长度
127.0.0.1:6379> get name
"lixixixi"
команда стрлен:
127.0.0.1:6379> strlen name
(integer) 8
команда увеличения:
127.0.0.1:6379> incr age //可以用来做点赞功能
(integer) 14
127.0.0.1:6379> get age
"14"
incrby команда:
127.0.0.1:6379> incrby age 3
(integer) 17
127.0.0.1:6379> get age
"17"
команда декр:
127.0.0.1:6379> decr age
(integer) 16
127.0.0.1:6379> get age
"16"
Команда расшифровки:
127.0.0.1:6379> decrby age 3
(integer) 13
127.0.0.1:6379> get age
"13"
хэш тип хэша
имя команды | формат команды | описание команды |
---|---|---|
hset | hset key field value | Назначение, не делается различия между добавлением или изменением |
hmset | hmset field1 value1 field2 value2 | массовое присвоение |
hsetnx | hsetnx key field value | Назначение, ничего не делать, если поле существует |
hexists | hexists key filed | Проверить, существует ли поле |
hget | hget key field | получить значение поля |
hmget | hmget key field1 field2 ... | Получить несколько значений поля |
hgetall | hgetall key | |
hdel | hdel key field1 field2.. | удалить указанное поле |
hincrby | hincrby key field increment | Указанное поле увеличивается само по себе |
hlen | hlen key | получить количество полей |
Сценарий применения: может использоваться как корзина для покупок в электронной коммерции.
Корзина электронной коммерции:
- Идентификатор пользователя как ключ
- идентификатор продукта является полем
- Количество товаров является ценностью
Работа с корзиной:
- Добавить товар: hset в корзину: 1001 10088 1
- Увеличить количество: корзина hincrby: 1001 10088 1
- Общее количество товаров: hlen cart: 1001
- Удалить Продукт: Тележка для гун: 1001 10088
- Gets cart Все товары: hgetвсей корзины: 1001
Преимущества и недостатки хэш-структуры
преимущество
- Однотипные данные классифицируются и объединяются для хранения, что удобно для управления данными
- По сравнению со строковыми операциями он потребляет меньше памяти и процессора.
- Экономит место по сравнению со строковым хранилищем
недостаток
- Функции истечения срока действия нельзя использовать на поле, только на ключе.
- Архитектура кластера Redis не подходит для крупномасштабного использования.
список тип списка
Тип списка может хранить упорядоченные повторяющиеся элементы.
Получение записей возле головы или хвоста происходит очень быстро
Количество элементов в списке не более 2^31-1 (4 миллиарда).
Общие рабочие команды следующие:
имя команды | формат команды | описание команды |
---|---|---|
lpush | lpush key v1 v2 v3 ... | Вставить список слева |
lpop | lpop key | Возьмите его слева от списка |
rpush | rpush key v1 v2 v3 ... | Вставить список справа |
rpop | rpop key | Возьмите его с правой стороны списка |
lpushx | lpushx key value | Вставить значение в начало списка |
rpushx | rpushx key value | вставить значение в конец списка |
blpop | blpop key timeout | Выньте из левой части списка, заблокируйте, когда список пуст, вы можете установить максимальное время блокировки, единица измерения - секунды |
brpop | blpop key timeout | Выньте из правой части списка, заблокируйте, когда список пуст, вы можете установить максимальное время блокировки, единица измерения - секунды |
llen | llen key | Получить количество элементов в списке |
lindex | lindex key index | Получить элемент с индексом index в списке index начинается с 0 |
lrange | lrange key start end | Возвращает элементы указанного диапазона в списке, диапазон задан по началу и концу |
lrem | lrem key count value | Удалить элементы из списка, которые равны значению Когда count>0, lrem удалит слева списка; когда count |
lset | lset key index value | Установите элементы местоположения индекса списка на значение |
ltrim | ltrim key start end | Обрежьте список, оставив только диапазон от начала до конца. |
rpoplpush | rpoplpush key1 key2 | Вставьте справа от списка key1 и вставьте слева от списка key2 |
brpoplpush | brpoplpush key1 key2 | Выталкивание из правой части списка key1 и вставка его в левую часть списка key2 заблокирует |
linsert | linsert key BEFORE/AFTER pivot value | Вставить значение в список до или после поворота значения |
Общие структуры данных
Стек(стек)=LPUSH+LPOP
Очередь (очередь) = lpush + rpop
BlockingMQ (очередь блокировки) = LPUSH+BRPOP
список сценариев применения:
Поток новостей официального аккаунта Weibo и WeChat
Weibo и официальный аккаунт - все новые новости, которые в топе
-
MacTalk отправил Weibo с идентификатором сообщения 10018
LPUSH msg:{ID} 10018
-
Запаска сказала, что машина размещена на Weibo, ID сообщения 10086
LPUSH msg:{ID} 10086
-
Просматривайте последние новости Weibo
LRANGE msg:{ID} 0 4
Если Weibo big V или WeChat big V уделяют больше внимания, несколько тысяч, десятков тысяч можно распространять партиями, например, сначала отправлять их в онлайн, это будет очень быстро.
установить тип коллекции
набор: неупорядоченные, уникальные элементы
Максимальное количество элементов в наборе 2^32-1.
Общие рабочие команды следующие:
имя команды | формат команды | описание команды |
---|---|---|
sadd | sadd key mem1 mem2 .... | Добавить нового участника в коллекцию |
srem | srem key mem1 mem2 .... | Удалить указанный элемент из коллекции |
smembers | smembers key | Получить все элементы в коллекции |
spop | spop key | Возвращает случайный элемент в коллекции и удаляет этот элемент |
srandmember | srandmember key | Возвращает случайный элемент в коллекции, не удаляя элемент |
scard | scard key | Получить количество элементов в коллекции |
sismember | sismember key member | Проверить, находится ли элемент в коллекции |
sinter | sinter key1 key2 key3 | Найдите пересечение нескольких множеств |
sdiff | sdiff key1 key2 key3 | Найдите разницу нескольких наборов |
sunion | sunion key1 key2 key3 | найти объединение нескольких множеств |
Сценарии применения:
Подходит для структур данных, которые не могут повторяться и не требуют упорядочения
Например: подписчики также могут проводить случайную лотерею через spop.
Лотерейный апплет WeChat:
-
Нажмите, чтобы принять участие в розыгрыше, чтобы присоединиться к коллекции
SADD key {userId}
-
Посмотреть всех пользователей, участвовавших в лотерее
SMEMBERS key
-
Победители розыгрыша
SRANDMEMBER key [count] / SPOP key [count]
Wechat Weibo Нравится, Избранное, Тег
-
как
Sadd Alke: {ID сообщений} {ID пользователя}
-
в отличие
SREM, например: {идентификатор сообщения} {идентификатор пользователя}
-
Проверить, понравилось ли пользователю
SISMEMBMR, например: {идентификатор сообщения} {идентификатор пользователя}
-
Получить список понравившихся пользователей
УЧАСТНИКИ любят: {идентификатор сообщения}
-
Получайте лайки от пользователей
SCARD типа: {идентификатор сообщения}
Операция сбора реализует следующую модель Weibo и WeChat.
-
люди, на которых вы подписаны
хх -> {х, ххх}
-
люди, на которых я подписан
Ll -> {xx , xxx}
-
я и люди, на которых вы подписаны
SINTER xx LI -> {xxx}
-
Я обеспокоен людьми, также обеспокоен им:
SISMEMBER xx LI
-
Люди, которых я могу знать:
SDIFF xx LI -> {xx}
zset упорядоченный тип коллекции
Сами элементы неупорядочены и не повторяются
Каждый элемент связан с оценкой (score)
Сортировка по баллам, баллы можно повторить
Общие рабочие команды следующие:
имя команды | формат команды | описание команды |
---|---|---|
zadd | zadd key score1 member1 score2 member2 ... | Добавить новый элемент в отсортированный набор |
zrem | zrem key mem1 mem2 .... | удаляет указанный элемент из упорядоченного набора |
zcard | zcard key | Получить количество элементов в отсортированном наборе |
zcount | zcount key min max | Возвращает количество элементов в коллекции, значение оценки которых находится в интервале [мин, макс] |
zincrby | zincrby key increment member | На члене плюсового приращения набора баллов |
zscore | zscore key member | Получить оценку участников в коллекции |
zrank | zrank key member | Получить ранг участников в наборе (от малого к большому) |
zrevrank | zrevrank key member | Получить ранг участников в наборе (в порядке убывания баллов) |
zrange | zrange key start end | Получить элементы указанного интервала в наборе, отсортированные по возрастанию оценки |
zrevrange | zrevrange key start end | Получить элементы указанного интервала в наборе, отсортированные по убыванию оценки |
Сценарии применения:
Поскольку его можно сортировать по количеству очков, он подходит для различных списков лидеров. Например: рейтинги, рейтинги продаж, рейтинги подписчиков и т. д.
Пример:
127.0.0.1:6379> zadd hit:1 100 item1 20 item2 45 item3
(integer) 3
127.0.0.1:6379> zcard hit:1
(integer) 3
127.0.0.1:6379> zscore hit:1 item3
"45"
127.0.0.1:6379> zrevrange hit:1 0 -1
1) "item1"
2) "item3"
3) "item2"
127.0.0.1:6379>
zset установить операцию для достижения таблицы лидеров
-
Нажмите, чтобы узнать новости
ZINCRBY горячие новости:20190819 1 гвардеец Гонконг
-
10 лучших в выставочный день
ZREVRANGE hotNews:20190819 0 9 WITHSCORES
-
Список поиска за семь дней
ZUNIONSTORE hotNews:20190813-20190819 7
hotNews:20190813 hotNews:20190814... hotNews:20190819
-
Показать семь из первой десятки рейтинга
ZREVRANGE hotNews:20190813-201908109 0 9 WITHSCORES
Однопоточность и высокая производительность для Redis
Является ли Redis однопоточным?
Один поток Redis в основном означает, что сетевой ввод-вывод и чтение и запись пары ключ-значение Redis выполняются одним потоком, который также является основным процессом Redis, предоставляющим внешние службы хранения ключей-значений. Но другие функции Redis, такие как сохранение, асинхронное удаление, синхронизация данных кластера и т. д., выполняются дополнительными потоками.
Почему Redis работает в однопоточном режиме так быстро?
Здесь мы тестируем параллелизм, поддерживаемый Redis локально.
执行这条命令: ./redis-benchmark get
结果:
====== get ======
100000 requests completed in 1.02 seconds
50 parallel clients
3 bytes payload
keep alive: 1
host configuration "save": 900 1 300 10 60 10000
host configuration "appendonly": no
multi-thread: no
0.00% <= 0.1 milliseconds
13.00% <= 0.2 milliseconds
55.85% <= 0.3 milliseconds
80.60% <= 0.4 milliseconds
92.57% <= 0.5 milliseconds
97.12% <= 0.6 milliseconds
99.06% <= 0.7 milliseconds
99.68% <= 0.8 milliseconds
99.86% <= 0.9 milliseconds
99.90% <= 1.0 milliseconds
99.90% <= 1.1 milliseconds
99.90% <= 1.2 milliseconds
99.91% <= 1.3 milliseconds
99.93% <= 1.4 milliseconds
99.95% <= 1.5 milliseconds
99.97% <= 1.6 milliseconds
99.98% <= 1.7 milliseconds
99.99% <= 1.8 milliseconds
99.99% <= 1.9 milliseconds
100.00% <= 2 milliseconds
100.00% <= 2 milliseconds
98328.42 requests per second
Здесь мы видим, что если секунд нет, он может поддерживать почти 100 000 concurrency, что уже является очень страшными данными.
Поскольку все данные находятся в памяти, все операции являются операциями на уровне памяти, но также и для того, чтобы избежать однопотокового переключения производительности проблемы многопоточного потребления. Поскольку Redis является однопоточным, будьте осторожны при использовании команд Redis, эти команды (например, ключи) отнимают много времени, их следует использовать с осторожностью, поскольку они могут привести к Redis Caton.
Как один поток Redis обрабатывает такое количество одновременных клиентских подключений?
Мультиплексирование операций ввода-вывода в Redis: Redis использует epoll для реализации мультиплексирования операций ввода-вывода, помещая информацию о соединении и события в очередь и одновременно помещая их в диспетчер событий файлов, а диспетчер событий распределяет события обработчику событий.
Некоторые другие расширенные команды Redis
keys
Полный обход ключей используется для получения списка всех ключей, которые удовлетворяют определенным правилам обычных строк.Когда объем данных Redis относительно велик, производительность относительно низкая, и этого следует избегать.
сканирование: клавиша прогрессивного обхода
SCAN cursor [MATCH pattern] [COUNT count]
Параметр сканирования предоставляет три параметра: первый — целочисленное значение курсора (значение индекса хэш-контейнера), второй — обычный шаблон ключа, а третий — количество ключей, пройденных за один раз (эталонное значение, количество базовых обходов не обязательно), а не количество подходящих результатов. При первом обходе значение курсора равно 0, а затем первое целочисленное значение в возвращаемом результате используется в качестве курсора для следующего обхода. Перемещайтесь до тех пор, пока возвращаемое значение курсора не станет равным 0.
127.0.0.1:6379> scan 0 match key* count 3
1) "12" //这个12代表返回下一次扫描的游标数,下一次scan就需要从这个数开始扫描
2) 1) "key4"
127.0.0.1:6379> scan 12 match key* count 3
1) "26"
2) 1) "key1"
2) "key3"
Примечание: Но сканирование не является совершенным.Если в процессе сканирования происходит изменение ключа (добавление, удаление, изменение), эффект обхода может столкнуться со следующими проблемами: вновь добавленный ключ может не пройти, и обход повторяется. Другими словами, сканирование не гарантирует, что полный ключ проходит через все ключи, это то, что мы должны учитывать при разработке.
Основные принципы проектирования Redis
Redis как система хранения ключей и значений имеет следующую структуру данных:
Экземпляр Redis соответствует нескольким БД, а БД соответствует нескольким ключам. Ключи обычно представляют собой строки. Значение, стоящее за ним, называется RedisObject. Это не означает, что значение является строкой, списком, картой и т. д., но что все эти Типы используются Redis.Он инкапсулирован в RedisObjcet, какой это тип? Вот способ использования указателя, чтобы указать, к какому типу он относится.
Почему вы хотите это сделать, в основном для повышения производительности Redis
PS: Вставьте здесь предложение, почему способ использования указателей лучше, чем способ использования самого объекта?
Здесь есть две точки:
Во-первых, это динамическое размещение, и большая особенность указателей заключается в том, что вам нужно только объявить тип, на который он указывает впереди (и если вы хотите использовать фактический объект, вам также нужно его определить). Таким образом, вы можете уменьшить связь между вашими модулями компиляции и, таким образом, сократить время компиляции.
Структура RedisDB
В Redis нет понятия таблиц. БД, соответствующие экземплярам Redis, различаются по номерам. Сама БД является пространством имен ключа.
Например: user: 1000 в качестве значения ключа, указывающего на элемент с идентификатором 1000 в пользовательском пространстве имен, аналогично строке с идентификатором = 1000 в пользовательской таблице.
Строка паспорта безопасности
Как мы все знаем, Redis реализован на языке C. В языке C тип String на самом деле представляет собой массив символов, например char data[]="xxx\0". Однако клиент может отправить набор отправка произвольной строки не проверяется, поэтому, если мы отправим строку xx\0xx, то xx после \0 не будет прочитан, а только предшествующий xx (в языке C "\0" означает конец строки, если в самой строке есть символ "\0", строка будет усечена)
Таким образом, Redis реализовал строку с именем SDS, и SDS записал LEN и char buf[], len используется для записи длины buf, например, Char Buf[] = "xx \ 0xx", тогда Len равно 5 , SDS Так же есть более важный атрибут free, указывающий сколько там.
free вычисляется путем изменения len. Например, если «xxx1234» изменить на «xxx123456», емкость будет увеличена в соответствии с (len + addlen) * 2 = 18. В это время len становится 9, а free — 18. -9. 9
Например:
char buf[] = "xxx1234" 改成 "xxx123456" //这里的buf是柔性数组
free:12 变成free:10
len:8 变成len:10
Каковы преимущества Redis при разработке SDS следующим образом:
- Двоичные безопасные структуры данных
- Предоставляет механизм предварительного выделения памяти, чтобы избежать частого выделения памяти.
- Библиотека функций, совместимая с языком C
- Есть отдельные статистические переменные len и free, по которым можно легко получить длину строки, что позволяет избежать риска неполного чтения.
- Содержимое хранится в гибком массиве buf, а указатель, предоставляемый SDS верхнему уровню, является не указателем на структуру SDS, а указателем непосредственно на гибкий массив buf. Верхний уровень может читать содержимое SDS так же, как чтение строк C, и совместим с различными функциями языка C для обработки строк.
Вот объяснение того, что такое мягкий массив:
Гибкий массив — это массив, размер которого необходимо определить.Последним элементом структуры в языке C может быть массив неизвестного размера, который является так называемой нулевой длиной, поэтому мы можем использовать структуру для создания гибкого массива. множество. Основная цель гибких массивов — удовлетворить потребности структур переменной длины, чтобы решить проблему избыточности памяти и выхода массива за границы при использовании массивов.
Это также было достигнуто до Redis 3.2.