Session簡介
session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/訊息,例如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱為一個session。有時候我們可以看到這樣的話“在 一個瀏覽器會話期間,...”,這裡的會話一詞用的就是其本義,是指從一個瀏覽器窗口打開到關閉這個期間①。最混亂的是「使用者(客戶端)在一次會話期間」這樣一句話,它可能指使用者的一系列動作(般情況下是同某個具體目的相關的一系列動作,例如從登入到選購商品到結帳登出這樣一個網上購物的過程,有時候也被稱為一個transaction),然而有時候也可能僅僅是指一次連接,也有可能是指含義①,其中的差別只能靠上下文來推斷②。
然而當session一詞與網路協定相關聯時,它往往隱含了「面向連結」和/或「保持狀態」這樣兩個意義,「面向連結」指的是在通訊雙方在通信之前要先建立一個通信的管道,例如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你並不能確認對方的地址是否正確,通訊管道不一定能建立,但對發信人來說,通訊已經開始了。 「保持狀態」則是指通信的一方能夠把一系列的消息關聯起來,使得消息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客並且記得上次這個顧客還欠店裡一塊錢。這一類的例子有「一個TCP session」或「一個POP3 session」③。
而到了web伺服器蓬勃發展的時代,session在web開發語境下的語意又有了新的擴展,它的意義是指一類用來在客戶端與伺服器之間保持狀態的解決方案④。有時候session也用來指這種解的儲存結構,例如「把xxx放在session裡」⑤。由於各種用於web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指稱該語言的解決方案,例如經常把Java裡提供的javax.servlet.http.HttpSession簡稱為session⑥。
鑑於此混亂已無法改變,本文中session一詞的運用也會依上下文有不同的意義,請大家留意分辨。
在本文中,使用中文「瀏覽器會話期間」來表達意義①,使用「session機制」來表達意義④,使用「session」表達意義⑤,使用具體的「HttpSession」來表達意義⑥
為什麼要把SESSION保存在快取
就PHP來說,語言本身支援的session是以檔案的方式儲存到磁碟檔案中,儲存在指定的資料夾中,已儲存的路徑可以在設定檔中設置或在程式中使用函數session_save_path()進行設置,但是這麼做有弊端,
第一就是儲存到檔案系統中,效率低,只要有用到session就會從好多個檔案中找出指定的sessionid,效率很低。
第二就是當用到多台伺服器的時候可能會出現,session遺失問題(其實是儲存在其他伺服器上)了。
當然了,保存在快取中可以解決上面的問題,如果使用PHP本身的session函數,可以使用 session_set_save_handler()函數很方便的對session的處理過程進行重新控制。如果不用php的session系列函數, 可以自己寫個類似的session函數,也是可以的,我現在做的這個專案就是這樣,會根據使用者的mid、登入時間進行求hash作為sessionId,每次請求的時候都必須加上sessionId才算合法(第一次登入的時候是不需要的,這個時候會建立sessionId,回傳給客戶端),這麼做也很方便、簡潔有效率的。當然了,我這篇文章主要說的是在php自身的SESSION中」做做手腳」。
SESSION保存在快取中
php將快取保存到Redis中,可以使用設定文件,對session的處理和保存做修改,當然了,在程序中使用ini_set()函數去修改也可以,這個很方便測試,我在這裡就用這種方式,當然了,要是生產環境還是建議使用設定檔。
如果想簡單操作session入redis操作可以將一下程式碼運行一下
<?php ini_set("session.save_handler", "redis"); ini_set("session.save_path", "tcp://localhost:6379"); session_start(); header("Content-type:text/html;charset=utf-8"); $_SESSION['view'] = 'zhangsan'; echo $_SESSION['view'];
這裡設定session.save_handler方式為redis,session.save_path為redis的位址和端口,設定之後刷新,再回頭查看redis,會發現redis中的產生了sessionId,sessionId和瀏覽器請求的是一樣的,
如果是memcache
<?php ini_set("session.save_handler", "memcache"); ini_set("session.save_path", "tcp://localhost:11211"); session_start(); header("Content-type:text/html;charset=utf-8"); $_SESSION['view'] = 'zhangsan'; echo $_SESSION['view'];
也可以使用
Session_set_save_handler(‘open’,’close’,’ read’,’ write’,’ destory’,’ gc’);
用法如下自訂一個Redis_session類別
<?php class RedisSession{ private $_redis = array( 'handler' => null, //数据库连接句柄 'host' => null, //redis端口号 'port' => null, ); public function __construct($array = array()){ isset($array['host'])?$array['host']:"false"; isset($array['port'])?$array['host']:"false"; $this->_redis = array_merge($this->_redis, $array); } public function begin(){ //设置session处理函数 session_set_save_handler( array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'), array($this, 'destory'), array($this, 'gc') ); } public function open(){ $redis = new Redis(); $redis->connect($this->_redis['host'], $this->_redis['port']); if(!$redis){ return false; } $this->_redis['handler'] = $redis; $this->gc(null); return true; } //关 public function close(){ return $this->_redis['handler']->close(); } //读 public function read($session_id){ return $this->_redis['handler']->get($session_id); } //写 public function write($sessionId, $sessionData){ return $this->_redis['handler']->set($sessionId, $sessionData); } public function destory($sessionId){ return $this->_redis['handler']->delete($sessionId) >= 1 ? true : false; } public function gc(){ //获取所有sessionid,让过期的释放掉 $this->_redis['handler']->keys("*"); return true; } } $ses = new RedisSession(array('host'=>'127.0.0.1','port'=>'6379')); $ses->begin(); session_start(); $_SESSION['name']='zhangsan'; echo $_SESSION['name'];
這樣就可以實作session資料如redis程式碼執行過程中必須安裝redis才可以
以上是php中的session存入redis或memcache中的方法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!