【问题标题】:Cassandra chat app: sorting rooms after last message insertedCassandra 聊天应用程序:插入最后一条消息后对房间进行排序
【发布时间】:2021-10-17 12:36:57
【问题描述】:

对于消息传递应用程序,我的数据库结构相对于:

CREATE TABLE users(
    userid text,
    name text, 
    rooms list<text>
    ...
    PRIMARY KEY (userid)
);

CREATE TABLE rooms(
    roomid text,
    members list<text>,
    createdat bigint,
    lastmessage bigint,
    ...
    PRIMARY KEY (roomid, createdat)
);

CREATE TABLE messages(
    roomid text,
    bucket int,
    messageid bigint,
    authorid text,
    ...
    PRIMARY KEY ((hash, roomid), messageid)
);

客户端在启动时为给定用户请求所有房间。我希望在某个时候,用户将成为数百个频道的成员。所以我只想检索最后 X 个活动频道以减少流量。

目前房间存储了最后一个 messageid(包括时间戳的雪花),所以我可以在检索所有房间后进行排序。

仅从 cassandra 加载最后 X 个活动房间需要进行哪些更改? 我知道我需要以某种方式对结构进行非规范化,但我不知道如何。

提前致谢!

【问题讨论】:

    标签: cassandra cql cassandra-3.0 cql3


    【解决方案1】:

    创建另一个表

    CREATE TABLE user_active_channels (
       userid text,
       time bigint,
       room text,
       PRIMARY KEY (userid, time))
    WITH CLUSTERING ORDER BY (time DESC);
    

    每次用户加入房间时,将数据保存在此表中。 然后像这样查询:

    SELECT room FROM user_active_channels
     WHERE userid='The users Id' AND time > 0 limit 5;
    

    由于聚类列是时间,数据在分区上按降序排列,所以前5条记录将是时间最长的记录,因此是最新用户的活动房间,避免检索所有数据,您可以将查询限制为仅返回前 5 条记录。

    【讨论】:

    • 我对您的回答有些考虑。时间将是一个聚类键,对吗?所以我将无法更新该列,而是必须插入一个新行。只是为了澄清,当任何用户向房间发布新消息时,我会更新时间 col,因此会产生很多垃圾。即使在插入新行后删除旧行,我也会生成很多墓碑。您的方式仍然是 cassandra 的最佳做法,还是您会提出其他建议?谢谢!
    • @lehmo 正确,您需要为用户将执行的每个活动插入数据,实际上,您正在跟踪用户,这将导致大量数据。在设计系统时,您将决定需要做出的权衡。例如,为了减少数据,您可能会跟踪每一分钟,而不是每条消息。墓碑是另一个因素,您可以配置 gc_grace_seconds 或仅保留最近的数据并压缩较旧的数据。有很多方法可以解决这个问题。对于 Cassandra,排序和范围是标准,正如 Erick 所回答的那样。
    【解决方案2】:

    这看起来像是您在 #68782996 中的问题的变体,我建议为您的应用查询“给我所有房间给用户”创建此表:

    CREATE TABLE rooms_by_userid (
      ...
      PRIMARY KEY (userid, roomid)
    )
    

    根据您的描述,听起来应用查询是“给我一个用户最近的 10 个房间”。您还提到您正在使用messageid 确定最近的房间。在这种情况下,表格如下所示:

    CREATE TABLE rooms_by_userid_by_messageid (
       userid text,
       messageid bigint,
       roomid text,
       ...
       PRIMARY KEY (userid, messageid)
    ) WITH CLUSTERING ORDER BY (messageid DESC, roomid ASC)
    

    此表中的数据将按用户 ID 进行分区,并包含按消息 ID 以相反顺序(最近的在前)排序的行,其中每条消息都有一个关联的房间。您将使用LIMIT 10 检索最近的 10 个房间,如下所示:

    SELECT roomid FROM rooms_by_userid_by_messageid
      WHERE userid = ?
      AND messageid = ?
      LIMIT 10;
    

    这里的重点是数据已经按照您需要的顺序排序,因此当您从数据库中获取结果时,您不需要进行任何客户端排序。干杯!

    【讨论】:

    • 与 Rami Del Toro 解决方案相同的问题。 rooms_by_userid_by_messagid 中的 messageid 在此房间中的每条新消息上都会更新。所以序列看起来像“新消息->插入消息表->房间的每个成员更新房间_by_userid_by_messageid中的lastmessageid”。这意味着一条新消息会导致 MEMBERS 计时表中的新行。这不是很多垃圾吗?我应该如何处理旧的/多余的行?提前感谢拉米雷斯!
    • 嗯,问题是在 Cassandra 中,我们必须设计一个匹配每个查询的表,因为它不是 RDBMS——您选择 C* 是因为您需要互联网规模的超快速查询.如果您不需要旧条目,您当然可以对它们应用 TTL。干杯!
    猜你喜欢
    • 2019-05-10
    • 2014-03-10
    • 1970-01-01
    • 2021-03-06
    • 2021-02-27
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多