這基本上算是個老舊的話題了,幾乎全部phper在第一次面試的時候都會被問到關於session的問題,若是不出意外,每每是以下三板斧:php
這三個問題堪稱是關於php session三大基礎問題了,要是掌握很差,直接致使面試掛掉,使人唏噓不已。node
就以上三個問題簡單回顧一下:mysql
其中sess是文件前綴,後面的「njjf8l3lh**ff6」就是你的session id了。可是如今session文件內容是空的,若是咱們用以下代碼,就能夠產生session文件的內容:linux
<?php // 開啓session session_start(); $_SESSION['hello'] = 'world';
刷新一下網頁,而後在再次查看原來的session文件,其中就會有以下內容:
就是說,你往全局變量$_SESSION保存的內容本質上都是PHP用文本形式給你存儲到服務器上了。服務器根據你的session id讀取相應的session文件而後把其中內容讀出來,你就會獲得你的$_SESSION數據。nginx
開篇說了,爲了搞明白「究竟是哈士奇仍是胖子」的問題,不得不引入額外標記數據才行,因此實際上,先有的cookie而有後的session,都是爲了解決這個問題而產生的。兩者的恩怨情仇在於:web
大概就這些,再也不贅述,我是建議你們配合php.ini文件去研究上面三個問題。面試
若是說真的只回顧一下這三個問題,那豈不是真的應了「一看標題猛如虎,打開內容1-5」?我說過了的,我這裏是個正經的博客網站,是個真正的有些內涵的php文化網站,不能只講些個初級的內容,是個話題都都要不管如何強塞點兒看起來高端的玩意進去撐場面。redis
剛叨叨過了,默認配置下session是以文本文件形保存在服務器的某個文件夾中的,有心的人應該知道「一個目錄中文件過可能是會下降讀取效率的」,因此,在用一些PC軟件的時候能夠看到這些軟件會把TA須要的數據分散開來到不一樣的次級目錄中去。php的session文件也能夠這麼幹,整體來講是比較簡單粗暴的。咱們須要關注下兩個php配置項:sql
<?php echo "let rock session"; session_start();
刷新網頁,以下圖所示:
錯誤緣由相比你們看到了,大概意思就是說「/var/lib/php/sessions/n/j/」這個文件夾不存在,那麼切換到這個目錄下看看,以下圖:
果真是空的,也就說沒有/n/j這個子目錄,看來得手工建立了。然而,真的不能去手工建立,由於你哪兒知道文件夾的名字是啥?回到配置文件一頓研究,在session.save_path配置項附近發現以下英文字樣:apache
; NOTE 1: PHP will not create this directory structure automatically. ; You can use the script in the ext/session dir for that purpose. ; NOTE 2: See the section on garbage collection below if you choose to ; use subdirectories for session storage
英文比較蹩腳昂,大概翻譯一下,多包涵:
; NOTE 1: PHP壓根不會幫你建立這些文件夾,您本身個兒下載php源碼包,到ext目錄的session目中去找那個腳本去建立 ; NOTE 2: 若是你要用子目錄存儲session的話,記得看下垃圾回收,不看就有坑。(坑在這裏直接告訴你們吧,大概就是說你要本身搞子目錄存session,那我那個靠信仰和機率才能觸發的垃圾回收機制就壓根就不觸發了,你本身想辦法搞定你的過時session,我無論了)
因此呢,咱們下載一個php源碼包,最好是和你運行環境版本同樣的php源碼包並解壓,命令行切到ext/session目錄下,以下圖:
看到那個mod_files.sh沒?Linux下就這腳本。mod_files.bat就是給windows用的。給這個腳本chmod +x mod_files.sh加個執行權限,而後查看下使用方式:
爲了幫助眼近視的讀者,友情翻譯一下使用方式:
./mod_files.sh 'session文件根目錄' 目錄深度 哈希函數比特量 對應個人php開發環境就是: ./mod_files.sh /var/lib/php/sessions/ 2 5 其中第一項就是你存儲session的根目錄,第二項就是那個N,第三項查看session.hash_bits_per_character配置項
而後執行,以下圖所示:
此時到/var/lib/php/sessions中查看下,果真有目錄了,那麼,再次刷新網頁,本覺得很順利的你可能依然會遇到錯誤,以下:
session_start(): open(/var/lib/php/sessions/n/j/sess_njjf8l3lhfrpq8nrlnl1d9qff6, O_RDWR) failed: Permission denied (13)
模模糊糊認得Permission denied這幾個字母,好像是權限的問題,難道是由於當前apache進程用戶或者fpm進程用戶沒有權限往這些目錄寫數據嗎?改下這些目錄的擁有者撒,改爲www-data(我係統中fpm的運行用戶),再試試,果真好了!
總有刁民覺得這就能夠解決很大的問題了,然而很悲劇的是:並非。當前這個方案必定程度能夠解決session文件過多的問題,可是依然有兩個問題沒有獲得解決:
藉此,就引入一個問題,就是分佈式web部署中,如何解決session共享的問題!
關子我就不賣了,沒意思,首先想到的是redis,爲A和B提供一臺C redis服務器就能夠了,這樣能夠「 多快好省 」地一舉解決問題!按照預想,引入redis後能夠順利解決三個問題:
將session存入redis須要修正以下兩處php配置,首先設置session.save_handler = redis,其次是設置ession.save_path = "tcp://127.0.0.1:6379",而後重啓apache或者fpm,刷新一下網頁,若是網頁不報什麼錯誤,理論上session數據就已經到redis中去了,鏈接redis查看下key,以下圖:
從上至下我一共執行了五次redis命令,分別表示:
除了redis外(memcache我就不舉例了,和redis相似),還有一種方案就是經過nfs共享來實現,大概原理就是弄一臺服務器,經過內網共享對全部php業務服務器開放讀寫,你們知道linux下磁盤是能夠掛載在某個文件夾下的,因此將nfs掛載到各個php業務服務器的某個目錄下,而後按照上述文章修改響應配置就能夠了。這個,我也沒有嘗試過也懶得本身去嘗試了,因此偷個懶直接給你們拋個鏈接吧,是老葉博客上的一篇文章,《iMySQL | 老葉茶館,PHP實現多服務器session共享之NFS共享》。
裝逼完畢,若有問題,火速留言指正!