PHP Redis应用:如何实现在线用户数量统计方案对比?

更新于
2026-09-27 16:49:13
2阅读来源:SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计848个文字,预计阅读时间需要4分钟。

PHP Redis应用:如何实现在线用户数量统计方案对比?

在线人数系统业务是开发web应用时必须考虑的业务逻辑,本文将给出几种设计方案,并分析每个方案的优缺点:

1. 使用有序集合 - 优点:可同时存储在线用户和用户在线时间 - 缺点:查询性能可能受影响

PHP Redis应用:如何实现在线用户数量统计方案对比?

2. 使用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('000|online_users_day_'.$i, mt_rand($day_start_time, $day_end_time), $user_id); } }

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

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

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

【

标签:几种方案

本文共计848个文字,预计阅读时间需要4分钟。

PHP Redis应用:如何实现在线用户数量统计方案对比?

在线人数系统业务是开发web应用时必须考虑的业务逻辑,本文将给出几种设计方案,并分析每个方案的优缺点:

1. 使用有序集合 - 优点:可同时存储在线用户和用户在线时间 - 缺点:查询性能可能受影响

PHP Redis应用:如何实现在线用户数量统计方案对比?

2. 使用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('000|online_users_day_'.$i, mt_rand($day_start_time, $day_end_time), $user_id); } }

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

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

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

【

标签:几种方案