2011-11-26 95 views
4

通常,我會通過在php中對每個頁面加載執行查詢來保存所有用戶活動,頁面視圖和所有值。在會話結束時將所有用戶活動存儲爲會話值並保存會話值

  • 現在我想保存所有這些爲會話值和 在會議結束執行查詢。但是,我不知道如何在PHP中處理這個「結束會話」事件。

我想過在會話超時之前存儲所有會話值的後臺進程,但我對php中的多線程方法一無所知,儘管我聽說過一些規避是可能的。

  • 我想確定用戶是不活動的,而不需要用戶 觸發(如頁面加載),並保存所有的會話值在會話的 結束,超時之前。

這將節省一些工作量上的數據庫引擎,在這樣的方式: 用戶意見多頁,我增加值閉會期間,執行像

update pageviews set numberofviews=numberofviews+1 

上查詢的insetead每頁加載。

  • 問題是這樣的:「我該如何處理在PHP 會話事件的結束而無需用戶活動?」

解決方案的實際問題也讚賞。不管與粗體問題的相關性如何。 (我還沒有開始寫這個代碼,我的問題是不是bug修復。)

可能的解決方案:

我已經找到了php session handler functioon但文件並沒有說明它是否能有回調的參數的空參數什麼?

如果爲$回調參數輸入空參數,是否會失去標準功能?

我只想更改會話$ destroy事件。我現在需要幫助。

相關帖子: RP1

+0

這個問題與多線程有什麼關係。 – robert

+0

apc,memcache,redis的工具都不符合你的要求? – ajreal

回答

0

有點偏離了軌道,但你可以做你自己的垃圾回收。

  • 使用PHP將會話保存在目錄中,最好是tmpfs,禁用垃圾回收功能。

  • 寫一個週期性的PHP腳本查找所有會議文件,20多分鐘的時候,打開它們,它們寫入數據庫,並刪除它們。

+0

在我看來,這是正確的答案。在你的情況下,會話不會被腳本銷燬(=用戶操作),但是當它已經足夠大以便清理。當任何* PHP腳本運行時,這種垃圾收集通常會有一定的機會完成。將你的會話放到一個單獨的目錄中,以防止它們被「外來」清理並禁用默認的垃圾收集。然後創建自己的收集器,在清理會話之前存儲內容。如果你想讓它由用戶運行的PHP腳本獨立出來,那麼你需要一個cronjob。 – BurninLeo

3

你真的不能使用session_destroy處理程序,因爲它只是調用,如果你顯式調用session_destroy,如果用戶只是關閉瀏覽器並結束會話,這將不會發生。由於在這種情況下無法捕獲會話結束「事件」,因此您必須改爲進行某種類型的定期檢查,以查看會話是否在給定的時間段內處於空閒狀態。最簡單的方法是在會話中創建一個包含最後訪問時間的字段,然後定期創建一個腳本(通過cron或觸發PHP腳本中的其他功能),檢查該字段是否存在所有活動會話,對於時間戳超過xx秒的任何時間戳,請運行更新查詢。

注意,爲了做到這一點使用其存儲,你必須真正打開文件並直接解析到文件系統上的標準的PHP會議。另一種方法是將會話存儲在數據庫中,但這可能不是你想要做的事情,因爲你試圖減少db的負載。

另外一個可能性,這是不太開發密集是:

  1. 添加最後訪問的時間戳到您的會話
  2. 檢查,每次時間戳您更新會話
  3. 如果時間戳記早於xx秒在數據庫上運行更新查詢並將時間戳設置爲當前時間。

這樣你只更新數據庫,而不是每次頁面加載。這種方法的缺點當然是,除非會話中的最後一個活動與調用更新功能的時間間隔完全一致,否則您可能不會將最新的會話信息存儲在數據庫中。

1

只是胡亂想到這裏,你可以觸發一個HTTP請求從javascript節省窗口卸載您的會話數據。問題是瀏覽器通常會在頁面關閉後停止請求,因此這個請求可能不會觸及服務器,但我想這是值得進行測試的。

1

雖然有一些變通方法,每一個你能找到解決這個問題的解決方案會比在每個請求記錄每個用戶活動更加低效。

1

你想解決什麼問題?我不明白你爲什麼不會爲啓動一個更新查詢到數據庫的每個請求。它不應該花費比0.0001更長的時間。

我都肯定會去更新每個請求。它是1行代碼,不會對數據庫造成任何過度負載,並且效率更高。

