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 numvar_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. python输入字符串并反序result_python字符串反转的四种方法详解

    python字符串反转的四种方法详解 这篇文章主要介绍了python字符串反转的四种详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.用red ...

  2. php 去重_php求两数组交集的四种方法详解

    题目:给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1],nums2 = [2,2] 输出: [2] 示例 2: 输入: nums1 = [4,9,5 ...

  3. 字符串反转python_python字符串反转的四种方法详解

    这篇文章主要介绍了python字符串反转的四种详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.用reduce函数方法 book = 'Pyt ...

  4. 批量 杀掉 mysql 连接_批量杀死MySQL连接的四种方法详解

    方法一 通过information_schema.processlist表中的连接信息生成需要处理掉的MySQL连接的语句临时文件,然后执行临时文件中生成的指令.复制代码 代码如下:mysql> ...

  5. Request获取表单数据的四种方法详解

    表单代码 <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/html" ...

  6. 【NLP】四万字全面详解 | 深度学习中的注意力机制(四,完结篇)

    作者 | 蘑菇先生 知乎 | 蘑菇先生学习记 深度学习Attention小综述系列: 四万字全面详解 | 深度学习中的注意力机制(一) 四万字全面详解 | 深度学习中的注意力机制(二) 四万字全面详解 ...

  7. 【NLP】四万字全面详解 | 深度学习中的注意力机制(三)

    NewBeeNLP原创出品 公众号专栏作者@蘑菇先生 知乎 | 蘑菇先生学习记 深度学习Attenion小综述系列: 四万字全面详解 | 深度学习中的注意力机制(一) 四万字全面详解 | 深度学习中的 ...

  8. 【NLP】四万字全面详解 | 深度学习中的注意力机制(二)

    NewBeeNLP原创出品 公众号专栏作者@蘑菇先生 知乎 | 蘑菇先生学习记  前情提要:四万字全面详解 | 深度学习中的注意力机制(一) 目前深度学习中热点之一就是注意力机制(Attention ...

  9. ❤️导图整理数组6:四数组的四数之和,详解Counter类实现哈希表计数,力扣454❤️

    此专栏文章是对力扣上算法题目各种方法的总结和归纳, 整理出最重要的思路和知识重点并以思维导图形式呈现, 当然也会加上我对导图的详解. 目的是为了更方便快捷的记忆和回忆算法重点(不用每次都重复看题解), ...

最新文章

  1. 机器视觉-EasyDL商品检测-标准版-Demo
  2. 【设计模式】里氏替换原则
  3. linux下安装php扩展模块gettext
  4. 极限与连续知识点总结_考研数学一试卷全面分析,历年题型和知识点整理,送给2021的学子...
  5. AD20学习笔记3---PCB封装库的创建方法及现有封装调用
  6. do while的使用
  7. 密钥协商(密钥交换)机制的讲解
  8. 我38岁,从外企技术高管到失业在家,只因为做错了这件事
  9. 搭建一个简单的SpringBoot项目
  10. .Net中的Placeholder控件
  11. php通过mysqldump数据库备份,mysql使用mysqldump进行数据库备份_MySQL
  12. 软件测试详细的基本流程
  13. 【Android安全】ActivityManager.isUserAMonkey API
  14. 软件工程关于教务系统的测试,软件工程课程设计——教务成绩管理系统摘要.doc...
  15. Autumn2.0.1_WP扁平化博客自媒体文章资讯类网站模板
  16. 100兆宽带下载速度为什么没有100兆/秒
  17. 《计算之魂》读书笔记 04
  18. 拆解USB无线网卡,电路方案非常经典(附高清美图)
  19. oracle 自定义数据类型
  20. VS 官方历史版本下载

热门文章

  1. 字符串转换成十进制整数
  2. 企业WiFi管理解决方案
  3. 工厂数字化转型必备的多协议转换网关
  4. ggplot2-标度、坐标轴和图例4
  5. python glob函数_Python glob()函数
  6. sql获取group by最后一条记录
  7. Processing互动编程开发实践之动态文字打乱功能(别嫌长,代码多,图片多)
  8. 用docker部署go简单应用
  9. 海康iv4200支持多少_追赶极速:海康威视C2000 Pro 2T固态硬盘到手简评
  10. LeetCode-241. Different Ways to Add Parentheses [C++][Java]