加入收藏 | 设为首页 | 会员中心 | 我要投稿 我爱故事小小网_铜陵站长网 (http://www.0562zz.com/)- 视频终端、云渲染、应用安全、数据安全、安全管理!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

用PHP来统计在线人数的四个方法分析

发布时间:2022-07-09 12:41:27 所属栏目:PHP教程 来源:互联网
导读:本篇文章给大家带来了关于PHP的相关知识,其中主要介绍了怎么实现统计在线人数的问题,可以利用表统计方式、用redis有序集合统计、用hyperloglog做统计等等,下面一起来看一下,希望对大家有帮助。 推荐学习:《PHP视频教程》 一个业务系统网站每天人数的访
  本篇文章给大家带来了关于PHP的相关知识,其中主要介绍了怎么实现统计在线人数的问题,可以利用表统计方式、用redis有序集合统计、用hyperloglog做统计等等,下面一起来看一下,希望对大家有帮助。
 
 
  推荐学习:《PHP视频教程》
 
  一个业务系统网站每天人数的访问量是多少,在线人数是多少?这种业务我们在开发中就要预留,也是在我们的设计范围内的咯!因为一个正在运营的网站,每天都会用到统计。
 
  那在线人数是如何统计的呢,这里有几种方案,代码用 laravel 框架。可以作为开发中参考。
 
  1 用表统计方式
  用数据表统计在线人数,这种方式只能用在并发量不大的情况下。
 
  首先我们先新建表:user_login
 
  20.png
 
  编辑
 
  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 不能像集合那样,返回输入的各个元素。

(编辑:我爱故事小小网_铜陵站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读