首页   注册   登录
 huangz 最近的时间轴更新

huangz

V2EX 第 3333 号会员,加入于 2010-11-30 12:51:15 +08:00
huangz 最近回复了
2016-08-13 13:19:19 +08:00
回复了 Livid 创建的主题 Redis 关于用 Redis 做在线人数统计
Livid 的这个思路很有趣!

最近我也在研究这方面的问题,提供一些备选方案让大家参考。


方案 1 :使用有序集合
--------------------------------------

每当用户上线时,执行以下操作:

ZADD("online_users", <user_id>, <current_timestamp>)

想要知道有多少人在指定的时间区间(比如一天或者一周)内上线过,那么可以使用时间区间的起始时间戳和结束时间戳作为参数,调用 ZCOUNT 命令:

ZCOUNT("oneline_users", <start_timestamp>, <end_timestamp>)

判断用户的 session 是否过期可以通过以下方法:

user_online_timestamp = ZSCORE("online_users", <user_id>)
return (user_online_timestamp+SESSION_EXPIRETIME) < now()

其中 SESSION_EXPIRETIME 为 SESSION 的有效期秒数。

这个方案的优点是信息齐全,能够通过有序集合的特性方便地执行区间操作( O(logN)),也可以快速地获取指定用户的登录时间( O(1))。缺点是耗费的内存比较大,并且需要手动删除有序集合中已经过期的用户信息。


方案 2 :使用 HyperLogLog
--------------------------------------

用户上线:

PFADD("online_users", <user_id>)

获取在线人数:

PFCOUNT("online_users")

这个方案的优点是非常节约内存,无论网站的用户数量有多大,一个 HyperLogLog 都只消耗 12 KB 内存。当然,这个方案的缺点也非常明显:

1. 它无法获取用户的具体登录时间。
2. 因为 HyperLogLog 是一个概率算法,所以它无法准确地判断一个用户是否在线。

以上缺点都可以通过增加一个储存用户登录时间的 Hash 来解决,不过这一样一来,需要消耗的内存也会增加。


方案 3 :使用 bitmap
---------------------------------------

上线:

SETBIT("online_users", <user_id>, 1)

检查指定的用户是否上线:

GETBIT("online_users" <user_id>) == 1

统计在线人数:

BITCOUNT("online_users")

这个方案最有趣的地方,就是可以对多个 bitmap 执行聚合计算,从而计算出诸如“有多少个人连续一周都上线了(全勤)”、“这周一共上线了多少个人”、“有多少人今天上线了但是昨天没上线”等问题:

BITOP("AND", "one_week_both_online", "day_1_online", "day_2_online", ..., "day_7_online") # 计算一周都上线的人

BITOP("OR", "one_week_online_total", "day_1_online", ..., "day_7_online") # 计算这周一共有多少人上线

这个方案储存一个用户的在线信息只需要使用一个二进制位,对于用户数为 100 万的网站来说,使用这一方案只需要花费 125 KB 内存,而储存 1000 万的用户信息只需要花费 1.25 MB 。

虽然 bitmap 节约内存的效果不及 HyperLogLog ,但是使用 bitmap 可以准确地判断一个用户是否上线。对于想要尽量节约内存,但又需要准确地知道用户是否在线,又或者需要对用户的在线信息进行聚合计算的应用来说,这个方案是最佳之选。


结语
---------------------------------------

好的,关于统计在线用户的备选方案就介绍到这里,希望这些方案会给大家带来帮助和启发。

最后打个小广告,我正在写一本名为《 Redis 使用教程》的书,里面不仅对用户 SESSION 储存、用户在线统计等问题给出了详细的解法,还提供了实际可运行的 Python 代码,上面给出的一些方案在书中也有介绍,有兴趣的朋友可以关注一下: RedisGuide.com 非常感谢!

huangz
2016.8.13
2016-08-08 15:03:16 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@markme 谢谢支持。
2015-11-03 14:41:51 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@boboweb 谢谢支持!等电子版出了之后会第一时间发布消息的。
2015-11-03 11:16:12 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@ynztyl10 不客气,收到就好!
2015-11-03 11:15:35 +08:00
回复了 lijinma 创建的主题 Redis 感谢 huangz 送的《Redis 实战》
不客气,收到就好!
2015-10-20 19:57:44 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@ynztyl10 没关系,已经给你回邮件了。
2015-10-20 13:46:40 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@ynztyl10 hi ,在吗?你中奖了,请给我发邮件。
2015-10-19 17:01:24 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@lijinma OK 。
2015-10-19 12:40:33 +08:00
回复了 huangz 创建的主题 Redis 赠送几本即将出版的《Redis 实战》
@lijinma 你好,我收到了你一封邮件,并且已经回复了,是你本人吗?
关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2531 人在线   最高记录 3821   ·  
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.1 · 13ms · UTC 10:54 · PVG 18:54 · LAX 02:54 · JFK 05:54
♥ Do have faith in what you're doing.
沪ICP备16043287号-1