2006年8月15日 星期二

非mmcache!Memcached的應用:多網站伺服器 PHP 共享 Session

Standard
請注意是 Memcached 不是 mmcache,很多人搞不清楚他們兩個的不同!多半玩過 PHP 的人大概都聽過 mmcache,它是一個預編譯緩衝的 PHP 加速程式,能夠提升 PHP 的執行效能。但很少人聽過 Memcached ,因為大多人乍看之下都以為它是mmcache,使得它沒什麼機會介紹自己。事實上,若您正打算架構一個真正高負載的大型網站系統,你需要了解的並不是 mmcache,而是 memcached。

Memcached 是什麼?顧名思義,他是由記憶體(Memory)和暫存(cache)所組合起來的常駐程式(Daemon),你也可以稱它為『暫存伺服器』。 Memcached 能提供一個暫存資料的服務,透過網路供其他電腦使用。Memcached 有什麼用途?最常見的應用就是在網站伺服器的叢集,它能讓許多的網站伺服器 Session 互相流通使用。如果你正在傷透腦筋煩惱這一點,恭喜你找到解決方法了!

想要在網站伺服器的叢集中,多網站伺服器 Session 互相流通使用,首先你必須將 Memcached 架起來當 Session 分享伺服器,這邊建議你使用大的記憶體,最好是能多大就有多大,因為 Memcached 並不會以硬碟當資料暫存,而是會完全跑在記憶體上,所以若記憶被用完了,Memcached 就會無法再存放更多資料。

接著,你必須修改 PHP 的 Session Save Handler,讓 PHP 懂得利用 Memcached Server 存放 PHP 的 Session 資料並能從 Memcached Server 取出 Session 的資料。PHP提供了 session_set_save_handler() 函式讓我們能輕易修改 Session Save Handler ,以下是我修改後的 PHP 程式碼,你必須在呼叫 session_start() 之前使用:


<?

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) {
return true;
}

function close() {
return true;
}

function read($sesskey) {
global $memcache;

return $memcache->get($sesskey);
}

function write($sesskey, $data) {
global $memcache;

$memcache->set($sesskey, $data, SHARED_SESS_TIME);

return true;
}

function destroy($sesskey) {
global $memcache;

$memcache->delete($sesskey);
$memcache->flush_all();

return true;
}

function gc($maxlifetime = null) {
return true;
}
}

$GLOBALS["memcache"] = memcache();
$GLOBALS["memcache"]->add_server("192.168.1.1", 11211);
$GLOBALS["memcache"]->add_server("192.168.1.2", 11211);
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。

因為我偷懶, Memcached 的安裝方法就沒寫了,去求助 google 大神,它應該會告訴你更多詳細的安裝資料。其實 Memcached 除了可應用在 Session 共享上,也可以應用在資料庫的資料暫存緩充,降低SQL Server負擔以提升速度。Memcached多好用?就看你怎麼用了!

2006年8月5日 星期六

對於高負載資料庫的突發奇想

Standard

一直以來,我所開發的程式、系統,都是往大格局方向去規劃,但是卻往往高估了電腦硬體的能力。縱使程式被設計能夠支 持大架構的使用,電腦硬體卻總是不給面子。尤其資料庫的部份更是令人頭痛,大量的查詢、輸入、修改,都造成資料庫效能不彰。雖然 PostgreSQL 、 MySQL等資料庫系統,都號稱每秒能夠查詢幾百萬筆資料,但事實上確不是如此。可能有人會說我應該將資料表的設計做重新的規劃和分割,或是對系統做更多 的調校。但我敢問心無愧的說,大多數該做的我都做過了。

追根究底,任何機器有它能夠負荷的運算量,縱使我們做再多的最佳化,也不過是將其他用途的運算省略減少以增加我們需 要的運算效能。所以,一直以來都有人提議,將資料庫的新增修改等操作與查詢分開,或是將資料依價值時限分割移出原本的Table。雖都可以暫時解決效能問 題,但在功能操作上多了很多不便限制,也增加了系統設計上的複雜度。

市面上常討論的資料庫叢集,不外乎是Master/Slave架構,他能做的用途只不過是資料庫的備援,能迅速彌補 Master資料庫的當機。就算是多Master的架構,也不過是將操作連線分散到各主機上。不論是哪一種,對每台主機而言,每次連線所要處理查詢的負擔 根本沒變,舉例來說,若Table裡有一千萬筆資料,每次連線所要處理的資料量就是一千萬筆。

在此我有個想法,我們何不將這一千萬筆資料分散到各主機,查詢操作資料庫時,就可分散至各個主機運算,最後再合併各個主機傳回結果。如此,若我們有10台主機共同運算,每台機器只要負擔一百萬筆的資料,效能也因此可大幅提升。

本著新想法至網路上查了一些資料,卻發現Oracle已有如此的設計,看來我不是第一個想到的人。手癢的我又去查了PostgrSQL和MySQL等開放源始碼資料庫的資料,驚訝的發現,居然沒有這種功能,也難怪Oracle始終在資料庫系統市場有一番地位。

開放源始碼的社群一向以熱情和效率著稱,或許不久後的某一天,他們也會將這項功能放入他們的系統中。