php实时在线人数统计,php精确统计在线人数

php是世界上非常著名的一款后端编程语言,其功能也很强大,下面匿名技术栈就为你分享一下使用php实现实时在线人数统计的功能,底部附带精准统计源码哦!

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

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

php精确统计在线人数的四种方法:

phptongji

1.用表统计方式

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

首先我们先新建表:user_login

phptongji2

编辑

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

phptongji1

php显示在线人数源码

在线人数统计程序源代码如下:如有错误请指正。

db层:

db_online.php

//该函数使用户自己在线,并且检查其他用户的在线情况

function checkOnline($userid,$tempid=null)

{

$conn = connect();

//对于所有用户

//先设置自己为在线

$stmt = “UPDATE “.DB_NAME.”.USER SET IsOnline=’Y’ WHERE UserID=”.$userid;

$result = query($stmt,$conn);

//info($stmt);

//如果当前用户是游客

if ($tempid != null)

{

$stmt = “SELECT TempID FROM “.DB_NAME.”.TEMPUSER WHERE

TempID=”.$tempid;

$result = query($stmt,$conn);

//info($stmt);

//如果该游客还在线

if ($row = fetch_array($result))

{

$stmt = “UPDATE “.DB_NAME.”.TEMPUSER SET

RequestTime='”.getCurrentTime().”‘ WHERE TempID=”.$tempid;

$result = query($stmt,$conn);

//info($stmt);

}

//该游客已经离线

else

{

$stmt = “INSERT INTO “.DB_NAME.”.TEMPUSER

VALUES(‘”.$tempid.”‘,'”.getCurrentTime().”‘)”;

$result = query($stmt,$conn);

//info($stmt);

}

}

//查看其他用户

//普通用户

$stmt = “UPDATE “.DB_NAME.”.USER SET IsOnline=’N’ WHERE “.time().” –

unix_timestamp(RequestTime) > “.ONLINE_DURATION.” AND UserGroupID != “.GUEST;

$result = query($stmt,$conn);

//游客

$stmt = “DELETE FROM “.DB_NAME.”.TEMPUSER WHERE “.time().” –

unix_timestamp(RequestTime) > “.ONLINE_DURATION;

$result = query($stmt,$conn);

disconnect($conn);

}

//得到在线人数,分用户和游客

function getOnlineNumber()

{

$olnum = array();

$conn = connect();

$stmt = “SELECT COUNT(UserID) FROM “.DB_NAME.”.USER WHERE IsOnline=’Y’ AND

UserGroupID != 4″; //4 为guest的用户组id

//info ($stmt);

$result = query($stmt,$conn);

$olnum[‘user’] = result($result,0,”COUNT(UserID)”);

$stmt = “SELECT COUNT(TempID) FROM “.DB_NAME.”.TEMPUSER”;

//info ($stmt);

$result = query($stmt,$conn);

if ($row = fetch_array($result))

{

$olnum[‘guest’] = $row[‘COUNT(TempID)’];

}

disconnect($conn);

return $olnum;

}

其中的connect(), disconnect(), query(),fetch_array()函数在dbmanager.inc.php中

dbmanager.inc.php

define(“DB_NAME”,”databasename”);

define(“DB_USER”,”user”);

define(“DB_PASS”,”pass”);

define(“DB_HOST”,”localhost”);

function connect()

{

//echo “Connecting to Host:”.HOST.”
“;

$conn = mysql_connect(DB_HOST,DB_USER,DB_PASS);

mysql_select_db(DB_NAME);

/*

if ($conn)

{

echo “Connect to database sucessfully. connection id:”.$conn.”
“;

}

else

{

echo “Connect to database failed.
“;

}

*/

return $conn;

}

function pconnect()

{

return mysql_pconnect(DB_HOST,DB_USER,DB_PASS);

}

function disconnect($conn)

{

$close = mysql_close($conn);

/*

if ($close)

echo “MySQL Database disconnected.
“;

else

echo “MySQL Database disconnecting failed. Please try again.
“;

*/

}

function query($stmt,$conn)

{

return mysql_query($stmt,$conn);

}

function fetch_array($result)

{

return mysql_fetch_array($result);

}

function fetch_row($result)

{

return mysql_fetch_row($result);

}

function num_rows($result)

{

return mysql_num_rows($result);

}

function result($result,$row,$field)

{

return mysql_result($result,$row,$field);

}

rule层:

rl_online.php

function getOnline()

{

if ($userid == 2)

{

if (session_is_registered(“tempuserid”))

{

checkOnline($userid,$tempuserid);

}

}

else

{

checkOnline($userid);

}

return getOnlineNumber();

}

ui层:

ui_online.php

$online_num = getOnline();

echo “在线人数,注册用户”.$online_num[‘user’].”人,游客”.$online_num[‘guest’].”人”;

php的实时精准统计代码就为你分享到这里哦,希望可以帮助到对统计在线人群有帮助的伙伴,如果你还有什么疑问可以底部留言咨询哦。

本文来自投稿,不代表(钦钦技术栈)立场,如若转载,请注明出处:https://www.qin1qin.com/catagory/364/

(0)
上一篇 2022年 6月 22日 3:56:33
下一篇 2022年 6月 23日 11:55:43

软件定制开发公司

相关阅读

发表回复

登录后才能评论
通知:禁止投稿所有关于虚拟货币,币圈类相关文章,发现立即永久封锁账户ID!