Я видел вопрос на stackoverflow,Redis strings vs Redis hashes to represent JSON: efficiency?Содержание следующее:
I want to store a JSON payload into redis. There's really 2 ways I can do this:
One using a simple string keys and values.
key:user, value:payload (the entire JSON blob which can be 100-200 KB)
SET user:1 payload
Using hashes
HSET user:1 username "someone" HSET user:1 location "NY" HSET user:1 bio "STRING WITH OVER 100 lines"
Keep in mind that if I use a hash, the value length isn't predictable. They're not all short such as the bio example above. Which is more memory efficient? Using string keys and values, or using a hash?
Строковые и хэш-визуальные тесты
Во-первых, давайте проверим данные с тестовыми данными, Структура тестовых данных выглядит следующим образом:
values = {
"name": "gs",
"age": 1
}
Используйте for для генерации ключей 10w, а правила генерации ключей:
for i in range(100000):
key = "object:%d" % i
Храните данные в redis в виде хэша и строки (значения кодируются как строки с использованием json).
Результат выглядит следующим образом:
хеш занимает 10.16M
строка занимает 10.15M
Кажется, это не согласуется с нашим впечатлением о том, что хеш занимает много места Почему это так?
Это связано с тем, что хеш-объекты Redis имеют два метода кодирования:
- ziplist (zipmap до 2.6)
- hashtable
Хэш-объект использует кодировку ziplist, если он может удовлетворять обоим из следующих условий:
- Длина строки всех пар ключ-значение, хранящихся в хеш-объекте, меньше 64 байтов;
- Количество пар ключ-значение, хранящихся в хеш-объекте, меньше 512;
Хэш-объекты, которые не соответствуют этим двум условиям, должны использовать кодировку хэш-таблицы. Приведенные выше тестовые данные удовлетворяют этим двум условиям, поэтому здесь вместо хеш-таблицы используются данные, хранящиеся в ziplist.
注意
Верхний предел этих двух условий можно изменить.Подробности см. в описании параметра hash-max-ziplist-value и параметра hash-max-ziplist-entries в файле конфигурации.hash-max-ziplist-entries for Redis >= 2.6 hash-max-ziplist-value for Redis >= 2.6
ziplist
Базовые данные кодирования ziplist должны использовать сжатый список в качестве базовой структуры данных, структура выглядит следующим образом:
Когда хэш-объект сохраняется с использованием ziplist, программа помещает узел ziplist, содержащий ключ, в конец списка, а затем помещает узел ziplist, содержащий значение, в конец списка.
При сохранении таким образом нет необходимости применять дополнительное пространство памяти, и каждый ключ должен хранить некоторую связанную системную информацию (например, время истечения срока действия, LRU и т. д.), по сравнению с типом String Key/Value, типом Hash. Количество ключей значительно уменьшено (большинство ключей представлены и хранятся в виде хэш-полей), что дополнительно оптимизирует эффективность использования дискового пространства.
в этомredis memory optimizationВ официальной статье автор настоятельно рекомендует использовать хеш для хранения данных
Use hashes when possible
Small hashes are encoded in a very small space, so you should try representing your data using hashes every time it is possible. For instance if you have objects representing users in a web application, instead of using different keys for name, surname, email, password, use a single hash with all the required fields.
But many times hashes contain just a few fields. When hashes are small we can instead just encode them in an O(N) data structure, like a linear array with length-prefixed key value pairs. Since we do this only when N is small, the amortized time for HGET and HSET commands is still O(1): the hash will be converted into a real hash table as soon as the number of elements it contains will grow too much (you can configure the limit in redis.conf).
This does not work well just from the point of view of time complexity, but also from the point of view of constant times, since a linear array of key value pairs happens to play very well with the CPU cache (it has a better cache locality than a hash table).
hashtable
hashtable
Закодированный хэш-объект использует словарь в качестве базовой реализации, и каждая пара ключ-значение в хеш-объекте хранится с использованием пары ключ-значение словаря:
- Каждый ключ словаря является строковым объектом, а ключ пары ключ-значение хранится в объекте;
- Каждое значение словаря представляет собой строковый объект, содержащий значение пары ключ-значение.
Закодированный хеш-таблицей объект выглядит следующим образом:
второй тест
values = {
"name": "gs",
"age": 1,
"intro": "long..long..long..string"
}
Второй метод тестирования такой же, как и в первый раз, за исключением того, что к тестовым данным добавляется большая строка, чтобы убедиться, что хэш использует метод хеш-таблицы для хранения данных.
Результат выглядит следующим образом:
хеш-таблица: 1.13G
строка: 1.13G
В принципе же, это должен быть в основном тип Hash, что значительно уменьшает количество ключей (большинство ключей представлены и хранятся в виде полей Hash), тем самым еще больше оптимизируя эффективность использования пространства хранения.
NOTE:Скорость чтения и записи в основном одинакова, с небольшой разницей
Вернемся к этому вопросу, как выбрать строку и хэш?
Я предпочитаю следующий ответ:
Какую структуру данных использовать, на самом деле зависит от данных, которые вы хотите сохранить, и от сценария использования.
Если хранимые данные относительно структурированы, например, кэш пользовательских данных, или с одним или несколькими данными необходимо часто манипулировать, особенно если в данных много файлов, но каждый раз нужно использовать только один или несколько из них. Во многих случаях использование хэша — хороший выбор, поскольку он предоставляет hget и hmget без необходимости извлекать все данные и обрабатывать их в коде.
С другой стороны, если данные сильно различаются, часто необходимо прочитать все данные, а затем обработать их.Хорошим выбором является использование строки.
Конечно, вы также можете слушать Redis и уверенно использовать хэш.
Есть и другой сценарий: если в хеше большое количество полей (тысячи тысяч), нужно подумать, не лучше ли использовать строки для их отдельного хранения.
Ссылка на ссылку
- [1] Redis strings vs Redis hashes to represent JSON: efficiency?: stackoverflow.com/questions/1…
- [2] redis memory optimization: Redis.IO/темы/памятка…
- [3] Дизайн и реализация Redis:Redisbook.com/preview/obj…
Наконец, поблагодарите мою девушку за ее поддержку и терпимость, чем ❤️
Вы также можете ввести следующие ключевые слова в официальном аккаунте, чтобы получить исторические статьи:公号&小程序
| 设计模式
| 并发&协程