首页 后端开发 php教程 PHP+REDIS实践:统计在线人数的几种方案分析

PHP+REDIS实践:统计在线人数的几种方案分析

Mar 17, 2021 pm 05:24 PM
php redis

在线人数统计业务是我们开发web肯定要设计的业务逻辑,本文就会给出几种设计方案,来分析下各个方案的优缺点:

  • 使用有序集合

这种方案能够同时储存在线的用户 和 用户上线时间,能够执行非常多的聚合计算,但是所消耗的内存也是非常可观的。

  • 使用集合

这种方案能储存在线的用户,也能够执行一定的聚合计算,相对有序集合,所消耗的内存要小些,但是随着用户量的增多,消耗内存空间也处于增加状态

  • 使用hyperloglog

这种方案无论统计多少在线用户, 消耗的内存都是12k,但是只能给出在线用户的统计信息,无法获取准确的在线用户名单

  • 使用bitmap

这种方案还是比较好的,在尽可能节省内存空间情况下,记录在线用户的情况,而且能做一定的聚合运算

下面我们就用实际例子来说明:

                                                      

我们先以每天会有10w~30w的小量用户, 100w的用户群来说明下面的几种方案

方案一:使用有序集合

先生成用户在线记录数据:

$start_time = mktime(0, 0, 0, 9, 5);    //monday
for ($i=0; $i < 6; $i++) {
    $day_start_time  = $start_time + 86400 * $i;    //every day begin time
    $day_end_time =  $day_start_time + 86400;       //every day end time
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->zadd(&#39;000|online_users_day_&#39;.$i, mt_rand($day_start_time, $day_end_time), $user_id);
    }
}
登录后复制

好了记下来我们就来看看都能统计出哪些信息来吧

