Я хочу сохранить полезную нагрузку JSON в Redis. Есть два способа сделать это:
Один использует простые строковые ключи и значения.
ключ: пользователь, значение: полезная нагрузка (весь двоичный объект JSON, который может быть 100-200 КБ)SET user:1 payload
Использование хэшей
HSET user:1 username "someone"
HSET user:1 location "NY"
HSET user:1 bio "STRING WITH OVER 100 lines"
Имейте в виду, что если я использую хеш, длина значения не будет предсказуемой. Они не все короткие, как пример био выше.
Какая память более эффективна? Используя строковые ключи и значения, или используя хэш?
Ответы:
Это зависит от того, как вы получаете доступ к данным:
Перейти к варианту 1:
Перейти к варианту 2:
PS: как правило, выберите вариант, который требует меньше запросов в большинстве случаев использования.
источник
JSON
полезной нагрузки , как ожидается , (классическая проблема неатомическоеread-modify-write
).Эта статья может дать много понимания здесь: http://redis.io/topics/memory-optimization
Есть много способов сохранить массив объектов в Redis ( спойлер : мне нравится вариант 1 для большинства случаев использования):
Сохраните весь объект как строку в кодировке JSON в одном ключе и отслеживайте все объекты, используя набор (или список, если это более уместно). Например:
Вообще говоря, это, вероятно, лучший метод в большинстве случаев. Если в Объекте много полей, ваши Объекты не вложены в другие Объекты, и вы, как правило, получаете доступ только к небольшому подмножеству полей одновременно, может быть, лучше использовать вариант 2.
Преимущества : считается «хорошей практикой». Каждый объект представляет собой полноценный ключ Redis. Синтаксический анализ JSON выполняется быстро, особенно если вам нужно получить доступ ко многим полям для этого объекта одновременно Недостатки : медленнее, когда вам нужно получить доступ только к одному полю.
Сохраните свойства каждого объекта в хэше Redis.
Преимущества : считается «хорошей практикой». Каждый объект представляет собой полноценный ключ Redis. Нет необходимости анализировать строки JSON. Недостатки : возможно, медленнее, когда вам нужно получить доступ ко всем / большинству полей объекта. Кроме того, вложенные объекты (объекты внутри объектов) не могут быть легко сохранены.
Сохраните каждый объект в виде строки JSON в хэше Redis.
Это позволяет вам консолидировать немного и использовать только два ключа вместо большого количества ключей. Очевидным недостатком является то, что вы не можете установить TTL (и другие элементы) для каждого пользовательского объекта, поскольку это просто поле в хэше Redis, а не полноценный ключ Redis.
Преимущества : JSON-анализ выполняется быстро, особенно если вам нужно получить доступ ко многим полям для этого объекта одновременно. Меньше "загрязняющих" пространство имен основного ключа. Недостатки : Примерно такое же использование памяти, как у # 1, когда у вас много объектов. Медленнее, чем # 2, когда вам нужно получить доступ только к одному полю. Вероятно, не считается "хорошей практикой".
Храните каждое свойство каждого объекта в выделенном ключе.
В соответствии со статьей выше, эта опция почти никогда не является предпочтительной (если только свойство Object не должно иметь определенного TTL или чего-то еще).
Преимущества : Свойства объекта - это полноценные ключи Redis, которые не могут быть излишними для вашего приложения. Недостатки : медленный, использует больше памяти и не считается «лучшей практикой». Множество загрязнений пространства имен основного ключа.
Общая сводка
Вариант 4 обычно не является предпочтительным. Варианты 1 и 2 очень похожи, и оба они довольно распространены. Я предпочитаю вариант 1 (вообще говоря), потому что он позволяет хранить более сложные объекты (с несколькими слоями вложенности и т. Д.). Вариант 3 используется, когда вы действительно хотите не загрязнять пространство имен основного ключа (то есть не хотите там быть много ключей в вашей базе данных, и вы не заботитесь о таких вещах, как TTL, разделение ключей или что-то еще).
Если я что-то не так понял, пожалуйста, оставьте комментарий и разрешите мне пересмотреть ответ, прежде чем понизить голосование. Спасибо! :)
источник
obj
и храним поля, такие как views, голосования и избирателей, с отдельными ключами? Таким образом, с помощью одного запроса READ вы получите весь объект и сможете быстро обновить динамические части вашего объекта? Относительно редкие обновления полей в строке JSON можно выполнить, прочитав и записав весь объект обратно в транзакцию.Некоторые дополнения к заданному набору ответов:
Прежде всего, если вы собираетесь эффективно использовать хэширование в Redis, вы должны знать максимальное количество ключей и максимальный размер значений - в противном случае, если они выдают значения из hash-max-ziplist-value или hash-max-ziplist-records, Redis преобразует его в практически обычные пары ключ / значение под капотом. (см. hash-max-ziplist-value, hash-max-ziplist-records). И ломать под капотом из опций хеш-функции очень плохо, потому что каждая обычная пара ключ / значение внутри Redis использует +90 байт на пару.
Это означает, что если вы начнете со второго варианта и случайно выйдете из max-hash-ziplist-value, вы получите +90 байт на КАЖДЫЙ АТРИБУТ, который вы имеете внутри пользовательской модели! (на самом деле не +90, а +70, см. вывод консоли ниже)
Для ответа TheHippo комментарии к Варианту 1 вводят в заблуждение:
hgetall / hmset / hmget на помощь, если вам нужны все поля или несколько операций get / set.
За ответ BMiner.
Третий вариант на самом деле очень интересный, для набора данных с max (id) <has-max-ziplist-value это решение имеет сложность O (N), потому что, к удивлению, Reddis хранит небольшие хэши в виде массива как контейнер длины / ключа / значения объекты!
Но вы не должны волноваться, вы очень быстро сломаете записи в hash-max-ziplist и приступите к решению № 1.
Второй вариант, скорее всего, пойдет к четвертому решению под капотом, потому что, как говорится в вопросе:
И, как вы уже сказали: четвертое решение - самый дорогой +70 байт на каждый атрибут.
Мое предложение, как оптимизировать такой набор данных:
У вас есть два варианта:
Если вы не можете гарантировать максимальный размер некоторых пользовательских атрибутов, тогда вы выбираете первое решение, и если вопрос памяти имеет решающее значение, сожмите пользователя json перед сохранением в redis.
Если вы можете заставить максимальный размер всех атрибутов. Чем вы можете установить hash-max-ziplist-records / value и использовать хэши в виде одного хеша на представление пользователя ИЛИ в качестве оптимизации хеш-памяти из этого раздела руководства Redis: https://redis.io/topics/memory-optimization и сохранить пользователя в виде строки json. В любом случае вы также можете сжать длинные пользовательские атрибуты.
источник