【问题标题】:Cassandra, storing various events about itemCassandra,存储有关项目的各种事件
【发布时间】:2012-12-02 12:24:10
【问题描述】:

我需要为上传的歌曲存储这些类型的事件:

  • 观看次数
  • 喜欢
  • 不喜欢
  • 评论
  • 收藏夹
  • 下载

可能还有更多。

为了存储有关歌曲本身的信息,我使用了宽行,其中列名是时间戳,值是 JSON 字符串,其中包含有关该歌曲的所有信息。

现在如果我只需要存储数字就不会有太大问题了,但我实际上需要存储说喜欢那首歌的用户的信息。

因此,如果有 1000 位用户喜欢某首歌曲,那么将所有这些信息放在一个列中可能是个坏主意。

所以我可能做到这一点的唯一方法就是将该信息存储在不同的 CF 中。

但我不确定如何将歌曲本身与分散在不同列中的所有信息“连接”起来?

所以我的问题是,我是否朝着正确的方向前进?如果是,我将如何存储所有这些动作并将它们连接在一起。

编辑

我正在尝试建立喜欢系统,但它几乎失控了,这些是我需要执行的操作才能喜欢/不喜欢

  1. 检查用户是否已经喜欢该项目
  2. 检查用户之前是否不喜欢该项目
  3. 如果他不喜欢,则删除该条目
  4. 现在获取当前的喜欢
  5. 现在更新项目本身,设置新的喜欢计数
  6. 更新CF,其中包含所有喜欢该项目的用户

实际上我需要运行更多查询,所以我总共得到了将近 6 个查询,甚至更多是正常的吗?

【问题讨论】:

    标签: cassandra data-modeling


    【解决方案1】:

    了解您需要查询的内容是规划 Cassandra 架构时最重要的考虑因素之一。 Cassandra 旨在处理大量写入。

    根据您要实现的其他功能,您可能需要创建额外的列族或完全替换这些列族,以便以最适合 cassandra 查询的方式存储数据。

    此外,我建议尽可能多地将数据本地存储在 cassandra 中。我不会将 JSON 对象加载到胖字符串列中。最起码在cassandra中直接存储相关数据,比如点赞值等。

    您有两个域模型,用户和歌曲,以及要存储的三类数据:

    1. 评论
    2. 喜欢/不喜欢/收藏夹
    3. 查看次数/下载次数

    您详细说明了更新算法所需的一些功能查询:

    1. 检查用户是否已经喜欢该项目
    2. 检查用户之前是否不喜欢该项目
    3. 如果他不喜欢,则删除该条目
    4. 现在获取当前的喜欢
    5. 现在更新项目本身,设置新的喜欢计数
      • 使用 cassandra 计数器,这两个步骤可以同时发生
    6. 更新包含所有喜欢该项目的用户的 CF

    可以满足这些查询要求的架构如下。

    首先,我们将为 User 和 Song 定义 CF,两者都使用 UUID 作为键。

    create column family users with comparator=UTF8Type
       and column_metadata=[{column_name: user_name, validation_class: UTF8Type, index_type: KEYS},
       {column_name: json_data, validation_class: UTF8Type}];
    
    create column family songs with comparator=UTF8Type
       and column_metadata=[{column_name: user_name, validation_class: UTF8Type, index_type: KEYS},
          {column_name: json_data, validation_class: UTF8Type}];
    

    二级索引有助于按用户名检索用户行。有关性能方面的考虑,请参阅 this


    评论可以使用 UUID 为每个评论建模,如下所示:

    create column family comments with comparator = 'UTF8Type' 
       and column_metadata=[{column_name: user, validation_class: UUIDType, index_type: KEYS},
          {column_name: song, validation_class: UUIDType, index_type: KEYS},
          {column_name: timestamp, validation_class: DateType},
          {column_name: comment, validation_class: UTF8Type}];
    

    由于用户喜欢和不喜欢是互斥的,我们可以使用一个列族来存储用户所有的歌曲喜欢/不喜欢。如果您将“收藏”限制为暗示喜欢,我们可以只用这个来完成所有三个。使用用户的UUID作为行键,歌曲的UUID作为列键,列值为0 => 无值,1 => 不喜欢,2 => 喜欢,3 => 喜欢。

    create column family user_likes with comparator = 'UUIDType'
       and default_validation_class = IntegerType;
    

    现在剩下的就是跟踪每首歌曲的总喜欢、不喜欢、收藏、观看和下载。我们可以使用Cassandra's counter column 类型在一个 CF 中完成此操作。使用歌曲的 UUID 作为 CF 键。

    create column family song_data with default_validation_class=CounterColumnType
       and column_metadata=[{column_name: likes},
          {column_name: dislikes},
          {column_name: favorites},
          {column_name: views},
          {column_name: downloads}];
    

    【讨论】:

    • 谢谢,这很有用,我已经以不同的方式做到了,但我会看看可以改进的地方。
    【解决方案2】:

    为“User、Song、Song_Likes、User_Likes、Song_Dislike、User_Dislike”创建不同的列族,使用songId(UUID)和UserId(UUID)在列族之间建立like。

    CF
     User: KS {userId} -> {{user}, {JSON user Info}}
     Song: KS {songId} -> {{song}, {JSON song Info}}
    
     Song_Comments: {songId -> {(Reversed)timestamp, userUUID:UserName:comment}}
      Reveresed Time stamp can help you to get latest N comments quickly.
    
     Song_Likes: {songId -> {timeStamp, userUUID}}
       (or if time of event is not important.)
     Song_Likes: {songId -> {userUUID, column Data {....} }
    
     similarly for other Column Families.
    

    下面的赞可能对你有帮助。 http://www.rackspace.com/blog/cassandra-by-example/

    【讨论】:

      【解决方案3】:

      在 casandra 中,您无法执行连接,因此您必须改为对数据进行非规范化。所以这个想法是将实体和关系保持在单独的列族中。还要记住 cassandra 确实有超级列,当你想深入一层时,这非常有用,所以你有所有在一起。也不要错过 cassandra 的限制 - 取决于您使用的版本。

      【讨论】:

        猜你喜欢
        • 2021-12-24
        • 1970-01-01
        • 2019-11-02
        • 2011-05-06
        • 2018-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        相关资源
        最近更新 更多