我在Cassandra中使用两个单独的表来跟踪MAU和DAU的情况。每个表的设计都是一样的:
create table log.MAU(d timestamp, userId varchar, primary key (d, userId));
每次用户登录或恢复会话时,我都会插入到表中。对于时间戳,我使用相应的UTC"零小时" (例如DAU当天的UTC午夜,以及MAU当月第一天的UTC午夜)。
我当前设计的好处是简单性(例如select count(*) from DAU where d = ?
)和大小(如果用户处于活动状态,则每天/每月只保留一条记录)。
然而,缺点是我无法进行滚动期(例如过去24小时内的活跃用户),而且我也无法按每天或每月的每个小时跟踪活动(虽然我有其他cassandra日志,如果我添加了必要的二级索引,我可能会争吵。)
考虑到我提到的具体缺点或者我没考虑过的具体缺点,我是否可以更好地跟踪DAU和MAU?也许像postgres这样的另一个DB更合适?谢谢!
答案 0 :(得分:2)
我认为你可以通过键入另一个不太精确的日期列来解决这个问题。
对于每月用户,这样的事情会起作用:
CREATE TABLE mau(
month bigint,
d timestamp,
userid text,
PRIMARY KEY (month,d,userId));
然后您可以查询特定月份:
SELECT d, userid FROM may WHERE month=201603;
您还可以查询范围内的范围:
SELECT d, userid FROM mau WHERE month=201603
AND d>'2016-03-21 19:40:00+0000' AND d<'2016-03-21 19:50:00+0000';
d | userid
--------------------------+--------
2016-03-21 19:40:13+0000 | tron
2016-03-21 19:40:20+0000 | yori
2016-03-21 19:40:28+0000 | quorra
2016-03-21 19:40:36+0000 | paige
(4 rows)
month
是否适合您,取决于您预计每月会达到多少行,以及这将使您接近Cassandra每个分区20亿个单元格的限制。请记住,按day
进行分区可能是个好主意,如下所示:
CREATE TABLE mau(
month bigint,
day bigint,
d timestamp,
userid text,
PRIMARY KEY ((month,day),d,userId));
当然,您将无法一次查询整个月份。但是搞乱这种方法,看看你是否能找到适用于你的应用程序的PRIMARY KEY策略。
编辑20160323
因此,为了统计“唯一”登录,我需要做一个“select count(*)distinct userId”或者其他一些。我对Cassandra不太熟悉,但我知道它适用于分区键。假设此模式中的分区键是三列(month,d,userId)的组合,那么userId上是否允许单独计数?
不,count
将无法通过iteslf在userid上运行。首先,您不能跳过PRIMARY KEY组件。其次,使用Cassandra,您需要采用基于查询的建模方法。如果您需要查询已登录的不同用户ID,那么您需要新建一个表来支持它。
CREATE TABLE logins_by_user (
userid text,
d timestamp,
PRIMARY KEY(userid,d))
WITH CLUSTERING ORDER BY (d DESC);
假设我有与上面相同的数据,但用户“tron”第二次登录:
SELECT * FROM logins_by_user ;
userid | d
--------+--------------------------
quorra | 2016-03-21 19:40:28+0000
paige | 2016-03-21 19:40:36+0000
tron | 2016-03-22 19:37:53+0000
tron | 2016-03-21 19:40:13+0000
yori | 2016-03-21 19:40:20+0000
(5 rows)
查询唯一的用户ID会产生:
SELECT DISTINCT userid FROM logins_by_user ;
userid
--------
quorra
paige
tron
yori
(4 rows)
不确定这是否正是您所期待的,但我希望这个想法可以引导您朝着正确的方向前进。