一个业务系统网站每天人数的访问量是多少,在线人数是多少?这种业务我们在开发中就要预留,也是在我们的设计范围内的咯!因为一个正在运营的网站,每天都会用到统计。

那在线人数是如何统计的呢,这里有几种方案,代码用laravel框架。可以作为开发中参考。

1 用表统计方式

用数据表统计在线人数,这种方式只能用在并发量不大的情况下。

首先我们先新建表:user_login

user_login表

模拟用户登录,不存在用户就存入表,存在的则更新登录信息

// 客户端唯一的识别码
$client_id = session()->getId();//用户是否已存在
$user = DB::table('user_login')->where('token', $client_id)->first();//不存在则插入数据
if (empty($user)) {$data = ['token' => $client_id,'username' => 'user_' . $client_id, // 模拟用户'uid' => mt_rand(10000000, 99999999),   //模拟用户id'create_time' => date('Y-m-d H:i:s'),'update_time' => date('Y-m-d H:i:s')];DB::table('user_login')->insert($data);
} else {    // 存在则更新用户登录信息DB::table('user_login')->where('token', $client_id)->update(['update_time' => date('Y-m-d H:i:s')]);
}

这里还需要定期清理无任何操作的用户,假如用户一个小时内无任何操作,我们可以记为无效用户

代码如下:

// 客户端唯一的识别码
$client_id = session()->getId();//用户是否已存在
$user = DB::table('user_login')->where('token', $client_id)->first();//不存在则插入数据
if (empty($user)) {$data = ['token' => $client_id,'username' => 'user_' . $client_id, // 模拟用户'uid' => mt_rand(10000000, 99999999),   //模拟用户id'create_time' => date('Y-m-d H:i:s'),'update_time' => date('Y-m-d H:i:s')];DB::table('user_login')->insert($data);
} else {    // 存在则更新用户登录信息DB::table('user_login')->where('token', $client_id)->update(['update_time' => date('Y-m-d H:i:s')]);
}

我们可以实现的功能:

1)当前在线人数

2)某时间段内在线人数

3)最新上线的用户

4)指定用户是否在线

// 可实现功能一:当前总共在线人数
$c = DB::table('user_login')->count();
echo '当前在线人数:' . $c . '<br />';// 可实现功能二:某时间段内在线人数
$begin_date = '2020-08-13 09:00:00';
$end_date = '2020-08-13 18:00:00';$c = DB::table('user_login')->where('create_time', '>=', $begin_date)->where('create_time', '<=', $end_date)->count();
echo $begin_date . '-' . $end_date . '在线人数:' . $c . '<br />';// 可实现功能三:最新上线的用户
$newest = DB::table('user_login')->orderBy('create_time', 'DESC')->limit(10)->get();
echo '最新上线的用户有:';foreach ($newest as $value) {echo $value->username . ' ';
}
echo '<br />';// 可实现功能四:指定用户是否在线
$username = 'user_1111';
$online = DB::table('user_login')->where('username', $username)->exists();
echo $username . ($online ? '在线' : '不在线');

2 使用redis有序集合实现在线人数统计

因为是内存中,所以效率很高,可以统计某个时间段内的在线人数,可以做各种聚合操作。但是如果在线人数比较多的情况下,会比较占用内存。还有一点:

无法通过用户操作时间清除掉无效用户,只有手动登出的用户才会从集合中删除。

代码如下:

