session的存儲了解以前是怎么做的,搞清楚了來龍去脈,才會明白進行共享背后的思想和出發(fā)點。我喜歡按照這樣的方式來問(或者去搞清楚):為什么要session要進行共享,不共享會什么問題呢?

以前業(yè)界使用session的做法:
默認情況下,php的session文件是保存在磁盤文件中。在php.ini配置文件中的配置項如下:
session.save_handler = files
session.save_path = "N;/path"
第一個配置項是指定使用files(文件形式)存儲session數(shù)據(jù)。
第二個參數(shù)指定保存的路徑。N表示生成多少級目錄(不放到一個目錄下,分散到多個磁盤目錄中去)
我的配置項是:session.save_path = "F:/wamp/tmp"。那么就會去這個目錄下面看到很多session數(shù)據(jù)的文件。
當我們使用php的內(nèi)置函數(shù)session_start()的時候,就是去上面指定的磁盤目錄把session數(shù)據(jù)載入,實際上就是拿類似
sess_74dd7807n2mfml49a1i12hkc45的文件。
74dd7807n2mfml49a1i12hkc45就是大家經(jīng)常說的什么session的id號。
php.ini中還有一個關鍵配置項,如下:
session.name = PHPSESSID
PHPSESSID就是cookie的名稱,其實上面一串"74dd7807n2mfml49a1i12hkc45"會保存在一個名為PHPSESSID的cookie中。
根據(jù)http的請求機制,當瀏覽器請求的時候,頭部信息會把瀏覽器中的cookie一起發(fā)給服務器。PHPSESSID這個cookie也
是在其中發(fā)給了服務器,php引擎通過讀取PHPSESSID的值來確定要載入哪個session文件。
比如值為74dd7807n2mfml49a1i12hkc45,載入的就是"sess_74dd7807n2mfml49a1i12hkc45"。
注:當你調(diào)用php的函數(shù)session_start(),才表明你需要使用session文件了。不然平白無故就去載入文件,浪費性能。
===========================================
根據(jù)如上原理。session的數(shù)據(jù)默認是保存在磁盤文件中。假設這種情況:多臺php服務器進行負載均衡的時候,比如有三臺php服務器,為了實現(xiàn)負載均衡,那么三臺服務器上面的php代碼都是一樣(拷貝一份)。
上面的圖是nginx+fpm部署圖。可以看到多臺php服務器進行負載均衡。
生成session數(shù)據(jù)文件都是在本地了(a,b,c各自的服務器磁盤上)。負載均衡的目的本來就是要為了平均分配請求,所以沒有固定第一次訪問和第二次訪問是同一臺服務器,實際上無法確定的。第一秒訪問可能是a服務器,第二秒訪問的可能是c服務器。
所以同一個登錄會員,實際上就會出現(xiàn):第一秒訪問第一臺php服務器,第二秒訪問的是第二臺服務器。登錄的信息一般是保存在session中的。這樣子登錄保存的session數(shù)據(jù)就需要進行共享了。不然的話會出現(xiàn),訪問第一臺服務器生成了一個session數(shù)據(jù)。第二秒負載請求到第三臺服務器,結(jié)果獲取不到剛才生成的session數(shù)據(jù)。
我的理解是:只有涉及到多臺多臺后端服務器(php,java等處理服務器)的時候,才涉及到session讀取不到的問題。
在php環(huán)境中,只有多臺php服務器(php服務器而非web服務器,session文件是php引擎生成的)的情況下,才會涉及到
session共享的問題。單臺php服務器,存儲都在一臺主機上。不涉及到共享問題。因為session直接存儲在這臺服務器磁盤上是能夠被本機讀取到的。
如果是:一臺php服務器,多臺mysql服務器。這種也是負載均衡,這種負載均衡不涉及到共享問題。因為怎么session數(shù)據(jù)怎么操作都是保存在一臺服務器上。
==================================
ps:實際上,session在php,.net,java等只要是后端語言都會用到。session的存儲機制,各種語言都大體差不多。我覺得這跟cookie在各個語言中都會用到差不多。.net,java我沒去了解過。但是存儲原理是差不多的。區(qū)別就是,php,java,.net調(diào)用的函數(shù),讀和取session數(shù)據(jù)的方式不同。默認都是存儲在本地文件中的(不然怎么會涉及到session共享問題呢,存儲在數(shù)據(jù)庫本身就可以實現(xiàn)共享的)。
所以,無論是.net還是java都會涉及到session數(shù)據(jù)共享的問題。
其實我的理解是,session的原理都是一樣的。討論session共享方案設計,是可以拋開具體的語言去討論session共享方案設計。
目前業(yè)界解決session共享的幾種思路,我總結(jié)如下:
第一種辦法:把原來存儲在服務器磁盤上的session數(shù)據(jù)存儲到客戶端的cookie中去。
這樣子,就不需要涉及到數(shù)據(jù)共享了。a客戶端請求的時候,原來生成在服務器的數(shù)據(jù)生成到瀏覽器的cookie中,根據(jù)cookie中的數(shù)據(jù)識別用戶。php由原來的”從本地(也就是服務器)磁盤上讀取session數(shù)據(jù)”轉(zhuǎn)變?yōu)?rdquo;瀏覽器的cookie中讀取數(shù)據(jù)”,
這樣子,在多臺php服務器負載均衡的情況下,即便第一秒請求是a服務器,第二秒請求是b服務器,都不需要管哪臺服務器了。反正都是讀取客戶端上的cookie數(shù)據(jù)。
一般是把session數(shù)據(jù)按照自己定義的加密規(guī)則,加密后后存在cookie中。
數(shù)據(jù)保存在cookie中這種做法有好處,也有壞處。
好處是服務器的壓力減小了,因為session數(shù)據(jù)不存在服務器磁盤上。根本就不會出現(xiàn)session讀取不到的問題。
帶來的弊端是:
網(wǎng)絡請求占用很多。每次請求時,客戶端都要通過cookie發(fā)送session數(shù)據(jù)給服務器。
另外,瀏覽器對cookie的大小存在限制。每個瀏覽器限制是不同的。
Firefox和Safari允許cookie多達4097個字節(jié),包括名(name)、值(value)和等號。
Opera允許cookie多達4096個字節(jié),包括:名(name)、值(value)和等號。
Internet Explorer允許cookie多達4095個字節(jié),包括:名(name)、值(value)和等號。
所以第一種方案不適合高訪問量的情況下,因為高訪問量的情況下,每次請求瀏覽器都要發(fā)送session數(shù)據(jù)給服務器。一般一個cookie大小2k的樣子。
要占用很多帶寬了(服務器購買帶寬是一個很大費用),成本增高。歸納為帶寬性能,速度問題。
存儲到cookie中去,第二方面是安全問題:把session數(shù)據(jù)放到客戶端,一般session中存的都是重要性數(shù)據(jù)(帳號、昵稱、用戶id等),會存在安全問題。
了解到,淘寶以前用過這種方式,把session數(shù)據(jù)存儲到cookie中,根據(jù)cookie來識別用戶。
第二種思路:用一種算法(簡單理解為規(guī)則),什么機制下session是保存在哪臺服務器下,那么讀取的時候就按照這種規(guī)則去讀取,就能定位到原來的服務器。叫做分發(fā)請求,分發(fā)到特定的服務器上去,我理解其原理是存session和讀session數(shù)據(jù)保證都在一臺服務器操作,就不會需要涉及到共享,具體實現(xiàn)方式是通過約定一種分發(fā)機制來實現(xiàn)。
也叫做sticky模式(粘性會話模式),同一個用戶的訪問請求都被派送到同一個服務器上。
假設是同一個用戶user1,每次訪問都路由到同一臺服務器上,這樣即便是在負載均衡的情況下,也能保證每次訪問都能讀取到session,不需要做session數(shù)據(jù)共享了。
關鍵多臺server的原因是為負載均衡而做的,那么就得把原來負載均衡的規(guī)則假設是—a,現(xiàn)在改為按照session來均衡分發(fā)請求的規(guī)則—b。
如果這臺機子掛掉了,那么后續(xù)的請求按照session的規(guī)則還是會分發(fā)到這臺服務器上去,但是現(xiàn)在不可用了。
本來負載均衡有一個目的就是:當其中一臺機子不可用的時候,會自動分發(fā)到可用的機子上去(自動判斷現(xiàn)在要請求的機子是否可用)
因為某種規(guī)則的session都是保存在一臺服務器上,比如用戶編號是1-200涉及到的session數(shù)據(jù)保存到a服務器上去。所以只要一臺出問題,1-200的用戶就無法實現(xiàn)登錄了。后面就不可用了(可能想到1-200用戶的session服務器用多臺進行復制,這感覺很蹩腳,仍然需要用到復制的話,還不如用其他簡便的方法)
第三種思路:做一個中間層,專門來存儲所有訪問涉及到的session。也就是所有的session都存儲在這里。
服務器端統(tǒng)一從這里讀取session數(shù)據(jù)。
具體實現(xiàn)方式很多種。我的理解是,這里只是一種思想層面上的。我不知道淘寶的tbsession框架的具體實現(xiàn)。但是大致思想差不多,
由這個session框架來維護所有網(wǎng)站的session數(shù)據(jù)。我根據(jù)自己的理解,猜測淘寶的結(jié)構(gòu)畫圖大致如下:
使用這種中間層的思想來實現(xiàn)共享,具體的技術方案,我歸納為以下幾種:
1、通過NFS文件共享的方式,多臺php服務器共享保存session文件的磁盤。
通過nfs的方式,各個php服務器操作session數(shù)據(jù)的時候,是讀取本地磁盤目錄,但實際上是一個共享網(wǎng)絡文件。各個php服務器實際上操作的都是同一個目錄的文件。
具體的操作細節(jié)。到時候還需要詳細寫一下。我根據(jù)理解,畫了下面的圖:
2、保存在數(shù)據(jù)庫中,這種方式的擴展性很強,可以隨意增加WEB而不受影響。放在數(shù)據(jù)庫里面安全方面好。
其實我理解本質(zhì)是:自己寫程序(php,java都可以實現(xiàn),反正是保存在數(shù)據(jù)庫中)模擬實現(xiàn)session的機制。
具體為,把以前存儲在文件中的session數(shù)據(jù)存儲到數(shù)據(jù)庫中去,那么這樣做,其實就不用到php內(nèi)置的session機制了(像session_start()之類的函數(shù)都不需要去用了)。
寫程序要模擬的是,從數(shù)據(jù)庫拿session數(shù)據(jù),約定什么情況下數(shù)據(jù)過期了然后自動清理,這里是指刪除數(shù)據(jù)庫中的行。保存在文件中的時候,php有垃圾回收機制會去自動清理過期的session文件。
====================================弊端
放在數(shù)據(jù)庫里面,訪問量小沒有問題。大流量網(wǎng)站這么做,只會拖慢速度。因為得查詢數(shù)據(jù)庫,造成數(shù)據(jù)庫壓力大。
高并發(fā)訪問的情況下,會出現(xiàn)很大的性能問題。
有些做法跟這種思想是類似的:比如ecshop、phpcms是把session數(shù)據(jù)都存儲在數(shù)據(jù)庫中去。服務端就是從數(shù)據(jù)庫中拿session的數(shù)據(jù)。
放到數(shù)據(jù)庫存儲后,就可以實現(xiàn):多臺web服務器統(tǒng)一操作數(shù)據(jù)庫,因為數(shù)據(jù)都在數(shù)據(jù)庫,web服務器都能從數(shù)據(jù)庫進行讀取,那么session數(shù)據(jù)就能實現(xiàn)共享。
存儲在數(shù)據(jù)庫的做法,在線人數(shù)決定了其瓶頸,主要問題是影響性能。在線人數(shù),因為登錄的session數(shù)據(jù)存儲在數(shù)據(jù)庫中,只要是登錄的用戶就會涉及到頻繁操作數(shù)據(jù)庫。
我覺得小網(wǎng)站,同時1-2萬個人在線情況下。應該沒什么問題。
看網(wǎng)上丟出一個問題:對于大訪問量的網(wǎng)站,數(shù)據(jù)庫存儲session方法可行性有待商榷。
我搜尋了一些資料,理解如下:
訪問量大的話,一個用戶訪問了n多個頁面,哪怕是刷新頁面,都需要去數(shù)據(jù)庫取session數(shù)據(jù)。數(shù)據(jù)庫的承受壓力,確實很恐怖。pv是多少,就要請求多少次數(shù)據(jù)庫服務器。
訪問每個頁面都會去數(shù)據(jù)庫查詢是否登錄,或者添加數(shù)據(jù)進數(shù)據(jù)庫的sessions表
保存在文件中的時候,則交給了操作系統(tǒng)去控制。一個用戶怎么刷新頁面,查看其他頁面,都只需要讀取單個session文件(sess_74dd7807n2mfml49a1i12hkc45)。
我覺得,ecshop,discuz之類的系統(tǒng)之所以把session存儲在數(shù)據(jù)庫中去,跟網(wǎng)站的應用級別有關。他們設計的系統(tǒng)本身就是給中小站長用的,這些中小站長一般由于規(guī)模小,經(jīng)濟成本考慮,使用的是虛擬主機之類的。不具備對服務器的完全控制權(quán)限,比如還要安個memcache之類的,修改php.ini之類的都需要自己擁有獨立服務器才能操控的(vps也算,只是虛擬出來的硬件而已)。
其實真正要做到網(wǎng)站大了,系統(tǒng)承受不住了。也會自己有獨立的技術人員可以進行二次開發(fā)。
discuz這些做通用的軟件要考慮思路有個特點:得考慮大部分用戶的服務器環(huán)境。比如經(jīng)常看到源代碼里面要做php版本判斷的代碼,判斷是5.0之前的要如何處理,以求盡量適應大部分環(huán)境。而我們公司自己運營的內(nèi)部系統(tǒng),環(huán)境我們完全可控。做這些確實是多余的工作量。
另外一個點是,這些通用軟件不會為了高級用戶的特殊需求,做一些改變,結(jié)果另外一部分用戶就無法使用了。沒法兩全。所以我的理解是,他們一般不會隨便去響應站長的需求,比如你明明是一個很大用戶的站點,你用了我的系統(tǒng),還要說數(shù)據(jù)量大了承受不住,表容易損壞。你都達到某種級別的應用了,還不自己進行開發(fā)。來這里抱怨。找我按照你們方式定制,愿意給錢就好。
從這里我看到,不是說這些軟件技術含量就多好,是多么成熟的解決方案。他們針對的用戶群不同。
由于http是短連接,每次過程是:建立連接(握手)》》數(shù)據(jù)通信》》通信結(jié)束后結(jié)束連接。如果頻繁的這樣子連接后再斷開,性能會非常差。
session存儲在數(shù)據(jù)庫中,有多少pv,就要多少次這樣的數(shù)據(jù)庫連接操作(得去數(shù)據(jù)庫拿session才能知道有沒有登錄,登錄是否過時)。
3、可以將session數(shù)據(jù)保存在memcached,redis之類內(nèi)存數(shù)據(jù)庫中,memcached是基于內(nèi)存存儲數(shù)據(jù)的,性能很高,用戶并發(fā)量很大的時候尤其合適。
主要是利用內(nèi)存的數(shù)據(jù)讀取速度是很快的,與磁盤讀取的速度不是一個數(shù)量級的。
使用內(nèi)存存儲:方便統(tǒng)計在線人數(shù),內(nèi)存的速度比磁盤訪問快、內(nèi)存數(shù)據(jù)庫系統(tǒng)能夠控制內(nèi)存中的過期數(shù)據(jù)自動失效(剛好符合session過期需要)。
存儲在redis比較理想的選擇,存儲在數(shù)據(jù)庫中方便存儲統(tǒng)計在線人數(shù),那么存儲在redis中也實現(xiàn)了這個要求。
也可以存儲在memcache中。但redis支持的數(shù)據(jù)類型多。所以用它好點。
關于使用技術工具復制session數(shù)據(jù)同步到多臺服務器的方案權(quán)衡:
這種方案是,使用一些文件同步工具(linux下的rsync),當a服務器中的session數(shù)據(jù)有更改的時候,就會把這些更改也同步到b,c服務器上去。通過復制的方式,最終a,b,c各個服務器上都拷貝了一份session數(shù)據(jù)。
這種方式的弊端是,速度慢。復制數(shù)據(jù)會出現(xiàn)延遲。比如第一秒訪問是a服務器,修改了session數(shù)據(jù),負載均衡,可能下一秒訪問是b服務器,session數(shù)據(jù)如果沒有被復制到b服務器,則是讀取不到session數(shù)據(jù)的,出現(xiàn)時間上的延遲。這種復制數(shù)據(jù)要消耗很多網(wǎng)絡帶寬的。在實際中業(yè)界用得比較少。機器的數(shù)量越多,復制數(shù)據(jù)的性能損耗越大。不具備高度擴展性。
復制session的方式,無論是網(wǎng)絡帶寬成本還是硬件開銷上都很大的。
=================================結(jié)束
我寫這篇總結(jié)文章的目的,只是為了梳理知識,完善自己的知識庫。不一定正確。其中有些方式我確實沒試過,也沒有100%搞清楚細節(jié)。所以不一定完全正確。
有不當之處,期待后續(xù)完善,歡迎指正。
分享題目:session多服務器共享的方案梳理
文章地址:http://chinadenli.net/article4/cpcpie.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設、定制網(wǎng)站、網(wǎng)站導航、建站公司、網(wǎng)站維護、營銷型網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)