Je veux stocker une charge utile JSON dans redis. Il y a vraiment 2 façons de le faire:
Un utilisant une simple chaîne de clés et de valeurs.
clé: utilisateur, valeur: charge utile (l'intégralité de l'objet blob JSON qui peut être compris entre 100 et 200 Ko)SET user:1 payload
Utiliser des hachages
HSET user:1 username "someone"
HSET user:1 location "NY"
HSET user:1 bio "STRING WITH OVER 100 lines"
Gardez à l'esprit que si j'utilise un hachage, la longueur de la valeur n'est pas prévisible. Ils ne sont pas tous courts comme l'exemple bio ci-dessus.
Quelle est la mémoire la plus efficace? À l'aide de clés et de valeurs de chaîne, ou à l'aide d'un hachage?
Réponses:
Cela dépend de la façon dont vous accédez aux données:
Optez pour l'option 1:
Optez pour l'option 2:
PS: En règle générale, optez pour l'option qui nécessite moins de requêtes sur la plupart de vos cas d'utilisation.
la source
JSON
charge utile est attendue (un problème classique de non-atomiqueread-modify-write
).Cet article peut fournir beaucoup d'informations ici: http://redis.io/topics/memory-optimization
Il existe de nombreuses façons de stocker un tableau d'objets dans Redis ( spoiler : j'aime l'option 1 pour la plupart des cas d'utilisation):
Stockez l'intégralité de l'objet sous forme de chaîne codée JSON dans une seule clé et conservez une trace de tous les objets à l'aide d'un ensemble (ou d'une liste, le cas échéant). Par exemple:
D'une manière générale, c'est probablement la meilleure méthode dans la plupart des cas. S'il y a beaucoup de champs dans l'objet, vos objets ne sont pas imbriqués avec d'autres objets, et vous avez tendance à accéder uniquement à un petit sous-ensemble de champs à la fois, il peut être préférable d'opter pour l'option 2.
Avantages : considéré comme une "bonne pratique". Chaque objet est une clé Redis à part entière. L'analyse JSON est rapide, en particulier lorsque vous devez accéder simultanément à de nombreux champs pour cet objet. Inconvénients : plus lent lorsque vous n'avez besoin d'accéder qu'à un seul champ.
Stockez les propriétés de chaque objet dans un hachage Redis.
Avantages : considéré comme une "bonne pratique". Chaque objet est une clé Redis à part entière. Pas besoin d'analyser les chaînes JSON. Inconvénients : peut-être plus lent lorsque vous devez accéder à tous / la plupart des champs d'un objet. De plus, les objets imbriqués (objets dans les objets) ne peuvent pas être facilement stockés.
Stockez chaque objet sous forme de chaîne JSON dans un hachage Redis.
Cela vous permet de consolider un peu et d'utiliser uniquement deux clés au lieu de beaucoup de clés. L'inconvénient évident est que vous ne pouvez pas définir le TTL (et d'autres éléments) sur chaque objet utilisateur, car il s'agit simplement d'un champ dans le hachage Redis et non d'une clé Redis complète.
Avantages : L'analyse JSON est rapide, en particulier lorsque vous devez accéder à plusieurs champs pour cet objet à la fois. Moins "polluant" de l'espace de noms principal. Inconvénients : À peu près la même utilisation de la mémoire que # 1 lorsque vous avez beaucoup d'objets. Plus lent que # 2 lorsque vous n'avez besoin d'accéder qu'à un seul champ. Probablement pas considéré comme une "bonne pratique".
Stockez chaque propriété de chaque objet dans une clé dédiée.
Selon l'article ci-dessus, cette option n'est presque jamais préférée (sauf si la propriété de l'objet doit avoir un TTL spécifique ou quelque chose).
Avantages : Les propriétés des objets sont des clés Redis à part entière, qui ne sont peut-être pas excessives pour votre application. Inconvénients : lent, utilise plus de mémoire et n'est pas considéré comme une «meilleure pratique». Beaucoup de pollution de l'espace de noms principal.
Sommaire général
L'option 4 n'est généralement pas préférée. Les options 1 et 2 sont très similaires et elles sont toutes les deux assez courantes. Je préfère l'option 1 (en général) car elle vous permet de stocker des objets plus compliqués (avec plusieurs couches d'imbrication, etc.) L'option 3 est utilisée lorsque vous vous souciez vraiment de ne pas polluer l'espace de noms des clés principales (c'est-à-dire que vous ne voulez pas là pour avoir beaucoup de clés dans votre base de données et vous ne vous souciez pas de choses comme TTL, partage de clés, ou autre).
Si je me trompe, pensez à laisser un commentaire et à me permettre de réviser la réponse avant de voter. Merci! :)
la source
obj
et stockons des champs comme les vues, les votes et les votants avec des clés séparées? De cette façon, avec une seule requête READ, vous obtenez l'intégralité de l'objet et pouvez toujours mettre à jour rapidement des parties dynamiques de votre objet? Les mises à jour relativement peu fréquentes des champs de la chaîne JSON peuvent être effectuées en lisant et en réécrivant l'intégralité de l'objet dans une transaction.Quelques ajouts à un ensemble de réponses donné:
Tout d'abord, si vous utilisez efficacement le hachage Redis, vous devez connaître le nombre de clés et la valeur maximale de la taille des clés - sinon, si elles décomposent la valeur de hachage-max-ziplist ou les entrées de hachage-max-ziplist, Redis le convertira en pratiquement paires de clés / valeurs habituelles sous un capot. (voir hash-max-ziplist-value, hash-max-ziplist-entries) Et briser sous un capot à partir d'une option de hachage EST VRAIMENT MAUVAIS, car chaque paire clé / valeur habituelle à l'intérieur de Redis utilise +90 octets par paire.
Cela signifie que si vous commencez avec l'option deux et sortez accidentellement de la valeur max-hash-ziplist, vous obtiendrez +90 octets par CHAQUE ATTRIBUT que vous avez dans le modèle utilisateur! (en fait pas le +90 mais le +70 voir la sortie console ci-dessous)
Pour la réponse de TheHippo, les commentaires sur la première option sont trompeurs:
hgetall / hmset / hmget à la rescousse si vous avez besoin de tous les champs ou de plusieurs opérations get / set.
Pour la réponse de BMiner.
La troisième option est en fait vraiment amusante, pour un ensemble de données avec max (id) <has-max-ziplist-value, cette solution a une complexité O (N), car, surprise, Reddis stocke les petits hachages comme un conteneur de type tableau de longueur / clé / valeur objets!
Mais ne vous inquiétez pas, vous casserez très rapidement les entrées de hachage-max-ziplist et vous voilà maintenant à la solution numéro 1.
La deuxième option ira très probablement à la quatrième solution sous un capot, car comme l'indique la question:
Et comme vous l'avez déjà dit: la quatrième solution est certainement le +70 octet le plus cher pour chaque attribut.
Ma suggestion pour optimiser un tel ensemble de données:
Vous avez deux options:
Si vous ne pouvez pas garantir la taille maximale de certains attributs utilisateur, optez pour la première solution et si la question de la mémoire est cruciale, compressez l'utilisateur json avant de le stocker dans redis.
Si vous pouvez forcer la taille maximale de tous les attributs. Ensuite, vous pouvez définir des entrées / valeur de hachage-max-ziplist et utiliser des hachages soit comme un hachage par représentation utilisateur OU comme optimisation de la mémoire de hachage à partir de cette rubrique d'un guide Redis: https://redis.io/topics/memory-optimization et stocker l'utilisateur sous forme de chaîne json. Dans tous les cas, vous pouvez également compresser de longs attributs utilisateur.
la source