【正文】
d適合什么場合在很多時(shí)候,memcached都被濫用了,這當(dāng)然少不了對(duì)它的抱怨。 Memcached內(nèi)存使用方式也和APC不同。在保守情況下memcached的最大同時(shí)連接數(shù)為200,這和Linux線程能力有關(guān)系,這個(gè)數(shù)值是可以調(diào)整的。它基于網(wǎng)絡(luò)連接(當(dāng)然它也可以使用localhost)方式完成服務(wù),本身它是一個(gè)獨(dú)立于應(yīng)用的程序或守護(hù)進(jìn)程(Daemon方式)。很多人把它當(dāng)作和SharedMemory那種形式的存儲(chǔ)載體來使用,雖然memcached使用了同樣的“Key=Value”方式組織數(shù)據(jù),但是它和共享內(nèi)存、APC等本地緩存有非常大的區(qū)別。本文的部分內(nèi)容可能需要比較好的數(shù)學(xué)基礎(chǔ)作為輔助。關(guān)于這個(gè)東西,相信很多人都用過,本文意在通過對(duì)memcached的實(shí)現(xiàn)及代碼分析,獲得對(duì)這個(gè)出色的開源軟件更深入的了解,并可以根據(jù)我們的需要對(duì)其進(jìn)行更進(jìn)一步的優(yōu)化。ve had production Memcached servers up for 4–5 months at a time, averaging 7,000 queries/second, without problems and maintaining consistently low CPU usage.Another key requirement for Memcached was that it be lockless. All objects are multiversioned internally and reference counted, so no client can block any other client39。 Memcache實(shí)現(xiàn)分析理解 實(shí)現(xiàn)結(jié)構(gòu)SpeedOf course, the primary motivation for caching is speed, so Memcached is designed to be as fast as possible. The initial prototype of Memcached was written in Perl. Although I love Perl, the prototype was laughably slow and bloated. Perl trades off memory usage for everything, so a lot of precious memory was wasted, and Perl can39。分布式存儲(chǔ)及應(yīng)用系統(tǒng)架構(gòu)分析目 錄1 Memcached Memcached架構(gòu)memcached是高性能的分布式內(nèi)存緩存服務(wù)器。 一般的使用目的是,通過緩存數(shù)據(jù)庫查詢結(jié)果,減少數(shù)據(jù)庫訪問次數(shù),以提高動(dòng)態(tài)Web應(yīng)用的速度、 提高可擴(kuò)展性。t handle tons of network connections at once.The current version is written in C as a singleprocess, singlethreaded, asynchronous I/O, eventbased d?mon. For portability and speed, we use libevent (see the online Resources section) for event notification. The advantage of libevent is that it picks the best available strategy for dealing with file descriptors at runtime. For example, it chooses kqueue on BSD and epoll on Linux , which are efficient when dealing with thousands of concurrent connections. On other systems, libevent falls back to the traditional poll and select methods.Inside Memcached, all algorithms are O(1). That is, the runtime of the algorithms and CPU used never varies with the number of concurrent clients, at least when using kqueue or epoll, or with the size of the data or any other factor.Of note, Memcached uses a slab allocator for memory allocation. Early versions of Memcached used the malloc from glibc and ended up falling on their faces after about a week, eating up a lot of CPU space due to address space fragmentation. A slab allocator allocates only large chunks of memory, slicing them up into little chunks for particular classes of items, then maintaining freelists for each class whenever an object is freed. See the Bonwick paper in Resources for more details. Memcached currently generates slab classes for all poweroftwo sizes from 64 bytes to 1MB, and it allocates an object of the smallest size that can hold a submitted item. As a result of using a slab allocator, we can guarantee performance over any length of time. Indeed, we39。s actions. If one client is updating an object stored in Memcached while a dozen others are downloading it, even with one client on a lossy network connection dropping half its packets, nobody has to wait for anybody else.A final optimization worth noting is that the protocol allows fetching multiple keys at once. This is useful if your application knows it needs to load a few hundred keys. Instead of retrieving them all sequentially, which would take a fraction of a second in network roundtrips, the application can fetch them all in one request. When necessary, the client libraries automatically split multikey loads from the application into separate parallel multikey loads to the Memcached instances. Alternatively, applications can provide explicit hash values with keys to keep groups of data on the same instance. That also saves the client library a bit of CPU time by not needing to calculate hash values.Ref:,2(運(yùn)營LiveJournal的技術(shù)團(tuán)隊(duì))開發(fā)的一套分布式內(nèi)存對(duì)象緩存系統(tǒng),用于在動(dòng)態(tài)系統(tǒng)中減少數(shù)據(jù)庫負(fù)載,提升性能。末了將通過對(duì)BSM_Memcache擴(kuò)展的分析,加深對(duì)memcached的使用方式理解?!騇emcached是什么在闡述這個(gè)問題之前,我們首先要清楚它“不是什么”。Memcached是分布式的,也就是說它不是本地的。Memcached使用libevent庫實(shí)現(xiàn)網(wǎng)絡(luò)連接服務(wù),理論上可以處理無限多的連接,但是它和Apache不同,它更多的時(shí)候是面向穩(wěn)定的持續(xù)連接的,所以它實(shí)際的并發(fā)能力是有限制的。關(guān)于libevent可以參考相關(guān)文檔。APC是基于共享內(nèi)存和MMAP的,memcachd有自己的內(nèi)存分配算法和管理方式,它和共享內(nèi)存沒有關(guān)系,也沒有共享內(nèi)存的限制,通常情況下,每個(gè)memcached進(jìn)程可以管理2GB的內(nèi)存空間,如果需要更多的空間,可以增加進(jìn)程數(shù)。我經(jīng)常在論壇上看見有人發(fā)貼,類似于“如何提高效率”,回復(fù)是“用memcached”,至于怎么用,用在哪里,用來干什么一句沒有。Memcached是“分布式”的內(nèi)存對(duì)象緩存系統(tǒng),那么就是說,那些不需要“分布”的,不需要共享的,或者干脆規(guī)模小到只有一臺(tái)服務(wù)器的應(yīng)用,memcached不會(huì)帶來任何好處,相反還會(huì)拖慢系統(tǒng)效率,因?yàn)榫W(wǎng)絡(luò)連接同樣需要資源,即使是UNIX本地連接也一樣??梢姡绻皇潜镜丶?jí)緩存,使用memcached是非常不劃算的。因?yàn)樗葦?shù)據(jù)庫少了很多SQL解析、磁盤操作等開銷,而且它是使用內(nèi)存來管理數(shù)據(jù)的,所以它可以提供比直接讀取數(shù)據(jù)庫更好的性能,在大型系統(tǒng)中,訪問同樣的數(shù)據(jù)是很頻繁的,memcached可以大大降低數(shù)據(jù)庫壓力,使系統(tǒng)執(zhí)行效率提升。需要注意的是,memcached使用內(nèi)存管理數(shù)據(jù),所以它是易失的,當(dāng)服務(wù)器重啟,或者memcached進(jìn)程中止,數(shù)據(jù)便會(huì)丟失,所以memcached不能用來持久保存數(shù)據(jù)?!騇emcached的工作方式以下的部分中,讀者最好能準(zhǔn)備一份memcached的源代碼。這個(gè)程序只有一個(gè)daemon函數(shù),這個(gè)函數(shù)很簡單(如無特殊說明,):CODE:include include include intdaemon(nochdir, noclose) int nochdir, noclose。 switch (fork()) { case 1: return (1)。 default: _exit(0)。 if (!nochdir) (void)chdir(”/”)。amp。 (void)dup2(fd, STDOUT_FILENO)。 if (fd STDERR_FILENO) (void)close(fd)。}這個(gè)函數(shù) fork 了整個(gè)進(jìn)程之后,父進(jìn)程就退出,接著重新定位 STDIN 、 STDOUT 、 STDERR 到空設(shè)備, daemon 就建立成功了。 在 daemon 方式中,因?yàn)?stderr 已經(jīng)被定向到黑洞,所以不會(huì)反饋執(zhí)行中的可見錯(cuò)誤信息。 Memcached 使用一套自定義的協(xié)議完成數(shù)據(jù)交換,它的 protocol 文檔可以參考: 在API中,換行符號(hào)統(tǒng)一為\r\n◎Memcached的內(nèi)存管理方式Memcached有一個(gè)很有特色的內(nèi)存管理方式,為了提高效率,它使用預(yù)申請(qǐng)和分組的方式管理內(nèi)存空間,而并不是每次需要寫入數(shù)據(jù)的時(shí)候去malloc,刪除數(shù)據(jù)的時(shí)候free一個(gè)指針。,后面會(huì)分別介紹。每一個(gè)slab被劃分為若干個(gè)chunk,每個(gè)chunk里保存一個(gè)item,每個(gè)item同時(shí)包含了item結(jié)構(gòu)體、key和value(注意在memcached中的value是只有字符串的)。slab有一個(gè)初始chunk大小,chunk大小表示為初始大小*2^n,n為classid,即:id為0的slab,每chunk大小1字節(jié),id為1的slab,每chunk大小2字節(jié),id為2的slab,每chunk大小4字節(jié)……id為20的slab,每chunk大小為1MB,就是說id為20的slab里只有一個(gè)chunk:CODE:void slabs_init(size_t limit) { int i。 mem_limit = limit。 i=POWER_LARGEST。 slabclass[i].perslab = POWER_BLOCK / size。 slabclass[i].sl_curr = slabclass[i].sl_total = slabclass[i].slabs = 0。 slabclass[i].end_page_free = 0。 slabclass[i].list_size = 0。 } /* for the test suite: faking of how much we’ve already