在redis中存储用户配置文件有哪些更好的数据结构?

时间:2017-01-17 12:50:30

标签: json hash redis paging

我想将用户的个人资料存储在redis中,因为我必须经常阅读多个用户的个人资料。。我目前看到两种选择:

选项1: - 为每个用户的个人资料存储单独的哈希密钥

  • [hash] - u1个人资料{id:u1,姓名:user1,电子邮件:user1 @ domain.com,照片:url}
  • [hash] - u2个人资料{id:u2,姓名:user2,电子邮件:user2 @ domain.com,照片:网址}
  • 其中每个用户的id是散列键和配置文件字段以及值JSON序列化的配置文件对象。 (或者代替json用户字段 - 值对)

选项2: - 使用单个哈希键存储所有用户个人资料

  • [hash] - users-profile u1 {id:u1,name:user1,email:user1@domain.com,photo:url}
  • [hash] - users-profile u2 {id:u2,name:user2,email:user2 @ domain.com,photo:url}
  • 其中,在users-profile哈希键,用户的id字段和值JSON序列化的配置文件对象。

请告诉我哪个选项最好考虑以下内容:

  1. 性能
  2. 内存利用率
  3. 阅读多个用户的个人资料 - 对于批处理,我应该能够阅读1-100,101-200个用户的个人资料
  4. 较大的数据集 - 如果有数百万用户资料
  5. 会怎样

3 个答案:

答案 0 :(得分:2)

正如Sergio Tulentsev指出的那样,以任何方式将所有用户数据(特别是如果数据集很大的情况下)存储在单个哈希中都是不好的。

如果您按照本blog post的要求进行内存优化,则也不希望将用户数据存储为单独的密钥。

使用分页机制读取用户数据需要使用数据库而不是像redis这样的简单缓存系统。因此,建议为此使用NoSQL数据库,例如mongoDB。

但是每次从数据库中读取都是一项昂贵的操作,尤其是当您要读取大量记录时。

因此,最好的解决方案是在Redis中缓存最活跃的用户数据,以消除数据库获取开销。

我建议您调查walrus

基本上遵循以下模式:

@cache.cached(timeout=expiry_in_secs)
def function_name(param1, param2, ...., param_n):
    # perform database fetch
    # return user data

这可确保经常访问或请求的用户数据位于redis中,并且该函数自动从redis返回值,而不是进行数据库调用。另外,如果长时间不访问,密钥也会过期。

您将其设置如下:

from walrus import *
db = Database(host='localhost', port=6379, db=0)

主机可以在其中获取远程运行的redis集群的域名。

希望这会有所帮助。

答案 1 :(得分:1)

选项1。

  • 性能:通常取决于您的用例,但要说您想读取特定的用户(有关登录/注销,授权目的等)。使用选项#1,您只需计算用户哈希并获取用户配置文件。使用选项#2,您将需要获取所有用户个人资料并解析json (尽管您可以使其高效,但它永远不会像选项#1那样高效和简单);

  • 内存利用率:您可以使选项#1和选项#2在redis中具有相同的大小(在选项#1上,可以避免将哈希/用户ID存储为json的一部分) 。但是,并选择相同的示例来加载特定用户,您只需要在代码/内存中使用单个用户配置文件json,而不是使用一组用户配置文件的较大json

  • 读取多个用户的配置文件-对于批处理,我应该能够同时读取1-100、101-200个用户的配置文件:为此,就像通常使用关系数据库一样,您需要做分页。有are different ways of doing paging with redis,但是使用scan operation是迭代一组用户的简便方法

  • 更大的数据集-如果有数以百万计的用户个人资料
  

Redis is an in-memory but persistent on disk database, so it represents a different trade off where very high write and read speed is achieved with the limitation of data sets that can't be larger than memory

如果“没有更大的数据集”,则可以将Partitioning视为Redis FAQ suggests。在Redis常见问题上,您还可以检查其他指标,例如“单个Redis实例可以容纳的最大密钥数”或“ Redis内存占用量”

答案 2 :(得分:0)

选项1的PROS

(但不要使用哈希,请使用单键。例如SET profile:4d094f58c96767d7a0099d49 {...}

  • 迭代键比迭代哈希略快。 (这也是为什么您应该修改选项1以使用SET而不是HSET的原因)
  • 检索键值比检索哈希字段稍快

选项2的PROS

  • 您可以使用HMGET在一次通话中吸引所有用户,但前提是您的用户群不是很大。否则,服务器很难为您提供结果。
  • 您可以在一个命令中刷新所有用户。如果您有备份数据库,则很有用。

选项3的PROS

选项3是将您的用户数据分解为由用户ID的哈希决定的哈希桶。如果您有很多用户并且经常进行批处理,则效果很好。像这样:

HSET profiles:<bucket> <id> {json object}
HGET profiles:<bucket> <id>
HMGET profiles:<bucket> 

最后一个获取完整配置文件的文件。建议不要将其总计超过1mb。与顺序ID搭配使用时效果很好,而对于散列ID则效果不佳,因为它们可能会增长太多。如果您将它与哈希一起使用,并且它增长得太多,这会减慢您的Redis速度,则您可以回退到HSCAN(如option2中一样),或者使用新的哈希函数将对象重新分配给更多存储桶。

  • 更快地批量加载
  • 单个对象的存储/加载速度稍慢

如果您的情况正确,我的建议是使用第三个选项,其序号范围为100。如果您要获取大量数据,请从第一天开始计划群集。< / p>