2011-10-19 139 views
36

從PHP手冊中,session.gc_probability和session.gc_divisor聲明gc將基於此概率發生。我明白了。PHP垃圾收集澄清

我不清楚的是這個概率是按照會話還是總體來說的。因此,如果我的概率是GC的1%(1/100),那麼這是否意味着如果一個會話不斷得到延長,每次有1%的變化,特定的會話將被清除?或者這是否意味着所有現有會議(包括新會議)中的1%會觸發GC來處理所有其他會議?

我很確定這是後者,我只是想確認一下。

這個問題的目的是在我們的網站上,我希望用戶有長期的會議(6個月)。如果所有會話的1%觸發GC,那麼這將有效地消除進行長期會話的目的,因爲GC最終會每隔一兩個小時發生一次。

+2

非常有趣的問題! +1 –

+0

相關http://stackoverflow.com/questions/3865303/debian-based-systems-session-killed-at-30-minutes-in-special-cron-how-to-overri –

+0

對於閱讀此嘗試的其他人如上所述,使用6個月的會話文件可能會導致嚴重的性能問題(如下所述)。但是,您可以使用session_set_save_handler()編寫一個自定義會話處理程序,該處理程序將使用數據庫而不是FS,從而消除許多性能損失。 – Meep3D

回答

10

每次執行PHP腳本並啓動會話時,都有可能會掃描會話文件夾以消除舊會話。

清理將只刪除在特定時間內未訪問的會話。但是,PHP並不保證會話在此期間將被銷燬。

您的長期會話策略應該工作得很好,但你可能希望減少1%到像0.1%

另一件事看出來的是,操作系統的過程中可能清理你的/ tmp文件夾重新啓動,即使PHP不會這樣做。

+0

我已將概率從1/100減少到1/1000000(0.000001%)。我希望能解決這個問題。另外,這是一個Magento網站,因此會話存儲在/ var/session中。就我所知,這個文件夾並沒有被服務器所觸及(但我猜如果從Magento管理員中選擇「Flush緩存存儲」,它將被刪除)。 – pspahn

+0

哦,希望Magento不要實施會忽略gc_ *設置的替代會話。 – romaninsh

+5

和減少可能性的副作用是你會用舊會話填滿你的硬盤。並且會話將需要更長和更長的時間來查找和加載,並且在一天結束時,仍然有很小的機會(儘管它遠小)會清除會話。您可以查看其他選項,例如編寫自己的會話處理程序,並準確控制要刪除哪些會話以及何時刪除會話。這並不難。 http://www.php.net/manual/en/function.session-set-save-handler.php – bumperbox

2

我不是這方面的專家,但是通過閱讀手冊,我會將您的注意力吸引到另一個設置session.gc_maxlifetime。從該文檔:

session.gc_maxlifetime指定後的數據將被視爲「垃圾」和潛在清理的秒數。垃圾收集可能會在會話開始時發生(取決於session.gc_probabilitysession.gc_divisor)。

因此,如果您將此設置設置爲一個合適的值(60 * 60 * 24 * 365/2了一年半,所以15768000),那麼相應的數據將沒有資格進行垃圾回收,無論其他設置是什麼。

+1

我已經將gc_maxlifetime設置爲15552000(180天) - 開發者網站上的所有內容似乎都能正常工作,但是一旦我將其推送到網站上,它在開始將用戶帶回登錄頁面之前已經運行了一段時間。 – pspahn

+7

這個值的意思是「會話創建後的秒數」或「上次修改後的秒數」? –

+0

它需要推遲垃圾收集器的組合,以便您的會話數據將會出現在字典中,同時還會延長您的Cookie使用壽命,因此,如果我正確理解了該會話數據行,它將保存會話ID唯一。 – vikingben

7

我最後一次看着源頭,每次調用session_start()「滾動骰子」,可以這麼說,使用除數和概率。如果您點擊,則會刪除session.save_path目錄中比session.gc_maxlifetime更早的所有文件。我忘記它是否使用了文件的修改或訪問時間,儘管它在正常情況下並不重要,因爲php在腳本執行結束時默認會覆蓋會話文件,所以mod和訪問時間幾乎總是非常接近。

// Rough psuedo code of how php's session_start() function works regarding garbage collection. 
function session_start() { 
    $percentChanceToGC = 100 * ini_get('session.gc_probability')/ini_get('session.session.gc_divisor'); 
    $shouldDoGarbageCollection = rand(1, 100) < $percentChanceToGC; 
    if ($shouldDoGarbageCollection) { 
     $expiredCutoffTime = time() - ini_get('session.gc_maxlifetime'); 
     foreach (scandir(ini_get('session.save_path')) as $sessionFile) { 
      if (filemtime($sessionFile) < $expiredCutoffTime) { 
       unlink($sessionFile); 
      } 
     } 
    } 

    // ... rest of code .... 
} 

我不知道你會多少會話文件,以最終擁有,如果你想讓他們住了至少6個月流連。考慮到php可能需要一些時間來統計成千上萬的文件來確定他們的年齡。也許考慮其他選項來持久存儲這些數據。或者你可以禁用php gc,只需運行一個cron作業來刪除陳舊的會話文件。否則,那1%的請求會觸發gc,必須等待php;換句話說它可能會滯後。