【问题标题】:Redis hash usage as tableRedis 哈希表的使用情况
【发布时间】:2020-05-17 02:47:05
【问题描述】:

我想像 Nosql 数据库一样使用 redis,我有一些想法,如下所示。

假设我有 3 张桌子

1 - user
2 - post
3 - comment

我为每个表创建哈希,如下所示

hset user _usr_100 {"id":"_usr_100","name":"john","username"="jhn","age":25}
hset user _usr_101 {"id":"_usr_101","name":"adam","username"="adm","age":26}
hset user _usr_102 {"id":"_usr_102","name":"eric","username"="erc","age":27}

hset post _post_100 {"id":"_post_100","title":"title","content":"testpost","userid"="_usr_100"}
hset post _post_101 {"id":"_post_101","title":"title","content":"testpost","userid"="_usr_101"}
hset post _post_102 {"id":"_post_102","title":"title","content":"testpost","userid"="_usr_102"}

hset comment _comment_100 {"id":"_comment_100","content":"testpost","userid"="_usr_100","postid":"_post_100"}    
hset comment _comment_101 {"id":"_comment_101","content":"testpost","userid"="_usr_101","postid":"_post_101"}    
hset comment _comment_102 {"id":"_comment_102","content":"testpost","userid"="_usr_102","postid":"_post_102"}

当我想从 redis 中获取用户(_user_100)时

hget user _usr_100
{"id":"_usr_100","name":"john","username"="jhn","age":25}

当我想获得用户时

hgetall user
{"id":"_usr_100","name":"john","username"="jhn","age":25}
{"id":"_usr_101","name":"adam","username"="adm","age":26}
{"id":"_usr_102","name":"eric","username"="erc","age":27}

通过 pne 反序列化 json 字符串并将它们填充到 list 中,我有 List 所以我可以做一些操作(搜索、groupby、order、pagination ...),我可以为另一个哈希做同样的事情(post、comment )

我可以删除、更新用户;

hdel user _usr_101 // deleted _usr_101
hset user _usr_100 {"id":"_usr_100","name":"john","username"="jhn","age":26} //updated age
hset user _usr_103 {"id":"_usr_103","name":"max","username"="max","age":15} //new user

hgetall user
{"id":"_usr_100","name":"john","username"="jhn","age":26}
{"id":"_usr_102","name":"eric","username"="erc","age":27}
{"id":"_usr_103","name":"max","username"="max","age":15}

这种用法有什么缺点?您能否提出另一个关于哈希的想法,以使用 redis 之类的 nosql 表。

【问题讨论】:

    标签: hash redis


    【解决方案1】:

    根据您的业务规则/模型,此选项“可能”有效,但它可能不是您所在领域的最佳/接近最佳解决方案。在大多数需要 relational 域的情况下使用键/值存储会导致您做出权衡,这可能对您不利。

    当您的user 类有新字段并且需要查询这些字段时,您需要创建更多“空间”以减少“时间”。您不断对数据进行非规范化以实现单个查询。您将尝试在键/值存储世界中实现您的关系数据库。当你只需要用一个简单的语句更新你的用户 101 时;

    UPDATE users SET username = 'mynewusername' where id = 101;
    

    在您的情况下,您需要通过所有哈希/集/列表找到所有相关的键/字段,并更新它们以确保数据完整性。将age 保留为字段可能不是一个好主意,您将需要使用生日,或者如果您的企业需要获取今天生日的用户列表,那么您需要创建新密钥,复制大部分数据,迁移所有您现有的用户到那里只是为了得到今天的生日。最好记住这一点,您需要按日和月查询才能获得生日 - 这意味着您必须将用户保留在单独的集合中,例如 users:birthday:01:01users:birthday:02:05users:birthday:11:08 以获取它们。如果用户想要更新他们的生日(取决于业务),那么您需要在这些集合之间手动移动用户,同时也更新其他集合。

    向用户添加active/passive 将是另一个痛苦。我不确定您是否需要获取 all 用户,您可能需要对它们进行分页,并且在使用哈希时 - 这会很困难,您需要另一个排序集/列表来获得它。

    用户帖子的 cmets、用户的最后 25 cmets、帖子最多的用户的最近 cmets 或搜索用户的帖子等也是如此。你的产品经理会提出这个想法,让我们将tag 添加到每个帖子中,您需要将relate 添加到具有新数据结构的数据模型中。

    这些是relational 数据,最好保持它们的相关性。当您开始在非关系数据库中对数据进行建模时,所有 elasticity rdbms 提供给您将消失,并且在数据和应用层上都将替换为 complexity

    在这个问题上,单个 postgresql 可能比 redis 更好。 Redis 具有解决问题的出色功能,但用户/帖子/评论不是其中之一。

    这个post 也可以提供一些见解

    【讨论】:

    • 当我需要更新用户时,我需要再次设置 json 字符串,即使它是针对一个字段(即:用户名)。我在使用哈希之前存储了 json 值,例如(set usr_100 {"json of user"}) 但搜索、排序、分页很困难(几乎不可能),但使用哈希我可以获取所有用户并转换为列表,然后我可以使用列表操作完成所有操作。我完全同意你的想法。这种情况是不适合 redis,但我需要使用它,因为我不想去磁盘获取值。
    • @YusufKayikci 这主要取决于业务规模,例如 100 万或 1000 个用户。这就是我在答案中多次使用“业务”的原因:)。感谢您的回复,祝您好运
    猜你喜欢
    • 2012-07-02
    • 2021-07-09
    • 2011-10-08
    • 2016-10-04
    • 2012-06-20
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    相关资源
    最近更新 更多