久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      用PHP來(lái)統(tǒng)計(jì)在線人數(shù)的四個(gè)方法詳解

      本篇文章給大家?guī)?lái)了關(guān)于PHP的相關(guān)知識(shí),其中主要介紹了怎么實(shí)現(xiàn)統(tǒng)計(jì)在線人數(shù)的問(wèn)題,可以利用表統(tǒng)計(jì)方式、用redis有序集合統(tǒng)計(jì)、用hyperloglog做統(tǒng)計(jì)等等,下面一起來(lái)看一下,希望對(duì)大家有幫助。

      用PHP來(lái)統(tǒng)計(jì)在線人數(shù)的四個(gè)方法詳解

      推薦學(xué)習(xí):《PHP視頻教程》

      一個(gè)業(yè)務(wù)系統(tǒng)網(wǎng)站每天人數(shù)的訪問(wèn)量是多少,在線人數(shù)是多少?這種業(yè)務(wù)我們?cè)陂_(kāi)發(fā)中就要預(yù)留,也是在我們的設(shè)計(jì)范圍內(nèi)的咯!因?yàn)橐粋€(gè)正在運(yùn)營(yíng)的網(wǎng)站,每天都會(huì)用到統(tǒng)計(jì)。

      那在線人數(shù)是如何統(tǒng)計(jì)的呢,這里有幾種方案,代碼用 laravel 框架??梢宰鳛殚_(kāi)發(fā)中參考。

      1 用表統(tǒng)計(jì)方式

      用數(shù)據(jù)表統(tǒng)計(jì)在線人數(shù),這種方式只能用在并發(fā)量不大的情況下。

      首先我們先新建表:user_login

      用PHP來(lái)統(tǒng)計(jì)在線人數(shù)的四個(gè)方法詳解

      編輯

      user_login 表

      模擬用戶登錄,不存在用戶就存入表,存在的則更新登錄信息

      // 客戶端唯一的識(shí)別碼 $client_id = session()->getId(); //用戶是否已存在 $user = DB::table('user_login')     ->where('token', $client_id)     ->first(); //不存在則插入數(shù)據(jù) 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')       ]); }

      這里還需要定期清理無(wú)任何操作的用戶,假如用戶一個(gè)小時(shí)內(nèi)無(wú)任何操作,我們可以記為無(wú)效用戶

      代碼如下:

      // 客戶端唯一的識(shí)別碼 $client_id = session()->getId(); //用戶是否已存在 $user = DB::table('user_login')     ->where('token', $client_id)     ->first(); //不存在則插入數(shù)據(jù) 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')       ]); }

      我們可以實(shí)現(xiàn)的功能:

      1)當(dāng)前在線人數(shù)

      2)某時(shí)間段內(nèi)在線人數(shù)

      3)最新上線的用戶

      4)指定用戶是否在線

      // 可實(shí)現(xiàn)功能一:當(dāng)前總共在線人數(shù) $c = DB::table('user_login')->count(); echo '當(dāng)前在線人數(shù):' . $c . '<br />'; // 可實(shí)現(xiàn)功能二:某時(shí)間段內(nèi)在線人數(shù) $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 . '在線人數(shù):' . $c . '<br />'; // 可實(shí)現(xiàn)功能三:最新上線的用戶 $newest = DB::table('user_login')     ->orderBy('create_time', 'DESC')     ->limit(10)     ->get(); echo '最新上線的用戶有:'; foreach ($newest as $value) {     echo $value->username . ' '; } echo '<br />'; // 可實(shí)現(xiàn)功能四:指定用戶是否在線 $username = 'user_1111'; $online = DB::table('user_login')     ->where('username', $username)     ->exists(); echo $username . ($online ? '在線' : '不在線');

      2 使用 redis 有序集合實(shí)現(xiàn)在線人數(shù)統(tǒng)計(jì)

      因?yàn)槭莾?nèi)存中,所以效率很高,可以統(tǒng)計(jì)某個(gè)時(shí)間段內(nèi)的在線人數(shù),可以做各種聚合操作。但是如果在線人數(shù)比較多的情況下,會(huì)比較占用內(nèi)存。還有一點(diǎn):

      無(wú)法通過(guò)用戶操作時(shí)間清除掉無(wú)效用戶,只有手動(dòng)登出的用戶才會(huì)從集合中刪除。

      代碼如下:

      // 客戶端唯一的識(shí)別碼 $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)) {    // 不在線,加入當(dāng)前客戶端     Redis::zAdd($key, time(), $client_id); } // 可實(shí)現(xiàn)功能一:當(dāng)前總共在線人數(shù) $c = Redis::zCard($key); echo '當(dāng)前在線人數(shù):' . $c . '<br />'; // 可實(shí)現(xiàn)功能二:某時(shí)間段內(nèi)在線人數(shù) $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 . '在線人數(shù):' . $c . '<br />'; // 可實(shí)現(xiàn)功能三:最新上線的用戶,時(shí)間從小到大排序 $newest = Redis::zRangeByScore($key, '-inf', '+inf', ['limit' => [0, 50]]); echo '最新上線的用戶有:'; foreach ($newest as $value) {     echo $value . ' '; } echo '<br />'; // 可實(shí)現(xiàn)功能四:指定用戶是否在線 $username = $client_id; $online = Redis::zScore($key, $client_id);; echo $username . ($online ? '在線' : '不在線') . '<br />'; // 可實(shí)現(xiàn)功能五:昨天和今天都上線的客戶 $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 做統(tǒng)計(jì)

      跟有序集合方式不同,hyperloglog 十分節(jié)約空間,但是實(shí)現(xiàn)的功能也非常單一,只能統(tǒng)計(jì)在線人數(shù),不能實(shí)現(xiàn)其余的任何功能。

      Redis HyperLogLog 是用來(lái)做基數(shù)統(tǒng)計(jì)的算法,HyperLogLog 的優(yōu)點(diǎn)是,在輸入元素的數(shù)量或者體積非常非常大時(shí),計(jì)算基數(shù)所需的空間總是固定 的、并且是很小的。

      在 Redis 里面,每個(gè) HyperLogLog 鍵只需要花費(fèi) 12 KB 內(nèi)存,就可以計(jì)算接近 2^64 個(gè)不同元素的基 數(shù)。這和計(jì)算基數(shù)時(shí),元素越多耗費(fèi)內(nèi)存就越多的集合形成鮮明對(duì)比。

      但是,因?yàn)?HyperLogLog 只會(huì)根據(jù)輸入元素來(lái)計(jì)算基數(shù),而不會(huì)儲(chǔ)存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個(gè)元素。

      // note HyperLogLog 只需要知道在線總?cè)藬?shù) for ($i=0; $i < 6; $i++) {     $online_user_num = mt_rand(10000000, 99999999);     //模擬在線人數(shù)     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'));

      這種方案僅僅只能統(tǒng)計(jì)出某個(gè)時(shí)間段在線人數(shù)的總量, 對(duì)在線用戶的名單卻無(wú)能為力,但是卻挺節(jié)省內(nèi)存的,對(duì)統(tǒng)計(jì)數(shù)據(jù)要求不多情況下 ,我們便可以考慮這種方案。

      4 使用 bitmap 統(tǒng)計(jì)

      bitmap 就是通過(guò)一個(gè) bit 位來(lái)表示某個(gè)元素對(duì)應(yīng)的值或者狀態(tài),其中的 key 就是對(duì)應(yīng)元素本身。我們知道 8 個(gè) bit 可以組成一個(gè) Byte,所以 bitmap 本身會(huì)極大的節(jié)省儲(chǔ)存空間。

      bitmap 常用來(lái)做比如用戶簽到、活躍用戶、在線用戶等功能。

      代碼如下

      // 模擬當(dāng)前用戶 $uid = request('uid'); $key = 'online_bitmap_' . date('Ymd'); // 設(shè)置當(dāng)前用戶在線 Redis::setBit($key, $uid, 1); // 可實(shí)現(xiàn)功能1:在線人數(shù) $c = Redis::bitCount($key); echo '在線人數(shù):' . $c . '<br />'; // 可實(shí)現(xiàn)功能2:指定用戶是否在線 $online = Redis::getBit($key, $uid); echo $uid . ($online ? '在線' : '不在線') . '<br />'; // 可實(shí)現(xiàn)功能3:昨天和今天均上線的用戶總數(shù) $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 '昨天和今天都上線的用戶數(shù)量有:' . $c . '<br />';

      bitmap 消耗的內(nèi)存空間不多, 統(tǒng)計(jì)的信息卻挺多的,這種方案是值得推薦一下的。

      推薦學(xué)習(xí):《PHP視頻教程》

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)