你提出的方法是很難測試,造成不必要的負擔,甚至可能會造成全球性的狀態。您可以通過僅使用傳統解決方案來防止所有這些。會議是確定何時「結束」的(...)。

+0

在asp.net –

+0

Update =寫入操作中很容易。硬盤驅動器有70-150個iops,當負載增加時,你開始注意到這一點。 – c2h5oh

+0

有大量的查詢需要執行每個請求,這一個不會是最重的。 – Sherlock

2

這不是創建會話的原因,所以您嘗試實現的目標不僅僅是會話機制。

隨着標準的PHP會話您的選擇是比較有限的,並取決於會話存儲:

  1. 默認會話存儲在文件中。如果禁用會話垃圾回收,則可以運行一個cron作業,該作業將解析比您定義的時間早的會話文件。這並不完美,但是迄今爲止最簡單。此外文件會話吸 - 寫每個請求。
  2. 會議在Memcached。由於沒有好的方法來獲取比x更早的記錄,並且Memcached只會在數據過期時丟失數據,這一點在這裏可以做的不多。
  3. DB中的會話 - 您已經更新了每個請求。

因此,您在標準會話中的選擇最多是有限的。我的建議是:用您自己的標準會話替換標準會話,但這意味着您將不再通過$ _SESSION訪問會話,並需要您重寫很多代碼。

我用一個存儲會話數據在APC/Memcached以及數據庫中的單例替換了常規會話。會話數據僅在我請求時保存在數據庫中(Session::persistentStore($key,$value)),或者在處理請求期間,APC/Memcached存儲的會話數據表明它沒有寫足夠長的時間。這限制了很多寫入次數。 有了這個替代品,您只需強制從數據庫端保存會話:從數據庫中獲取尚未更新x分鐘的會話的會話ID,從APC/Memcached爲每個數據提取信息,並且如果沒有更新信息那裏(指示會話將很快結束)保存到數據庫。

1

我想到了剛剛在會話超時之前存儲所有會話值 一個後臺進程,但我不知道在PHP 多線程方法什麼,即使我已經聽到了一些 規避被可能。

如果你很容易地使用基於db的會話,你可以這樣做。

  1. 不需要多線程
  2. 寫運行,每分鐘/5分鐘
    • cron作業選擇的所有記錄即將到期
    • 將它們保存到其它表

關鍵是使用cron作業,而不是嘗試處理http請求中游的到期事件

+0

太貴了 –

1

你在談論延遲統計寫入和會話管理。我猜,你真正的問題是要避免在數據庫上寫per-http-requests寫查詢。

一些提示,可能對於這樣的問題是有用的:

  1. 小心在會議並行訪問。我們通常認爲會話只能通過一個進程來訪問,但這是錯誤的,比方說,例如,您正在執行多文件上傳,一些js向服務器打開多個ajax請求,每個進程都使用同一個會話。使用瀏覽器在同一網站上打開10個選項卡時也是如此。
  2. 添加更新查詢對於每個請求是一個重的東西。選擇查詢很快,通常在SQL端使用某種緩存。更新查詢很慢,可能是重建索引,並且通常意味着SQL Server上的某些緩存清理操作。如果您在數據庫上使用不同的用戶進行只讀或讀寫訪問,則它們也可能意味着不同的SQL會話。
  3. 會話大小不宜過大,因爲會議必須裝載每個請求,並且每次東西在你的會話(因爲1)鎖定機構設置和數據被推送到實體會話存儲(默認文件)。所以會話寫入會減慢你的過程。
  4. 一個NoSQL的後端,如MongoDB的reddit的可能是保存每個請求的統計數據的好地方,他們有正確的工具來確保原子更新,鎖和可能真的比Relationnal數據庫更快地執行(但你也可以在關係數據庫中檢查內存表的性能)。因此,您可以使用這些工具來跟蹤活動並通過將這些後端用作實時統計的主要目標來避免SQL更新。你可以異步從你的數據庫的後端收集一些statictics。現在會話是臨時對象,這些NoSQl後端也可能是好的會話存儲(如果您編寫自己的會話存儲處理程序)。

編輯:與並行使用原子更新問題例如:執行查詢要求的增量計數器=計數器1是一樣讀計數器,遞增它並執行更新查詢計數器= mynewvalue。當多個進程使用相同的數據時,第二個錯誤是錯誤的。