需求與考量
在開發時遇到一個需求,是要定時清除PHP 中的Session資料。
於是我考慮了以下方案:
- 設定Session 過期時間
- 利用CI 架構中Hooker自訂Session生存時間程式,直接刪除Session 內容資料
當時我選擇了第二個,因為我記得Session的計時跟清除有蠻多東西要釐清的,
於是我選擇了我覺得我最有把握的做法–自己計時,自己清除。
PHP 中的Session 存活時間
在PHP中的Session 如果要設定過期時間
在php.ini中,
對session.gc_maxlifetime
和session.cookie_lifetime
這兩個參數的設定,就可以達成了。
前者gc_maxlifetime
掌管存在Server上的資料的過期時間,
若在Server上過期,如果你的客戶端仍然使用同一個Session id 存取,
你通常可以拿到已過期的資料,
因為在php中,Server上的過期資料清除,
是一個機率性的事件,
靠著session.gc_probability
(分子)
和session.gc_divisor
(分母)決定的。
意思是,每次存取伺服器資料,假設是1/100的機率刪除,
那麼在那百分之一的機率達成以後,會啟動gc去掃那些Session的過期檔案清除。
那有人會說,是不是乾脆機率調成1就一定可以運作得很好呢?
可以確保Session 必定被刪除,但Server的資源會被消耗得相當厲害。
所以為了效能考量,請不要把刪除的機率調整太高。
而session.cookie_lifetime
參數掌管著client端的phpsession id 更換,
phpsession id 就像是門牌號碼一樣,用來存取server上相同id的檔案。
如果被更換,那麼裡面的內容也會被更換。
若session.cookie_lifetime
設定成0 則代表每次關閉client都更換phpsession id,
若設定成300,
則代表著三百秒之後phpsession id會被更換。
因為phpsession id被更換了,你會啟用不同的session 檔案,因此裡面的資料是空的。
那你也許會問,那原本的檔案去哪了呢?
它,哪裡都沒去。
因此,如果你沒有設定server上的存活時間,那麼這檔案就會一直存在,久了server的資料就會越長越大,最後就會拖垮效能跟可用空間。
那麼如果要清除session 的資料,
但又不想要跟時間相關的話,
利用session_destroy()
與session_start()
的組合同樣可以造成phpsession id 更換的效果。
但如果使用全域變數直接指定成空陣列的做法$_SESSION = []
也可以做到資料面的清除,但phpsession id 仍會保留。
總結
- session.cookie_lifetime 用來設定client的有效時間,會自動更換phpsession id
- gc_maxlifetime 用來設定server資料有效時間,但機率性的啟動刪除過期資料,還沒刪除時可以取得過期資料。 phpsession id不會被改變。
- session.gc_probability 設定資料過期的刪除機率(分子)
- session.gc_divisor 設定server資料過期的樣本空間(分母)