用于编写和查询每月活动用户(MAU)和每日活动用户(DAU)的模式?

时间:2016-03-21 19:27:33

标签: cassandra

我在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更合适?谢谢!

1 个答案:

答案 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)

不确定这是否正是您所期待的,但我希望这个想法可以引导您朝着正确的方向前进。