目录
采取关注点名称+时间戳的方式,可以存储不同时间维度的活跃用户。
实时指标
Redis bitmap可用于快速、简单的实现实时指标。
传统情况下,由批量job生成指标数据。但是redis的bitmap支持实时指标计算,而且具有极高的空间利用率。例如1.28亿用户,实时统计日UV,仅仅占用16MB内存空间,在mbp上耗时50ms。
bitset
可视为由0和1组成的数组。在bitset中的每个bit可为0或1,使用offset表示bit在数组的位置。支持多个bitset间进行位操作,如与或非等。
群体统计
bitset的群体统计表示bitset中数据为1的bit数量。使用bitset做群体统计是非常高效的。如具有十亿bit的bitset,其90%空间已设置数据,在mbp上进行群体统计仅耗时几十或几百ms。
redis bitmap
bitmap是二进制数据,可通过set key offset val指令设置具体offset位置bit的数据,且时间复杂度为O(1)。
日活用户
针对关注点(某个页面或某个操作),统计活跃用户数量。
key规则:关注点名称+日时间戳
val:创建bitmap,宽度为当前用户数量,每个用户的id作为offset,这个用户ID是记录ID,不可能是由特定规则生成的userID。
当用户访问关注点时,针对具体bitset,将用户IDoffset位置数据设置为1。之后对该bitset进行群体统计,即为关注点的日活用户量。
采取关注点名称+时间戳的方式,可以存储不同时间维度的活跃用户。
如每小时播放音乐的用户量,key定义为play_yyyyMMddhh;每天播放音乐的用户量,key定义为play_yyyyMMdd。
当需要统计较大时间范围的用户量时,可以先对多个bitset求并集,然后再群体统计,如统计一周、一个月的用户量。
性能对比
1.28亿用户,使用bitset记录日活,使用日活并集统计7日 15日日活。
PERIOD TIME (MS)
Daily 50.2
Weekly 392.0
Monthly 1624.8
特性分析
周维度访问关注点且绑定手机号的唯一用户,采用绑定手机号用户bitset 交集 周维度访问关注点的用户bitset
最近n天唯一用户量的滚动统计,对最近n天每天的日活用户bitset求并集
涉及的指令
群体统计使用bitcount key
交集并集使用bitop and/or dest key1 keyn
对用户IDoffset设置数据使用setbit key offset 1
java bitset.cardinality()/and(bitset)/or(bitset)
局限性
使用bitset进行统计的确可以节省内存且高效,但是一个很大的局限性就是offset必须小于2^32
(4 294 967 296)。
为什么说是很大的局限性呢?
在系统设计阶段,会针对主要表的id制定生成规则,且非常可能最小id已经大于2^32。所以就很尴尬,在后续需求中,想使用bitset,但是观察id等唯一标识后,发现没法玩。
那么如何解决这种尴尬呢?
只能在系统设计阶段,考虑支持bitset场景。即主要表有两个唯一标识:ID 与 规则生成的唯一标识。
在系统逻辑中,使用规则生成的唯一标识。在数据库中,针对该唯一标识还要构建唯一索引。