Memcached深度分析_PHP教程

來源:互聯網
上載者:User

Memcached是danga.com(運營LiveJournal的技術團隊)開發的一套分布式記憶體對象緩衝系統,用於在動態系統中減少資料庫負載,提升效能。關於這個東西,相信很多人都用過,本文意在通過對memcached的實現及程式碼分析,獲得對這個出色的開源軟體更深入的瞭解,並可以根據我們的需要對其進行更進一步的最佳化。末了將通過對BSM_Memcache擴充的分析,加深對memcached的使用方式理解。

本文的部分內容可能需要比較好的數學基礎作為輔助。

◎Memcached是什麼

在闡述這個問題之前,我們首先要清楚它“不是什麼”。很多人把它當作和SharedMemory那種形式的儲存載體來使用,雖然memcached使用了同樣的“Key=>Value”方式組織資料,但是它和共用記憶體、APC等本機快取有非常大的區別。Memcached是分布式的,也就是說它不是本地的。它基於網路連接(當然它也可以使用localhost)方式完成服務,本身它是一個獨立於應用的程式或守護進程(Daemon方式)。

Memcached使用libevent庫實現網路連接服務,理論上可以處理無限多的串連,但是它和Apache不同,它更多的時候是面向穩定的持續串連的,所以它實際的並發能力是有限制的。在保守情況下memcached的最大同時串連數為200,這和Linux線程能力有關係,這個數值是可以調整的。關於libevent可以參考相關文檔。 Memcached記憶體使用量方式也和APC不同。APC是基於共用記憶體和MMAP的,memcachd有自己的記憶體配置演算法和管理方式,它和共用記憶體沒有關係,也沒有共用記憶體的限制,通常情況下,每個memcached進程可以管理2GB的記憶體空間,如果需要更多的空間,可以增加進程數。

◎Memcached適合什麼場合

在很多時候,memcached都被濫用了,這當然少不了對它的抱怨。我經常在論壇上看見有人發貼,類似於“如何提高效率”,回複是“用memcached”,至於怎麼用,用在哪裡,用來幹什麼一句沒有。memcached不是萬能的,它也不是適用在所有場合。

Memcached是“分布式”的記憶體對象緩衝系統,那麼就是說,那些不需要“分布”的,不需要共用的,或者乾脆規模小到只有一台伺服器的應用,memcached不會帶來任何好處,相反還會拖慢系統效率,因為網路連接同樣需要資源,即使是UNIX本地串連也一樣。 在我之前的測試資料中顯示,memcached本地讀寫速度要比直接PHP記憶體數組慢幾十倍,而APC、共用記憶體方式都和直接數組差不多。可見,如果只是本地級緩衝,使用memcached是非常不划算的。

Memcached在很多時候都是作為資料庫前端cache使用的。因為它比資料庫少了很多SQL解析、磁碟操作等開銷,而且它是使用記憶體來管理資料的,所以它可以提供比直接讀取資料庫更好的效能,在大型系統中,訪問同樣的資料是很頻繁的,memcached可以大大降低資料庫壓力,使系統執行效率提升。另外,memcached也經常作為伺服器之間資料共用的儲存媒介,例如在SSO系統中儲存系統單點登陸狀態的資料就可以儲存在memcached中,被多個應用共用。

需要注意的是,memcached使用記憶體管理資料,所以它是易失的,當伺服器重啟,或者memcached進程中止,資料便會丟失,所以memcached不能用來持久儲存資料。很多人的錯誤理解,memcached的效能非常好,好到了記憶體和硬碟的對比程度,其實memcached使用記憶體並不會得到成百上千的讀寫速度提高,它的實際瓶頸在於網路連接,它和使用磁碟的資料庫系統相比,好處在於它本身非常“輕”,因為沒有過多的開銷和直接的讀寫方式,它可以輕鬆應付非常大的資料交換量,所以經常會出現兩條千兆網路頻寬都滿負荷了,memcached進程本身並不佔用多少CPU資源的情況。

◎Memcached的工作方式

以下的部分中,讀者最好能準備一份memcached的原始碼。

Memcached是傳統的網路服務程式,如果啟動的時候使用了-d參數,它會以守護進程的方式執行。建立守護進程由daemon.c完成,這個程式只有一個daemon函數,這個函數很簡單(如無特殊說明,代碼以1.2.1為準):


