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)
# you need me-redis and awesome-print gems to run exact code
redis = Redis.include(MeRedis).configure( hash_max_ziplist_value: 64, hash_max_ziplist_entries: 512 ).new
=> #<Redis client v4.0.1 for redis://127.0.0.1:6379/0>
> redis.flushdb
=> "OK"
> ap redis.info(:memory)
{
"used_memory" => "529512",
**"used_memory_human" => "517.10K"**,
....
}
=> nil
# me_set( 't:i' ... ) same as hset( 't:i/512', i % 512 ... )
# txt is some english fictionary book around 56K length,
# so we just take some random 63-symbols string from it
> redis.pipelined{ 10000.times{ |i| redis.me_set( "t:#{i}", txt[rand(50000), 63] ) } }; :done
=> :done
> ap redis.info(:memory)
{
"used_memory" => "1251944",
**"used_memory_human" => "1.19M"**, # ~ 72b per key/value
.....
}
> redis.flushdb
=> "OK"
# setting **only one value** +1 byte per hash of 512 values equal to set them all +1 byte
> redis.pipelined{ 10000.times{ |i| redis.me_set( "t:#{i}", txt[rand(50000), i % 512 == 0 ? 65 : 63] ) } }; :done
> ap redis.info(:memory)
{
"used_memory" => "1876064",
"used_memory_human" => "1.79M", # ~ 134 bytes per pair
....
}
redis.pipelined{ 10000.times{ |i| redis.set( "t:#{i}", txt[rand(50000), 65] ) } };
ap redis.info(:memory)
{
"used_memory" => "2262312",
"used_memory_human" => "2.16M", #~155 byte per pair i.e. +90 bytes
....
}
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 souvent, les hachages ne contiennent que quelques champs. Lorsque les hachages sont petits, nous pouvons simplement les coder dans une structure de données O (N), comme un tableau linéaire avec des paires de valeurs de clé préfixées par la longueur. Puisque nous ne le faisons que lorsque N est petit, le temps amorti pour les commandes HGET et HSET est toujours O (1): le hachage sera converti en une véritable table de hachage dès que le nombre d'éléments qu'il contient augmentera trop
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:
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.
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.