广告位联系
返回顶部
分享到

PHP四种统计在线人数方式介绍

php 来源:互联网 作者:佚名 发布时间:2022-09-22 08:46:47 人浏览
摘要

1 用表统计方式 用数据表统计在线人数,这种方式只能用在并发量不大的情况下。 首先我们先新建表:user_login 编辑 user_login 表 模拟用户登录,不存在用户就存入表,存在的则更新登录

1 用表统计方式

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

首先我们先新建表:user_login

编辑

user_login 表

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

// 客户端唯一的识别码

$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

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

// 客户端唯一的识别码

$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)指定用户是否在线

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

// 可实现功能一:当前总共在线人数

$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 有序集合实现在线人数统计

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

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

代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

// 客户端唯一的识别码

$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 不能像集合那样,返回输入的各个元素。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// 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 常用来做比如用户签到、活跃用户、在线用户等功能。

代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// 模拟当前用户

$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 消耗的内存空间不多, 统计的信息却挺多的,这种方案是值得推荐一下的。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/qq_37448303/article/details/126927316
相关文章
  • PHP数据加密方式的总结

    PHP数据加密方式的总结
    首先我们来了解一下为什么要加密? 在网络通信的过程中攻击者可以伪造请求和返回,从而达到不可告人的目的。如下图所示: 数据加密之
  • PHP四种统计在线人数方式介绍

    PHP四种统计在线人数方式介绍
    1 用表统计方式 用数据表统计在线人数,这种方式只能用在并发量不大的情况下。 首先我们先新建表:user_login 编辑 user_login 表 模拟用户登
  • PHP获取系统毫秒数时间方法
    前言 php中获取时间方法是date(),在php中获取时间戳方法有time()、strtotime(); date():date(format, timestamp),format为格式、timestamp为时间戳(可选
  • PHP中的DI依赖注入的详细介绍
    什么是 DI / 依赖注入 依赖注入DI 其实本质上是指对类的依赖通过构造器完成 自动注入 通俗来说,就是你当前操作一个类,但是这个类的某
  • PHP8.1 Fiber交叉执行多任务(附代码)
    拿平时大家写的 for 循环举例。像 go 你可以写两个go每个里面各写一个循环同时输入,你可以看到输出是交替。在过去的php版本中,如果只开
  • PHP8.0的编译安装与使用的介绍
    安装与配置 本次使用的操作系统Ubuntu 18.04.4 LTS 安装 1.准备必要库 1 2 apt-get install -y autoconf libxml2-dev libsqlite3-dev \ libcurl4-openssl-dev libssl-dev l
  • Mac如何编译PHP 8.0 到MxSrvs工具

    Mac如何编译PHP 8.0 到MxSrvs工具
    开始准备工作 下载 PHP 8.0 PHP 官方下载 https://www.php.net/downloads.php 进入到 MxSrvs 的主程序路径下的/Applications/MxSrvs/bin,根据 Mxsrvs 的命名规则,
  • PHP8 中的 JIT的详细介绍

    PHP8 中的 JIT的详细介绍
    PHP 8 的 JIT(Just In Time)编译器将作为扩展集成到 php 中 Opcache 扩展 用于运行时将某些操作码直接转换为从 cpu 指令。 这意味着使用JIT后,
  • PHP8.2不再支持字符串中用${}插入变量了

    PHP8.2不再支持字符串中用${}插入变量了
    PHP 社区 4 月底通过了一项只有一张反对票的提案,提案内容是在即将发布的 PHP 8.2 中,不再支持使用 ${} 在字符串中插入变量的语法(标记
  • PHP8.2两个新的强类型:null和false的详细介绍

    PHP8.2两个新的强类型:null和false的详细介绍
    PHP 从 7.0 开始不断地在完善强类型,我们可以给方法参数、返回值、类属性等声明类型。 强类型可以让代码更加健壮,易于维护,可读性增
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计