//note: 统计每天的在线总人数
for ($i=0; $i < 6; $i++) { 
    print_r($redis->zsize(&#39;000|online_users_day_&#39;.$i). "\n");
}
//note: 统计最近6天都在线的人数
var_dump($redis->zInter(&#39;000|online_users_day_both_6&#39;, 
    [
    &#39;000|online_users_day_0&#39;, 
    &#39;000|online_users_day_1&#39;, 
    &#39;000|online_users_day_2&#39;, 
    &#39;000|online_users_day_3&#39;, 
    &#39;000|online_users_day_4&#39;, 
    &#39;000|online_users_day_5&#39;
    ]
    ));
//note: 统计出近6天中共有多少上线
$redis->zunion(&#39;000|online_users_day_total_6&#39;, [&#39;000|online_users_day_0&#39;, &#39;000|online_users_day_1&#39;, &#39;000|online_users_day_2&#39;, &#39;000|online_users_day_3&#39;, &#39;000|online_users_day_4&#39;, &#39;000|online_users_day_5&#39;]);
//note: 统计某个时间段总共在线用户
print_r($redis->zcount(&#39;000|online_users_day_5&#39;, mktime(13, 0, 0, 9, 10), mktime(14, 0, 0, 9, 10)));
//note: 统计某个时间段在线用户名单
print_r($redis->zrangebyscore(&#39;000|online_users_day_5&#39;, mktime(13, 0, 0, 9, 10), mktime(14, 0, 0, 9, 10), 
    array(&#39;withscores&#39; => TRUE)));
登录后复制

不单单只有这些, 我们还能统计出早, 中, 午, 晚 等等时间段的用户在线情况,还有很多其他的,这就让我们发挥想象吧,是不是挺多的?只是确实也相当耗费内存空间

【推荐:PHP视频教程

方案二:使用集合

还是先来成用户在线记录数据:

//note set 一般聚合
for ($i=0; $i < 6; $i++) {
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->sadd(&#39;001|online_users_day_&#39;.$i, $user_id);
    }
}
登录后复制

好了记下来我们就来看看都能统计出哪些信息来吧

//note 判断某个用户是否在线
var_dump($redis->sIsMember(&#39;001|online_users_day_5&#39;, 100030));
//note 每天在线用户总量的统计
for ($i=0; $i < 6; $i++) { 
    print_r($redis->ssize(&#39;001|online_users_day_&#39;.$i). "\n");
}
//note 对不同时间段的在线用户名单进行聚合
print_r($redis->sInterStore(&#39;001|online_users_day_both_4and5&#39;, &#39;001|online_users_day_4&#39;, &#39;001|online_users_day_5&#39;). "\n");
//note 对指定的时间段的在线用户名单进行统计
print_r($redis->sUnionStore(&#39;001|online_users_day_total_4add5&#39;, &#39;001|online_users_day_4&#39;, &#39;001|online_users_day_5&#39;). "\n");
//note 哪天上线哪天没上线
print_r($redis->sDiffStore(&#39;001|online_users_day_diff_4jian5&#39;, &#39;001|online_users_day_4&#39;, &#39;001|online_users_day_5&#39;). "\n");
登录后复制

是不是也挺不错的,先不要着急, 我们接着往下看

方案三:使用hyperloglgo

先来成用户在线记录数据:

// note HyperLogLog 只需要知道在线总人数
for ($i=0; $i < 6; $i++) {
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    var_dump($online_user_num);
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->pfadd(&#39;002|online_users_day_&#39;.$i, [$user_id]);
    }
}
登录后复制

这种方案,我们来看看都能实现哪些业务呢

$count = 0;
for ($i=0; $i < 3; $i++) { 
    $count += $redis->pfcount(&#39;002|online_users_day_&#39;.$i);
    print_r($redis->pfcount(&#39;002|online_users_day_&#39;.$i). "\n");
}
var_dump($count);
//note  3 days total online num
var_dump($redis->pfmerge(&#39;002|online_users_day_both_3&#39;, [&#39;002|online_users_day_0&#39;, &#39;002|online_users_day_1&#39;, &#39;002|online_users_day_2&#39;]));
var_dump($redis->pfcount(&#39;002|online_users_day_both_3&#39;));
登录后复制

好少啊,是的, 这种方案仅仅只能统计出某个时间段在线人数的总量, 对在线用户的名单却无能为力,但是却挺节省内存的,对统计数据要求不多情况下 ,我们便可以考虑这种方案。

方案四:使用bitmap

笔者对这种方案其实挺喜欢的,消耗的内存空间不多, 统计的信息却挺多的,还是老步骤,先来生成数据:

//note bitmap 综合前面3个的优缺点
for ($i=0; $i < 6; $i++) {
    $online_user_num = mt_rand(100000, 300000);     //online user between 100000 and 300000 
    for ($j=1; $j < $online_user_num; $j++) { 
        $user_id = mt_rand(1, 1000000);
        $redis->setbit(&#39;003|online_users_day_&#39;.$i, $user_id, 1);
    }
}
登录后复制

接下来我们看看能满足的统计信息吧

//note userid today whether online 
var_dump($userid = mt_rand(1, 1000000));
var_dump($redis->getbit(&#39;003|online_users_day_5&#39;, $userid));
//note how many user is online
var_dump($redis->bitcount(&#39;003|online_users_day_5&#39;));
//note 6 days both online
var_dump($redis->bitop(&#39;AND&#39;, &#39;003|online_users_day_both_6&#39;, &#39;003|online_users_day_0&#39;, &#39;003|online_users_day_1&#39;, &#39;003|online_users_day_2&#39;, &#39;003|online_users_day_3&#39;, &#39;003|online_users_day_4&#39;, &#39;003|online_users_day_5&#39;));
var_dump($redis->bitcount(&#39;003|online_users_day_both_6&#39;));
//note 6 days total online
var_dump($redis->bitop(&#39;OR&#39;, &#39;003|online_users_day_total_6&#39;, &#39;003|online_users_day_0&#39;, &#39;003|online_users_day_1&#39;, &#39;003|online_users_day_2&#39;, &#39;003|online_users_day_3&#39;, &#39;003|online_users_day_4&#39;, &#39;003|online_users_day_5&#39;));
var_dump($redis->bitcount(&#39;003|online_users_day_total_6&#39;));
//note 6 days only one online
var_dump($redis->bitop(&#39;XOR&#39;, &#39;003|online_users_day_only_one_6&#39;, &#39;003|online_users_day_0&#39;, &#39;003|online_users_day_1&#39;, &#39;003|online_users_day_2&#39;, &#39;003|online_users_day_3&#39;, &#39;003|online_users_day_4&#39;, &#39;003|online_users_day_5&#39;));
var_dump($redis->bitcount(&#39;003|online_users_day_only_one_6&#39;));
登录后复制

怎么样?是不是集合能统计的 这家伙也能统计出来?而且消耗的内容还少。

对于这几种方案其实各有各的好处, 根据业务统计信息 来取相应的方案来实施吧,这样内存利用也就更合理了

以上是PHP+REDIS实践:统计在线人数的几种方案分析的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1657
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
PHP和Python:代码示例和比较 PHP和Python:代码示例和比较 Apr 15, 2025 am 12:07 AM

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

PHP的目的:构建动态网站 PHP的目的:构建动态网站 Apr 15, 2025 am 12:18 AM

PHP用于构建动态网站,其核心功能包括:1.生成动态内容,通过与数据库对接实时生成网页;2.处理用户交互和表单提交,验证输入并响应操作;3.管理会话和用户认证,提供个性化体验;4.优化性能和遵循最佳实践,提升网站效率和安全性。

PHP和Python:解释了不同的范例 PHP和Python:解释了不同的范例 Apr 18, 2025 am 12:26 AM

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

PHP:处理数据库和服务器端逻辑 PHP:处理数据库和服务器端逻辑 Apr 15, 2025 am 12:15 AM

PHP在数据库操作和服务器端逻辑处理中使用MySQLi和PDO扩展进行数据库交互,并通过会话管理等功能处理服务器端逻辑。1)使用MySQLi或PDO连接数据库,执行SQL查询。2)通过会话管理等功能处理HTTP请求和用户状态。3)使用事务确保数据库操作的原子性。4)防止SQL注入,使用异常处理和关闭连接来调试。5)通过索引和缓存优化性能,编写可读性高的代码并进行错误处理。

在PHP和Python之间进行选择:指南 在PHP和Python之间进行选择:指南 Apr 18, 2025 am 12:24 AM

PHP适合网页开发和快速原型开发,Python适用于数据科学和机器学习。1.PHP用于动态网页开发,语法简单,适合快速开发。2.Python语法简洁,适用于多领域,库生态系统强大。

为什么要使用PHP?解释的优点和好处 为什么要使用PHP?解释的优点和好处 Apr 16, 2025 am 12:16 AM

PHP的核心优势包括易于学习、强大的web开发支持、丰富的库和框架、高性能和可扩展性、跨平台兼容性以及成本效益高。1)易于学习和使用,适合初学者;2)与web服务器集成好,支持多种数据库;3)拥有如Laravel等强大框架;4)通过优化可实现高性能;5)支持多种操作系统;6)开源,降低开发成本。

PHP和Python:深入了解他们的历史 PHP和Python:深入了解他们的历史 Apr 18, 2025 am 12:25 AM

PHP起源于1994年,由RasmusLerdorf开发,最初用于跟踪网站访问者,逐渐演变为服务器端脚本语言,广泛应用于网页开发。Python由GuidovanRossum于1980年代末开发,1991年首次发布,强调代码可读性和简洁性,适用于科学计算、数据分析等领域。

PHP的影响:网络开发及以后 PHP的影响:网络开发及以后 Apr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

See all articles