7亿注册用户,日活超1亿,怎么实时统计实时在线用户数?
关键是省成本、省内存,如果用set存用户Id,一个ID就占用64个字节,1亿用户要占6个多G,7亿用户ID=50G,别说实时统计,光存数据就能把Redis实例搞崩了,标准解法:Redis Bitmap 位图,用一个比特位,来代表用户的在线状态,在线标1,离线标0,把内存压缩到极致,7亿个用户占用7亿个比特位,除以8换算成字节,也就是8750W字节,算下来也就是83兆,连set的零头都没有,一台普通redis实例就能轻松抗住,操作性拉满,用户上线,用setbit把对应的位置上来,去set一下,下线就置位0,查单个用户状态,getbit统计在线人数,直接调用,bitcount,所有操作都是O(1)的复杂度亿级的数据架,毫秒级的返回,完全满足实时统计的要求,落地优化思路,可以按照大区或者按照服务器拆分位图做分片,避免单个key过大成为热点,位图还可以配合bitop位运算,轻松算出日活周活。
总结:针对亿级的用户,在线的统计的场景,我会采用Redis Bitmap位图方案来实现,核心思路呢,就是用单个比特位,映射一个用户的在线状态,以用户id作为位图的偏移量,在线置1,离线置0,极致压缩内存,开销,7亿的用户,也就差不多占用83兆的一个空间,效率远高于Set,在操作层面,通过SetBit更新用户的状态,GetBit查询用户状态,BITCOUNT命令毫秒级,统计在线人数,所有操作都是O(1)的,复杂度完全满足实时性的要求,还可以按照业务分区来做位图的分片,避免单体过热,同时可以通过BITOP来位运算,或者日活连续活跃等统计场景,复杂度极强,复用性极强。
demo:https://www.cnblogs.com/huangwentian/p/22994552
AI总结:
一、场景痛点:亿级在线统计的内存瓶颈
亿级用户规模下,用 Redis Set 存储在线用户 ID 会面临极高的内存成本:单个用户 ID 约占 64 字节,1 亿用户就需要 6GB + 内存,7 亿用户则超过 50GB。仅存储在线状态就会耗尽 Redis 实例内存,更无法支撑实时统计查询,成本完全不可控。
二、标准方案:Redis Bitmap 位图方案
核心原理
用1 个比特(bit)位映射一个用户的在线状态,以用户 ID 作为位图的偏移量(offset):
- 用户上线:对应偏移位置为 1
- 用户下线:对应偏移位置为 0
本质是用二进制位做状态标记,将内存压缩到极致。
内存开销对比(精准测算)
Bitmap 的内存占用仅由最大用户 ID 决定,和在线人数无关:
- 7 亿用户规模:700,000,000 bit ÷ 8 ÷ 1024 ÷ 1024 ≈ 83.45 MB
仅为 Set 方案的 1/600 左右,一台普通 Redis 实例即可轻松承载,成本优势极其显著。
三、核心操作与性能
- 状态读写:O (1) 复杂度
- 更新用户状态:
SETBIT key offset value
用户上线 / 下线直接定位偏移量修改,纯寻址操作,O (1) 耗时。 - 查询单个用户状态:
GETBIT key offset
直接定位偏移量返回结果,毫秒级响应。
- 更新用户状态:
- 实时统计:内存级批量计算
用BITCOUNT key统计在线总人数,按字节批量计算值为 1 的位数量。虽然时间复杂度为 O (N)(N 为位图字节数),但纯内存操作性能极高,80MB 级的位图统计仅需毫秒级,完全满足亿级数据的实时统计要求。
四、生产落地优化
- 位图分片,避免大 Key 热点
按大区、业务线、服务器维度拆分多个位图(比如online:region:1、online:region:2),避免单个 Bitmap 体积过大成为热点 Key,同时分散读写压力。 - 适用前提说明
要求用户 ID 为整数型、可映射为连续偏移量;若用户 ID 为字符串或非连续,需先增加一层「用户 ID → 偏移量」的映射。
五、扩展能力:位运算赋能多维统计
Bitmap 天然支持 BITOP 位运算命令,可以低成本扩展更多业务统计场景,复用性极强:
- 日活统计:当天各小时的位图做「或运算」,快速得到全天活跃用户
- 周活 / 月活:多天位图做「或运算」,得到周期内的活跃用户
- 用户留存:两天位图做「与运算」,得到连续活跃的留存用户
所有统计均为内存位运算,性能远高于数据库聚合查询。
总结
针对亿级用户在线状态统计场景,Redis Bitmap 是最优的成本方案:核心是用单个比特位映射用户状态,实现极致的内存压缩;核心读写操作为 O (1) 复杂度,统计操作毫秒级返回,满足实时性要求;支持分片水平扩展,还可通过位运算快速实现日活、留存等多维统计,兼具成本、性能和扩展性。

浙公网安备 33010602011771号