基於 Session + 數據庫的輕量級在線統計,實現秒級精度、自動清理過期記錄,適合中小型站點無需引入 Redis 等外部依賴。
<?php
session_start();
// 當前時間轉秒數
$now = time(); // 直接使用 timestamp,避免字符串解析開銷
// 讀取上次記錄時間
$last = isset($_SESSION['online_time']) ? $_SESSION['online_time'] : 0;
$interval = $now - $last;
// 會話有效且超過5分鐘(300秒),或時間異常(間隔<0)
if (isset($_SESSION['username']) && ($interval > 300 || $interval < 0)) {
$_SESSION['online_time'] = $now;
// 更新數據庫:使用預處理防注入
$stmt = $pdo->prepare("REPLACE INTO lt_t_online (lt_username, lt_lasttime) VALUES (?, NOW())");
$stmt->execute([$_SESSION['username']]);
}
?>
優化點:原代碼手動拆解時分秒計算間隔,直接用 time() 獲取 Unix 時間戳相減簡潔高效;使用 REPLACE INTO 避免主鍵衝突;引入 PDO 預處理修復原代碼 SQL 注入隱患。
<?php
// 每5分鐘運行一次:*/5 * * * * /usr/bin/php /path/cron_cleanup.php
require 'db_config.php';
$stmt = $pdo->prepare("DELETE FROM lt_t_online WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(lt_lasttime) > 300");
$stmt->execute();
// 可選:記錄清理日誌
error_log("[".date('Y-m-d H:i:s')."] Cleaned {$stmt->rowCount()} expired online records\n", 3, '/var/log/online_cleanup.log');
?>
CREATE TABLE `lt_t_online` (
`lt_username` varchar(50) NOT NULL,
`lt_lasttime` datetime NOT NULL,
PRIMARY KEY (`lt_username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
$stmt = $pdo->query("SELECT COUNT(*) FROM lt_t_online");
$online_count = $stmt->fetchColumn();
echo "當前在線:{$online_count} 人";
| 場景 | 方案 |
|---|---|
| 高併發(>10k QPS) | 改用 Redis Set + TTL,SADD online:users {uid} + EXPIRE 300,SCARD 獲取計數 |
| 分布式部署 | 共享 Session 存儲 + 中央化數據庫/Redis,避免多節點計數不一致 |
| 統計準確性要求極高 | WebSocket 長連接心跳檢測,而非依賴 HTTP 請求觸發 |
session_is_registered 已棄用(PHP 5.4+ 移除),改用 isset($_SESSION['username'])date("H+i+s") 格式字符串錯誤,+ 非分隔符,應用 time() 直接獲取秒數此方案代碼量極小、零外部依賴、部署即用,是中小項目快速上線在線統計的不二之選。