// 客户端唯一的识别码
$client_id = session()->getId();
echo $client_id . '<br />';// 按日期生成key
$day = date('Ymd');
$key = 'online:' . $day;// 是否在线
$is_online = Redis::zScore($key, $client_id);
if (empty($is_online)) {    // 不在线,加入当前客户端Redis::zAdd($key, time(), $client_id);
}// 可实现功能一:当前总共在线人数
$c = Redis::zCard($key);
echo '当前在线人数:' . $c . '<br />';// 可实现功能二:某时间段内在线人数
$begin_date = '2020-08-13 09:00:00';
$end_date = '2020-08-13 18:00:00';
$c = Redis::zCount($key, strtotime($begin_date), strtotime($end_date));
echo $begin_date . '-' . $end_date . '在线人数:' . $c . '<br />';// 可实现功能三:最新上线的用户,时间从小到大排序
$newest = Redis::zRangeByScore($key, '-inf', '+inf', ['limit' => [0, 50]]);
echo '最新上线的用户有:';
foreach ($newest as $value) {echo $value . ' ';
}
echo '<br />';// 可实现功能四:指定用户是否在线
$username = $client_id;
$online = Redis::zScore($key, $client_id);;
echo $username . ($online ? '在线' : '不在线') . '<br />';// 可实现功能五:昨天和今天都上线的客户
$yestoday = Carbon::yesterday()->toDateString();
$yes_key = str_replace('-', '', $yestoday);
$members = [];
Redis::pipeline(function ($pipe) use ($key, $yes_key, &$members) {Redis::zinterstore('new_key', [$key, $yes_key], ['aggregate' => 'min']);$members = Redis::zRangeByScore('new_key', '-inf', '+inf', ['limit' => [0, 50]]);//dump($members);
});echo '昨天和今天都上线的用户有:';
foreach ($members as $value) {echo $value . ' ';
}

3 使用hyperloglog做统计

跟有序集合方式不同,hyperloglog十分节约空间,但是实现的功能也非常单一,只能统计在线人数,不能实现其余的任何功能。

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

// note HyperLogLog 只需要知道在线总人数
for ($i=0; $i < 6; $i++) {$online_user_num = mt_rand(10000000, 99999999);     //模拟在线人数var_dump($online_user_num);for ($j=1; $j < $online_user_num; $j++) { $user_id = mt_rand(1, 100000000);$redis->pfadd('002|online_users_day_'.$i, [$user_id]);}
}$count = 0;
for ($i=0; $i < 3; $i++) { $count += $redis->pfcount('002|online_users_day_'.$i);print_r($redis->pfcount('002|online_users_day_'.$i). "\n");
}
var_dump($count);//note  3 days total online num
var_dump($redis->pfmerge('002|online_users_day_both_3', ['002|online_users_day_0', '002|online_users_day_1', '002|online_users_day_2']));
var_dump($redis->pfcount('002|online_users_day_both_3'));

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

4 使用bitmap统计

bitmap就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。

bitmap常用来做比如用户签到、活跃用户、在线用户等功能。

代码如下

// 模拟当前用户
$uid = request('uid');$key = 'online_bitmap_' . date('Ymd');// 设置当前用户在线
Redis::setBit($key, $uid, 1);// 可实现功能1:在线人数
$c = Redis::bitCount($key);
echo '在线人数:' . $c . '<br />';// 可实现功能2:指定用户是否在线
$online = Redis::getBit($key, $uid);
echo $uid . ($online ? '在线' : '不在线') . '<br />';// 可实现功能3:昨天和今天均上线的用户总数
$yestoday = Carbon::yesterday()->toDateString();
$yes_key = str_replace('-', '', $yestoday);
$c = 0;
Redis::pipeline(function ($pipe) use ($key, $yes_key, &$c) {Redis::bitOp('AND', 'yest', $key, $yes_key);$c = Redis::bitCount('yest');
});
echo '昨天和今天都上线的用户数量有:' . $c . '<br />';

bitmap消耗的内存空间不多, 统计的信息却挺多的,这种方案是值得推荐一下的。

[精选] 统计在线人数,用php 如何来实现 ?相关推荐

  1. 利用php比较精确的统计在线人数的办法

    利用php比较精确的统计在线人数的办法,注意这里所说的精确是指个数,如果需要精确在时间上,则需要根据实际情况调整代码中的有效时间.(自己没有写,从别人那拿过来的,先放着然后再研究) <?php/ ...

  2. session监听器统计在线人数存入数值后不能取出其值

    session监听器统计在线人数存入数值后不能取出其值 首先这是一个在线统计人数的需求,给大家看看我的代码 监听器的类: import javax.servlet.annotation.WebList ...

  3. php 固定人数拼手气_独立统计在线人数和访问数代码分享(php)

    代码有2张,和一个sql 1.conn_count.php < ?php $host="localhost"; //请在双引号内填写你的mysql数据库主机 $root=&q ...

  4. servlet监听完成统计在线人数,显示在线人员列表(附源码)

    ServletContext事件监听器---->针对applicationScope ServletContextListener(*) 对整个Web应用的装载和卸载进行监听. ServletC ...

  5. php自动计数,PHP 实现精确统计在线人数功能

    有需要学习交流的友人请加入交流群的咱们一起,有问题一起交流,一起进步!前提是你是学技术的.感谢阅读! PHP对session对象的封装的很好,根据HTTP协议,每个范围网站的访客都可以生成一个唯一的标 ...

  6. [asp]统计在线人数情况

    [asp]统计在线人数情况 以前ASP版本的统计在线.因为是从以前的系统中提取出来的.使用的话要修改下. If Cbool(Application("MARKONLINE")) = ...

  7. php 怎么从memcache缓存数据中统计某一字段总数,php和memcache统计在线人数的方法...

    $mc = new Memcache (); // 连接memcache $mc->connect("127.0.0.1", 11211); // 获取 在线用户 IP 和  ...

  8. java程序利用HttpSessionListener实现统计在线人数(示例代码)

    HttpSessionListener是个session监听器,它有两个方法:publicvoidsessionCreated(HttpSessionEventevent){}和publicvoids ...

  9. PHP 实现精确统计在线人数功能

    PHP对session对象的封装的很好,根据HTTP协议,每个范围网站的访客都可以生成一个唯一的标识符 这个就是统计在线人数的关键所在,只有有这个session_id 也就可以区分访问的人了.因为每一 ...

最新文章

  1. 中国消费者信息指数影响因素分析
  2. Python之pandas:数据类型变换之object、category、bool、int32、int64、float64以及数据类型标准化之详细攻略
  3. Lisenter笔记
  4. 【Python】Matplotlib绘制可爱机器人
  5. STL(四)——map映射
  6. TikZ绘图示例——尺规作图: 圆内接任意正边形的近似画法(以正七边形为例)
  7. 蔚来用户累计行驶里程超30亿
  8. 闲谈: 测试报告的插入图片
  9. hp服务器系统如何用u盘恢复,软硬件技巧 篇三:HP战66之恢复U盘制作,以及恢复系统之体验感想...
  10. Javascript实现图片幻灯片
  11. 学习阶段小测,简单的幸运抽奖系统
  12. 如何使用 CSS 使表格居中(快速指南)
  13. 你好Haskell (1) 环境搭建和简单玩玩
  14. 当自动驾驶驶入虚拟现实——苹果的沉浸式自动驾驶系统
  15. 关于Mysql8.0时区表问题解决
  16. 鸿蒙系统的理解,我所理解的鸿蒙系统
  17. 【JavaEE基础与高级 第42章】C3P0连接数据库操作顺序
  18. 微服务 杜家豪_将“厕所革命”进行到底
  19. 基于SmartThreadPool线程池技术实现多任务批量处理
  20. Tensorflow变量作用域及变量初始化

热门文章

  1. 电机控制书籍复习--高性能变频调速及其典型控制系统-马小亮
  2. 魏小亮:参加编程竞赛对实际工作的用处
  3. 求圆形矩形面积java_Java求矩形面积和圆形面积的异常处理实例
  4. Java多态(面试考点,不要因为基础而忽视)
  5. 杰理之ANC电路设计注意事项【篇】
  6. jeecg-boot学习及调通步骤
  7. 内容提交的时一个图片,但是前端显示的时<img src=“地址“>而不是图片
  8. 我给鸿星尔克写了一个720°看鞋展厅
  9. JavaScript学习第二部-js的基础语法和语句
  10. 用计算机算出神奇的数,神奇的数字:12345679!先随便乘一个数字,最后乘9,奇迹出现了...