傳統線上人數統計常用資料庫 `UPDATE` 計數器或 Memcached/Redis 原子操作。本文提出**零依賴、極簡部署**方案:
<?php
// online_counter.php
// 置於每頁頂部 include,或納入前端控制器
// 設定
$onlineDir = __DIR__ . '/online'; // 獨立目錄,避免干擾
$expireMinutes = 1; // 逾期分鐘數(可調 5~10 分鐘)
$refreshSeconds = 60 * $expireMinutes; // 前端自動重整間隔
// 1. 確保目錄存在且可寫
if (!is_dir($onlineDir)) {
@mkdir($onlineDir, 0755, true);
@chmod($onlineDir, 0755);
}
// 2. 啟動 Session(若未啟動)
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$sessionId = session_id();
// 3. 建立/更新當前訪客檔案
$myFile = $onlineDir . '/' . $sessionId;
@touch($myFile); // 建立或更新 mtime 為現在
// 4. 掃描目錄統計線上人數
$onlineCount = 0;
$now = time();
$expireTime = $now - ($expireMinutes * 60);
if ($handle = @opendir($onlineDir)) {
while (($file = readdir($handle)) !== false) {
if ($file === '.' || $file === '..') continue;
$filePath = $onlineDir . '/' . $file;
// 僅統計一般檔案,排除子目錄
if (!is_file($filePath)) continue;
$mtime = @filemtime($filePath);
if ($mtime !== false && $mtime >= $expireTime) {
$onlineCount++;
} else {
// 逾期檔案立即刪除(掃描順便清理)
@unlink($filePath);
}
}
closedir($handle);
}
// 5. 輸出結果(可根據需求調整格式)
// 扣除自己?視定義而定。這裡顯示含自己。
header('Content-Type: text/html; charset=utf-8');
echo "當前在線 $onlineCount 人";
// 6. 前端自動重整(簡易輪詢)
echo "";
?>
| 優點 | 缺點/風險 | |
|---|---|---|
| 天然唯一、無需額外產生 ID | Session ID 可能被竄改/固定 (Session Fixation),需配合 `session_regenerate_id(true)` 登入時重生 | |
| 自動綁定瀏覽器關閉失效 (Session Cookie) | 若用戶禁用 Cookie、使用無痕模式,可能頻繁產生新檔案造成計數偏高 | |
| 無需資料庫連線 | 高併發 (萬級同時在線) 時目錄掃描 `readdir` 成為瓶頸 |
| 同時在線 | 掃描耗時 (SSD) | 建議方案 |
|---|---|---|
| < 1,000 | < 5 ms | 本方案完美適用 |
| 1,000 ~ 10,000 | 10 ~ 50 ms | 可接受,建議加鎖、增加快取層 |
| 10,000 ~ 50,000 | 50 ~ 200 ms | 建議遷移 Redis Sorted Set |
| > 50,000 | > 200 ms | 必須用 Redis / 專用即時統計服務 |
「檔案 mtime + Session ID」是**最小可行性線上計數器**:零依賴、秒級部署、程式碼 < 30 行、維護成本極低。適合中小型站點、內部系統、快速原型。隨著流量增長,平滑遷移至 **Redis Sorted Set** 或 **專用即時分析系統 (如 ClickHouse、Apache Druid)**,核心邏輯「時間窗口內唯一標識計數」完全可復用。理解此模式,本質是掌握**「以時間為維度的集合運算」**——這正是所有即時統計系統的數學骨架。