【问题标题】:CQL design for SELECTs with no WHERE没有 WHERE 的 SELECT 的 CQL 设计
【发布时间】:2014-08-12 01:52:33
【问题描述】:

我们目前正在重写我们的点对点服务总线目录 (Zebus)。

我们有一个 Cassandra/Thrift 实现,必须对其进行改进以满足一些新的负载需求,因此使用 CQL 重写它似乎是正确的做法。

我们有两个 CF,一个用于存储 Peers,一个用于存储 Subscriptions,后者是最棘手的。

我们需要存储每个消息类型的路由键(绑定)列表,以及每个对等点的消息类型列表。我们还需要能够分别更新每种消息类型的路由列表(我们使用 Cassandra 的时间戳来处理潜在的竞争条件,因为我们有多个目录)。最后,我们需要能够在有人请求 Peers 状态时列出所有这些订阅。

最后一点是一个问题,因为它意味着运行SELECT * FROM "Subscriptions",这意味着列出来自多个节点的行(顺便说一句,CQL 如何允许您列出底层的 Cassandra 行?)而且速度很慢。

因此,我们最终为 CF 提供了以下架构,以将所有内容连续存储在同一 Cassandra 行的磁盘上,并具有出色的读取性能(我们知道这在平衡节点之间的数据方面非常糟糕)。

CREATE TABLE IF NOT EXISTS "DynamicSubscriptions" (
    "UselessKey" boolean,
    "PeerId" text,
    "MessageTypeId" text,   
    "SubscriptionBindings" blob,
    PRIMARY KEY("UselessKey", "PeerId", "MessageTypeId")
);

这很丑陋,但可以解决问题,每个人最终都在同一个“Thrift row”上,导致读取速度快如闪电。

所以我的问题如下:如果我希望我的数据在不受约束的 SELECT 期间非常快速地可查询,是否有一种漂亮方法可以使用 CQL 设计 CF?

(或者如果您认为我们的设计完全有缺陷,请随意说)。

【问题讨论】:

  • 我不确定我是否正确理解了您的数据模型 - 对于您想要存储消息类型列表的每个对等点以及您想要存储绑定列表的每个消息类型,对吗?特定消息类型的绑定列表是否为每个对等方独立定义?第二个问题——你想每次都选择所有数据吗?还是单个同行的数据?
  • 是的,我们希望为每个对等方独立地存储特定消息类型的不同绑定。关于检索,我们希望能够为特定对等点选择数据。

标签: database-design cassandra cql zebus nosql


【解决方案1】:

所以,据我正确理解,您应该创建这样的表: CREATE TABLE IF NOT EXISTS dynamic_subscriptions ( peer_id text, message_type text, bindings blob, PRIMARY KEY (peer_id, message_type) ); 它与您的非常相似,但主要区别在于主键定义。 主键的第一列是分区键,这意味着所有具有相同分区键的数据都将存储在同一个物理列族行中。其余的主键组件是集群列,用于区分和排序单个分区键中的数据。

换句话说,这种模式的优点是:

  • 对等数据均匀分布在集群中
  • 您可以高效地查询对等数据(消息类型、带有绑定的消息类型),因为它们是排序并存储在单个节点上的
  • 您可以在特定对等点的上下文中有效地查询单个消息类型
  • 您可以在特定对等点的上下文中有效地更新/删除选定消息类型的绑定

希望对你有所帮助。

【讨论】:

  • 不幸的是,这是我想出的第一个模式,但是没有 WHERE 约束的 SELECT * 的性能是不可接受的,因此我的设计“丑化”了。
  • 但是,正如您所说,您要为特定对等方检索数据,不是吗?
  • 对不起,我不是很清楚,我的意思是我需要两个,一个给定的 Peer 和所有的。
  • 好的,所以当你要求所有这些时,你需要一次得到所有这些,还是你可以做一些分页?
  • 嗯,越快越好。分页是指手动执行多个查询还是使用 C* 2.0 分页?
【解决方案2】:

通常会有一种方法来限制由用户交互驱动的要阅读的信息。这也将推动您的数据模型设计。

我能想到的一种限制您列出订阅的对等点数量的方法是基于时间段。请注意,这需要是一个单独的 CF,与您查询以获取每个对等点信息的 CF 不同。黄金法则是一个 CF 驱动一个查询。

假设您可以按时间限制向用户显示的对等点的数量,下一个要解决的问题是将数据分布在多个分区(Thrift 行)中。您可以使用 MessageType 和时间组件(如 day)的组合作为分区键。当您向用户显示这些数据时,您就有了一种自然的分页机制。

总而言之,您将需要 Jacek L 提到的 CF。此外,要显示多个同行的信息,您可以使用类似这样的内容

CREATE TABLE IF NOT EXISTS peer_subscriptions (
    message_type   text,
    connection_date  text,
    peer_id   text,
    bindings  blob,
    PRIMARY KEY ((message_type,connection_date),peer_id)
);

【讨论】:

    猜你喜欢
    • 2014-12-05
    • 2012-11-17
    • 2015-05-05
    • 2020-02-08
    • 1970-01-01
    • 2018-09-19
    • 2014-06-17
    • 1970-01-01
    • 2013-07-15
    相关资源
    最近更新 更多