srcacheNginx 的緩存模塊
我們知道,Nginx的核心設(shè)計(jì)思想是事件驅(qū)動的非阻塞I/O。Nginx被設(shè)計(jì)為可以配置I/O多路復(fù)用策略,在Unix系統(tǒng)中傳統(tǒng)的多路復(fù)用是采用select或poll,但是這兩個方法的問題是隨著監(jiān)聽socket的增加,性能會下降,因?yàn)樵趌inux內(nèi)核中是采用輪詢的方式判斷是否可以觸發(fā)事件,換句話說算法的復(fù)雜度為O(N),而在較新的linux內(nèi)核中引入了復(fù)雜度為O(1)的epoll,因此Nginx在Linux下默認(rèn)采用epoll,而在FreeBSD下默認(rèn)采用kqueue作為I/O策略。
即便是這樣,傳統(tǒng)的緩存策略仍可能造成效率低下,因?yàn)閭鹘y(tǒng)上是通過PHP操作memcache的,要執(zhí)行PHP代碼,Nginx就必然要和FastCGI通信,同時也要進(jìn)入PHP的生命周期,因此SAPI、PHP Core和Zend Engine的一系列邏輯會被執(zhí)行。更糟糕的是,fpm和PHP可能會阻塞,因此破壞了Nginx的非阻塞性。(原文中此處表述有誤,fastcgi與nginx進(jìn)行同步通信,但并不會破壞nginx i/o的非阻塞性,多謝agentzh給予指正)下圖展示了在memcache命中時整個處理過程。
可以看到,即使memcache命中,還是要進(jìn)入PHP的生命周期。我們知道,目前很多互聯(lián)網(wǎng)應(yīng)用都使用RESTful規(guī)范進(jìn)行設(shè)計(jì),在RESTful應(yīng)用下,普遍使用uri和查詢參數(shù)作為緩存的key,因此一種更高效的緩存策略是Nginx直接訪問memcache,并用$uri和$args等Nginx內(nèi)置變量設(shè)定緩存key規(guī)則,這樣,當(dāng)緩存命中時,Nginx可以跳過通過fastcgi和PHP通信的過程,直接從memcache中獲取數(shù)據(jù)并返回。memc-nginx和srcache-nginx正是利用這種策略提高了緩存的效率。下圖是這種高效緩存策略的示意圖(當(dāng)memcache命中時)。
模塊介紹
memc-nginx和srcache-nginx模塊均為前淘寶工程師agentzh(章亦春)開發(fā)。其中memc模塊擴(kuò)展了Nginx標(biāo)準(zhǔn)的memcache模塊,增加了set、add、delete等memcache命令,而srcache則是為location增加了透明的基于subrequest的緩存層。兩者配合使用,可以實(shí)現(xiàn)上一節(jié)提到的高效緩存機(jī)制。關(guān)于兩個模塊的詳細(xì)信息可以參考它們Nginx官網(wǎng)的wiki(memc wiki,srcache wiki)頁。