CODE:[Copy to clipboard]#include
#include
#include

int
daemon(nochdir, noclose)
int nochdir, noclose;
{
int fd;

switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}

if (setsid() == -1)
return (-1);

if (!nochdir)
(void)chdir("/");

if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > STDERR_FILENO)
(void)close(fd);
}
return (0);
}
這個函數 fork 了整個進程之後,父進程就退出,接著重新置放 STDIN 、 STDOUT 、 STDERR 到空裝置, daemon 就建立成功了。

Memcached 本身的啟動過程,在 memcached.c 的 main 函數中順序如下:

1 、調用 settings_init() 設定初始化參數
2 、從啟動命令中讀取參數來設定 setting 值
3 、設定 LIMIT 參數
4 、開始網路 socket 監聽(如果非 socketpath 存在)( 1.2 之後支援 UDP 方式)
5 、檢查使用者身份( Memcached 不允許 root 身份啟動)
6 、如果有 socketpath 存在,開啟 UNIX 本地串連(Sock 管道)
7 、如果以 -d 方式啟動,建立守護進程(如上調用 daemon 函數)
8 、初始化 item 、 event 、狀態資訊、 hash 、串連、 slab
9 、如設定中 managed 生效,建立 bucket 數組
10 、檢查是否需要鎖定記憶體頁
11 、初始化訊號、串連、刪除隊列
12 、如果 daemon 方式,處理進程 ID
13 、event 開始,啟動過程結束, main 函數進入迴圈。

在 daemon 方式中,因為 stderr 已經被定向到黑洞,所以不會反饋執行中的可見錯誤資訊。

memcached.c 的主迴圈函數是 drive_machine ,傳入參數是指向當前的串連的結構指標,根據 state 成員的狀態來決定動作。

Memcached 使用一套自訂的協議完成資料交換,它的 protocol 文檔可以參考: http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt

在API中,分行符號號統一為

◎Memcached的記憶體管理方式

Memcached有一個很有特色的記憶體管理方式,為了提高效率,它使用預申請和分組的方式管理記憶體空間,而並不是每次需要寫入資料的時候去malloc,刪除資料的時候free一個指標。Memcached使用slab->chunk的組織方式管理記憶體。

1.1和1.2的slabs.c中的slab空間劃分演算法有一些不同,後面會分別介紹。

Slab可以理解為一個記憶體塊,一個slab是memcached一次申請記憶體的最小單位,在memcached中,一個slab的大小預設為1048576位元組(1MB),所以memcached都是整MB的使用記憶體。每一個slab被劃分為若干個chunk,每個chunk裡儲存一個item,每個item同時包含了item結構體、key和value(注意在memcached中的value是只有字串的)。slab按照自己的id分別組成鏈表,這些鏈表又按id掛在一個slabclass數組上,整個結構看起來有點像二維數組。slabclass的長度在1.1中是21,在1.2中是200。

slab有一個初始chunk大小,1.1中是1位元組,1.2中是80位元組,1.2中有一個factor值,預設為1.25

在1.1中,chunk大小表示為初始大小*2^n,n為classid,即:id為0的slab,每chunk大小1位元組,id為1的slab,每chunk大小2位元組,id為2的slab,每chunk大小4位元組……id為20的slab,每chunk大小為1MB,就是說id為20的slab裡只有一個chunk:


CODE:[Copy to clipboard]void slabs_init(size_t limit) {
int i;
int size=1;

mem_limit = limit;
for(i=0; i<=POWER_LARGEST; i++, size*=2) {
slabclass[i].size = size;
slabclass[i].perslab = POWER_BLOCK / size;
slabclass[i].slots = 0;
slabclass[i].sl_curr = slabclass[i].sl_total = slabclass[i].slabs = 0;
slabclass[i].end_page_ptr = 0;
slabclass[i].end_page_free = 0;
slabclass[i].slab_list = 0;
slabclass[i].list_size = 0;
slabclass[i].killing = 0;
}

/* for the test su

http://www.bkjia.com/PHPjc/508220.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/508220.htmlTechArticleMemcached是danga.com(運營LiveJournal的技術團隊)開發的一套分布式記憶體對象緩衝系統,用於在動態系統中減少資料庫負載,提升效能。關於這...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.