首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 統計用戶在線時間三種方案:客戶端心跳、服務端定時掃描、活動時間更新的優劣權衡

     編輯:PHP 綜合知識

數據表設計

CREATE TABLE user_online (
    uid INT UNSIGNED NOT NULL,
    session_id CHAR(32) NOT NULL,
    login_time INT UNSIGNED NOT NULL,
    logout_time INT UNSIGNED NOT NULL,
    PRIMARY KEY (uid, session_id)
);

方案一:客戶端定時心跳


// 登錄時插入
$stmt = $pdo->prepare('INSERT INTO user_online (uid, session_id, login_time, logout_time) VALUES (?, ?, ?, ?)');
$stmt->execute([$uid, $sid, $now, $now + 600]);

// 頁面 JS 每 10 分鐘發送心跳
setInterval(() => fetch('/api/heartbeat'), 10 * 60 * 1000);

// 後端更新
$pdo->prepare('UPDATE user_online SET logout_time = ? WHERE uid = ? AND session_id = ?')
    ->execute([time() + 600, $uid, $sid]);
  • 優點:準確度高(可控間隔)。
  • 缺點:依賴 JS,刷新/關頁即停止;AJAX 較多的頁面(如 WebGame)適用,傳統多頁應用不適用。

方案二:服務端定時掃描


// Crontab 每 5 分鐘執行
// php /path/scan_online.php
$stmt = $pdo->query('SELECT uid, session_id FROM user_online WHERE logout_time > ' . time());
while ($row = $stmt->fetch()) {
    // 檢查 session 文件是否存在
    if (file_exists(session_save_path() . '/sess_' . $row['session_id'])) {
        $pdo->prepare('UPDATE user_online SET logout_time = ? WHERE uid = ? AND session_id = ?')
            ->execute([time() + 300, $row['uid'], $row['session_id']]);
    } else {
        // session 已失效,可選刪除記錄
    }
}
  • 優點:不依賴前端,準確反映 session 存活。
  • 缺點:需服務器控制權(crontab/systemd timer),虛擬主機無法使用;掃描大量記錄有性能開銷。

方案三:用戶活動時更新(推薦通用)


// 每次頁面請求(公共入口文件/中間件)
if (!empty($_SESSION['uid'])) {
    $pdo->prepare('UPDATE user_online SET logout_time = ? WHERE uid = ? AND session_id = ?')
        ->execute([time() + 600, $_SESSION['uid'], session_id()]);
}
// 登出時
$pdo->prepare('DELETE FROM user_online WHERE uid = ? AND session_id = ?')
    ->execute([$_SESSION['uid'], session_id()]);
  • 優點:實現簡單、無額外基礎設施、適用大多數項目、準確度可接受(±10 分鐘)。
  • 缺點:增加每請求一次 DB 寫入(可用 Redis 緩存批量落庫優化)。

優化建議

  1. Redis 緩存寫入:請求時只更新 Redis HSET online:{uid} logout_time {timestamp},定時腳本每分鐘批量同步到 MySQL。
  2. 複合索引:INDEX idx_logout (logout_time) 加速掃描/清理。
  3. 在線人數統計:SELECT COUNT(*) FROM user_online WHERE logout_time > UNIX_TIMESTAMP()。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved