接著,你必須修改 PHP 的 Session Save Handler,讓 PHP 懂得利用 Memcached Server 存放 PHP 的 Session 資料並能從 Memcached Server 取出 Session 的資料。PHP提供了 session_set_save_handler() 函式讓我們能輕易修改 Session Save Handler ,以下是我修改後的 PHP 程式碼,你必須在呼叫 session_start() 之前使用:
<? require_once"memcached-client.php"; define("SHARED_SESS_TIME",3600); // Timeout // Session Class by Fred class Shared_Session { function init() { ini_set("session.use_trans_sid",0); ini_set("session.gc_maxlifetime", SHARED_SESS_TIME); ini_set("session.use_cookies",1); ini_set("session.cookie_path","/"); ini_set("session.cookie_domain",".yourdomain.com.tw"); session_module_name("user"); session_set_save_handler( array("Shared_Session","open"), array("Shared_Session","close"), array("Shared_Session","read"), array("Shared_Session","write"), array("Shared_Session","destroy"), array("Shared_Session","gc") ); } function open($save_path,$session_name) { returntrue; } function close() { returntrue; } function read($sesskey) { global$memcache; return$memcache->get($sesskey); } function write($sesskey,$data) { global$memcache; $memcache->set($sesskey,$data, SHARED_SESS_TIME); returntrue; } function destroy($sesskey) { global$memcache; $memcache->delete($sesskey); $memcache->flush_all(); returntrue; } function gc($maxlifetime=null) { returntrue; } } $GLOBALS["memcache"] =new memcached(array( 'servers'=>array('127.0.0.1:11212'), 'debug'=>false, 'compress_threshold'=>10240, 'persistant'=>true)); Shared_Session::init(); ?>
其中粗字體的部分,是要特別修改的地方:
3600 是 Session 的生命周期﹝以秒為單位﹞,這應該不用再做太多解釋。
.yourdomain.com.tw 是你的網域名稱:想像一個情況若是 Loadbalance 在用戶第一次連線分配用戶到A伺服器,第二次連線分配給同一用戶到B伺服器,會導致 B 伺服器無法透過 cookies 取得 A 伺服器分配給用戶的 session_id,因為 cookies 無法跨網域存取,解決方法是必須修改 cookies 的網域設定,讓 www1.yourdomain.com.tw、www2.yourdomain.com.tw、www3.yourdomain.com.tw...等等,都可以共同存取同一個 cookies ,以取得同一個 session_id,故此時你必須設定成為『.yourdomain.com.tw』。
192.168.1.1 這是你的 Memcached Server 的 IP 位置,這裡值得提的是 add_server() 方法,你可以有多行設定許多 IP 做 Loadbalance 負載分配,前面也講到 Memcached 是純粹使用記憶體,若其中一台機器記憶體滿了,本方法可以從中找到另一台可用的機器使用。故你可以建立一個 Memcached 的叢集來處理 Session。
<?php // // +---------------------------------------------------------------------------+ // | memcached client, PHP | // +---------------------------------------------------------------------------+ // | Copyright (c) 2003 Ryan T. Dean <rtdean@cytherianage.net> | // | All rights reserved. | // | | // | Redistribution and use in source and binary forms, with or without | // | modification, are permitted provided that the following conditions | // | are met: | // | | // | 1. Redistributions of source code must retain the above copyright | // | notice, this list of conditions and the following disclaimer. | // | 2. Redistributions in binary form must reproduce the above copyright | // | notice, this list of conditions and the following disclaimer in the | // | documentation and/or other materials provided with the distribution. | // | | // | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | // | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | // | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | // | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | // | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | // | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // +---------------------------------------------------------------------------+ // | Author: Ryan T. Dean <rtdean@cytherianage.net> | // | Heavily influenced by the Perl memcached client by Brad Fitzpatrick. | // | Permission granted by Brad Fitzpatrick for relicense of ported Perl | // | client logic under 2-clause BSD license. | // +---------------------------------------------------------------------------+ // // $TCAnet$ // /** * This is the PHP client for memcached - a distributed memory cache daemon. * More information is available at http://www.danga.com/memcached/ * * Usage example: * * require_once 'memcached.php'; * * $mc = new memcached(array( * 'servers' => array('127.0.0.1:10000', * array('192.0.0.1:10010', 2), * '127.0.0.1:10020'), * 'debug' => false, * 'compress_threshold' => 10240, * 'persistant' => true)); * * $mc->add('key', array('some', 'array')); * $mc->replace('key', 'some random string'); * $val = $mc->get('key'); * * @author Ryan T. Dean <rtdean@cytherianage.net> * @package memcached-client * @version 0.1.2 */ // {{{ requirements // }}} // {{{ constants // {{{ flags /** * Flag: indicates data is serialized */ define("MEMCACHE_SERIALIZED",1<<0); /** * Flag: indicates data is compressed */ define("MEMCACHE_COMPRESSED",1<<1); // }}} /** * Minimum savings to store data compressed */ define("COMPRESSION_SAVINGS",0.20); // }}} // {{{ class memcached /** * memcached client class implemented using (p)fsockopen() * * @author Ryan T. Dean <rtdean@cytherianage.net> * @package memcached-client */ class memcached { // {{{ properties // {{{ public /** * Command statistics * * @var array * @access public */ var$stats; // }}} // {{{ private /** * Cached Sockets that are connected * * @var array * @access private */ var$_cache_sock; /** * Current debug status; 0 - none to 9 - profiling * * @var boolean * @access private */ var$_debug; /** * Dead hosts, assoc array, 'host'=>'unixtime when ok to check again' * * @var array * @access private */ var$_host_dead; /** * Is compression available? * * @var boolean * @access private */ var$_have_zlib; /** * Do we want to use compression? * * @var boolean * @access private */ var$_compress_enable; /** * At how many bytes should we compress? * * @var interger * @access private */ var$_compress_threshold; /** * Are we using persistant links? * * @var boolean * @access private */ var$_persistant; /**