一篇文章讓你深透理解cookie和session,附帶分布式WEB系統redis共用session方案

來源:互聯網
上載者:User

標籤:伺服器   情況   const   life   star   view   一個   file   foo   

cookie和session有什麼區別?這是一個很基礎的知識點,大家可能都知道一個大概:cookie是存在用戶端的,session是儲存在服務端,cookie和session用來驗證識別使用者的登入狀態,常見適用情境:使用者登入,使用者購物車資料等。偶然一次開發中遇到這些基礎的知識,還要去baidu一下,今天就做一個完整的記錄,便於以後查閱。

1.基礎概念

   cookie儲存在用戶端電腦中一般在:C:\Users\***\AppData\Local\Microsoft\Windows\Temporary Internet Files(檔案夾隱藏了),可以到自己電腦的IE設定裡面去查看,直接開啟。

我們建立一個設定cookie和session的簡單檔案實驗一下:

<?php$value = "my cookie value";// 發送一個簡單的 cookiesetcookie("TestCookie",$value,time()+3600,"/","127.0.0.1");//setcookie("TestCookie",$value, time()+3600*24);echo "setcookie Success!<br />";session_start();//views計數存在session裡面if(isset($_SESSION[‘views‘]))  $_SESSION[‘views‘]=$_SESSION[‘views‘]+1;else  $_SESSION[‘views‘]=1;echo "Views=". $_SESSION[‘views‘]."<br />";echo session_id()."<br />";print_r($_SESSION);echo "setsession Success!";?>

  訪問下,使用調試工具看看cookie:

ok,可以看見設定cookie成功了,而且在服務端也產生了相應的 session,服務端儲存session的位置一般在php.ini中可以找到:

找到相應的目錄下可以看到:session檔案以sess_***********************格式儲存,根據上面的PHPSESSID可以對應到所在的session檔案為:開啟看一下,和我們答應出來的session內容進行對比:

很明顯,這裡的內容就是$_SESSION中的內容。cookie和session整個互動過程用一張圖來表示:

或者更詳細一點:

 

在日常高並發,分布式的系統中經常會遇到一個問題,高並發請求對伺服器負載壓力過大,然後我們的方案是做負載平衡,使用nginx做反向 Proxy,多台主機(tomcat或者Apache)來做後端響應。這裡,問題就來了,多台伺服器的時候,不同的請求分發到不同的伺服器上,產生了不同的session,如果是儲存在記憶體或者檔案中,那麼就無法保持同一個使用者的登入狀態了,我們如何解決呢?

這裡要根據我們系統的實際情況進行選擇:

A.如果不是高並發,使用者很少,對session的操作不是很頻繁,我們可以選擇將session儲存在mysql資料庫中

B.如果是對效能有一定的要求,且操作頻繁,我們可以選用k/v非結構化資料庫,如:redis

若使用php語言,以上兩種方案都需要修改php.ini中session.save_handler = files 中的files改為User

關於redis 安裝和php-redis擴充的安裝請點這裡:windows下 redis和php-redis安裝

這裡我們給一份PHP的參考代碼:php中有一個session_set_save_handler()函數,可以自訂對session的操作方法,主要的幾個操作,開啟,寫入,讀取,刪除分別對應到函數的6個參數。bool session_set_save_handler ( callable $open , callable $close , callable $read , callable $write , callable $destroy, callable $gc),

session_set_save_handler 函數各參數作用如下表

參 數 描述
open 當session開啟時調用此函數。接收兩個參數,第一個參數是保持session的路徑,第二個參數是session的名字
close 當session操作完成時調用此函數。不接收參數。
read 以session ID作為參數。通過session ID從資料存放區方中取得資料,並返回此資料。如果資料為空白,可以返回一個Null 字元串。此函數在調用session_start 前被觸發
write 當資料存放區時調用。有兩個參數,一個是session ID,另外一個是session的資料
destroy 當調用session_destroy 函數時觸發destroy函數。只有一個參數 session ID
gc 當php執行session記憶體回收機制時觸發

 

同樣的使用前需要到php.ini中進行配置一下。

session管理操作類:sessionredisManage.php

<?phpclass SessionRedisManage {    private $redis;    private $sessionSavePath;    private $sessionName;    private $sessionExpireTime = 1800;    // session的有效期間,設定為1800秒    /**     * 建構函式     */    public function __construct() {        $this->redis = new Redis();    // 建立一個redis用戶端對象        $this->redis->connect(‘127.0.0.1‘, 6379) || die(‘串連redis伺服器失敗!‘);     // 串連redis伺服器        $this->redis->auth(‘foobared‘);    // 密碼驗證        $this->redis->select(0);        // 選擇0號資料庫        $retval = session_set_save_handler(                array($this, "open"),                 array($this, "close"),                 array($this, "read"),                 array($this, "write"),                 array($this, "destroy"),                 array($this, "gc")                );        session_start();    // 啟動session    }    public function open($patn, $name) {        return true;    }    public function close() {        return true;    }    public function read($id) {        $value = $this->redis->get($id);        if ($value) {            return $value;        } else {            return ‘‘;        }    }    public function write($id, $data) {        if ($this->redis->set($id, $data)) {            $this->redis->expire($id, $this->sessionExpireTime);            return true;        } else {            return false;        }    }    public function destory($id) {        if ($this->redis->delete($id)) {            return true;        } else {            return false;        }    }    public function gc($maxlifetime) {        return true;    }    public function __destruct() {        session_write_close();    }}?>

 

注意:在上面代碼中的write方法中,以sessionid作為鍵名,把session的值作為value儲存到redis中,在read方法中,以sessionid作為鍵名key,從redis中擷取值返回。而在destroy回呼函數中,則以sessionid作為key 從redis伺服器中刪除對應的session資料。 

然後,建立session_set.php和session_get.php來設定,擷取session值,我們測試一下。

session_set.php

<?phprequire ‘SessionManager.php‘;new SessionManager();    // 執行個體化對象,開啟自訂的session儲存機制$_SESSION[‘username‘] = ‘masonzhang‘;     // 寫入sessionecho "session_set success!";?>

session_get.php

<?phprequire ‘SessionManager.php‘;new SessionManager();    // 執行個體化對象,開啟自訂的session儲存機制echo $_SESSION[‘username‘];     // 擷取指定的session變數?>

  測試:先訪問session_set.php

看一下redis資料庫:

然後訪問session_get.php

 

經測試,不同頁簽均可擷取到username,說明可以跨頁面訪問。

到這裡我們這個方案能實現nginx+php+redis的session共用了。

 分享一個JAVA版本的,大家一起學習:

http://blog.csdn.net/xlgen157387/article/details/52024139

 

 

 

 

一篇文章讓你深透理解cookie和session,附帶分布式WEB系統redis共用session方案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.