【问题标题】:How to model user event log in cassandra?如何在 cassandra 中建模用户事件日志?
【发布时间】:2017-01-24 01:08:36
【问题描述】:

我给定的用例相当简单:为给定用户存储事件,并允许在以后给定时间范围内为每个用户计算这些事件。

可能的事件数量相当少(

关键列是:

  • 用户名
  • 时间戳
  • 事件

目前我的模型看起来像此列将用作:

(username, (timestamp, event, uuid)) 

因此,用户名将是分区键,并且大多数查询可以通过仅查询一个节点来完成。一个非常常见的查询可能如下所示:

select * from user_events where username=? and timestamp>? and timestamp<? 

我进一步考虑使用计数器列而不是添加单独的 uuid 列,以防同一用户的同一事件在同一毫秒内发生。

因此,桌子也会变小。

如果有人能分享他/她对这个模型的想法,我将不胜感激。

更新

我创建了以下主表来存储用户事件

CREATE TABLE IF NOT EXISTS events.events_by_user(
        user text,
        added_week int,
        added_timestamp timestamp,
        event text,
        uuid uuid,
        PRIMARY KEY((user, added_week), added_timestamp, event))
    WITH CLUSTERING ORDER BY(added_timestamp DESC)

这很好用,我开始通过这样的查询来查询表:

SELECT event,added_timestamp FROM events_by_user WHERE user=? AND added_week=? AND added_timestamp>=? AND added_timestamp<?;

之后我创建了第二个查询来过滤特定事件:

SELECT event,added_timestamp FROM events_by_user WHERE user=? AND added_week=? AND added_timestamp>=? AND added_timestamp<? AND event IN ?;

这个虽然没有工作,因为我不允许在对时间戳执行 gte 和 lt 查询后添加一个包含以下消息的子句:

不能限制聚类列“事件”(前一列 "add_timestamp" 受非 EQ 关系限制)

【问题讨论】:

  • 这可能会导致宽行。
  • 我明白了,但是我怎样才能通过给定的要求呢?大多数查询包括用户名和给定的时间范围,但偶尔也会执行仅用户名的查询。

标签: database cassandra data-modeling


【解决方案1】:

您有两个相互冲突的要求:您想要执行以username 为中心的查询,但您不想要宽行...这里没有太多操作空间...

我会先解决宽行。您真的不想要宽行,它们只会杀死您(r 个节点)。因此,您需要找到与username 耦合的东西。据我所知,由于您的大多数查询都基于usernametimestamp,因此我会选择一个好的时间粒度来控制行的宽度。

你说

可能的事件数量非常少(

但是您没有指定事件数是否是每个用户,并且您没有指定插入频率是否适用于所有用户(我是假设他们从现在开始)。

据此,您预计每天有 8600 万个事件,这意味着每个用户平均有 8600 个事件。在我看来,这似乎是一个不错的粒度级别,所以我会以yyyy-mm-dd 的形式添加一个时间戳作为分区键:

CREATE TABLE myevents  (
    username text,
    day timestamp,
    timestamp timestamp,
    event int
    uuid uuid,
    ...
    PRIMARY KEY ((username, day), timestamp, event, uuid)
);

这使您可以完美地查询在特定日期属于特定用户的所有事件。如果您需要跨多天查询,那么您需要执行多个查询(每天一个),然后通过将第一天的结果与第二天的结果附加来重建应用程序中的结果,然后附加第三天……以此类推。我说追加是因为结果是按集群键 timestamp 排序的。

您可以通过更改day 值来选择最适合您需要的粒度级别。如果您希望小时粒度将格式更改为yyyy-mm-dd HH:00,这将允许您拥有更小的行,但您需要执行 24 次查询才能获取一天的数据。或者您可以选择执行为期两天的步骤,现在您的行数增加了一倍,但您将执行一半的查询。

现在一切都取决于您的需求和集群。鉴于 C* 的高可扩展性特性,我会使用更多查询和更小的行,即使这意味着在应用程序级别执行更多编码。它可以让你更好地扩展。

【讨论】:

  • 我基本上按照建议做了,但现在我遇到了需要在给定时间范围内查询特定事件的问题,但情况并非总是如此。当我尝试查询时,当我执行 y > ts >= x 并在 ? 中执行附加事件时出现异常。您是否建议为这种情况添加一个特殊的表?
  • 对不起,我不明白你要做什么。你能写下你的查询吗?
  • SELECT * FROM events_by_user WHERE user=? AND added_week=? AND added_timestamp&gt;=? AND added_timestamp&lt;? AND event IN ?; vs SELECT * FROM events_by_user WHERE user=? AND added_week=? AND added_timestamp&gt;=? AND added_timestamp&lt;?; 基本上,唯一的区别是一个查询还要求特定事件,而另一个查询则不流鼻涕。
  • @u6f6o:我明白了,您需要使用event = ? 执行多个SELECTs。即使交换 added_timestampevent 也是不行的,因为这会使您的第一个查询无效...
  • 我明白了,但这基本上意味着,我将在 cassandra 节点上一遍又一遍地执行相同的查找操作,唯一的区别是每次选择不同的事件。我还考虑过在不指定事件的情况下选择所有行并手动过滤,但后来我获取了太多行:-(
猜你喜欢
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 2012-09-08
  • 1970-01-01
相关资源
最近更新 更多