如何最佳地使用memcached?

Memcached是由DangaInteractive開發的,高性能的,分佈式的內存對象緩存系統,如何最佳地使用memcached,以提升站點性能?大家一起來了解一下。

一、Memcached簡介

memcached 常被用來加速應用程序的處理,在這裏,我們將着重於介紹將它部署於應用程序和環境中的最佳實踐。這包括應該存儲或不應存儲哪些、如何處理數據的靈活分佈以 及如何調節用來更新 memcached 和所存儲數據的方法。我們還將介紹對高可用性的解決方案的支持,比如 IBM WebSphere® eXtreme Scale。

所有的應用程序,特別是很多 web 應用程序都需要優化它們訪問客戶機和將信息返回至客戶機的速度。可是,通常,返回的都是相同的信息。從數據源(數據庫或文件系統)加載數據十分低效,若是每次想要訪問該信息時都運行相同的查詢,就尤顯低效。

雖然很多 web 服務器都可被配置成使用緩存發回信息,但那與大多數應用程序的動態特性無法相適。而這正是 memcached 的用武之地。它提供了一個通用的內存存儲器,可保存任何東西,包括本地語言的對象,這就讓您可以存儲各種各樣的信息並可以從諸多的應用程序和環境訪問這些信息。

二、Memcached是什麼?

memcached是一套分佈式的快取系統,當初是Danga Interactive爲了LiveJournal所發展的,但目前被許多軟件(如MediaWiki)所使用。這是一套開放源代碼軟件,以BSD license授權釋出。

memcached缺乏認證以及安全管制,這代表應該將memcached服務器放置在防火牆後。

memcached的API使用三十二位元的循環冗餘校驗(CRC-32)計算鍵值後,將資料分散在不同的機器上。當表格滿了以後,接下來新增的資料會以LRU機制替換掉。由於memcached通常只是當作快取系統使用,所以使用memcached的應用程式在寫回較慢的系統時(像是後端的數據庫)需要額外的程式碼更新memcached內的資料。

三、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 是一個開源項目,旨在利用多個服務器內的多餘 RAM 來充當一個可存放經常被訪問信息的內存緩存。這裏的關鍵是使用了術語緩存:memcached 爲加載自他處的信息提供的是內存中的暫時存儲。

比如,考慮這樣一個典型的基於 web 的應用程序。即便是一個動態網站可能也會有一些組件或信息常量是貫穿頁面整個生命週期的。在一個博客站點內,針對單個 blog post 的類別列表不大可能在頁面查看間經常性地變更。每次都通過一個對數據庫的查詢加載此信息相對比較昂貴,特別是在數據沒有更改的情況下,就更是如此。從圖 1 可以看到一個博客站點內可被緩存的頁面分區。

圖1.一個典型的博客頁面內的可緩存元素

這裏寫圖片描述
將這種結構放在 blog 站點的其他元素,poster 信息、註釋 — 設置 blog post 本身 — 進行推斷,可以看出爲了顯示主頁的內容很可能需要發生 10-20 次數據庫查詢和格式化。 每天對數百甚至數千的的頁面查看重複此過程,那麼您的服務器和應用程序執行的查詢要遠遠多於爲了顯示頁面內容所需執行的查詢。

通過使用 memcached,可以將加載自數據庫的格式化信息存儲爲一種可直接用在 Web 頁面上的格式。並且由於信息是從 RAM 而不是通過數據庫和其他處理從磁盤加載的,所以對信息的訪問幾乎是瞬時的。

再強調一下,memcached 是一個用來存儲常用信息的緩存,有了它,您便無需從緩慢的資源,比如磁盤或數據庫,加載並處理信息了。

對 memcached 的接口是通過網絡連接提供的。這意味着您可以在多個客戶機間共享單個的 memcached 服務器(或多個服務器,如本文稍後所示的)。這個網絡接口非常迅速,並且爲了改善性能,服務器會故意不支持身份驗證或安全性通信。但這不應限制部署選項。 memcached 服務器應該存在於您網絡的內部。網絡接口的實用性以及可以部署多個 memcached 實例的簡便性讓您可以使用多個機器上的多餘 RAM 來提高您緩存的整體大小。

五、存儲方法

memcached 的存儲方法是一個簡單的鍵/值對,類似於很多語言內的散列或關聯數組。通過提供鍵和值來將信息存儲到 memcached 內,通過按特定的鍵請求信息來恢復信息。

信息會無限期地保留在緩存內,除非發生如下的情況:

爲緩存分配的內存耗盡 — 在這種情況下,memcached 使用 LRU(最近最少使用)方法從此緩存刪除條目。最近未曾使用的條目會從此緩存中先刪除,最舊的最先訪問。
條目被明確刪除 — 總是可以從此緩存內刪除條目。
條目過期失效 — 各條目均有一個有效的期限以便針對此鍵存儲的信息在過於陳舊時可從緩存中清除這些條目。
上述這些情況可以與您應用程序的邏輯綜合使用以便確保緩存內的信息是最新的。有了這些基礎知識後,讓我們來看看在應用程序內如何能最好地利用 memcached。

六、何時使用memcached?

在使用 memcached 改進應用程序性能時,可以對一些關鍵的過程和步驟進行修改。

在加載信息時,典型的場景如圖 2 所示。

圖2.加載要顯示的信息的典型順序

這裏寫圖片描述

一般而言,這些步驟是:

執行一個或多個查詢來從數據庫加載信息
格式化適合於顯示(或進一步處理)的信息
使用或顯示格式化了的數據
在使用 memcached 時,爲配合這個緩存,可對應用程序的邏輯進行稍許修改:

儘量從緩存加載信息
如果存在,使用信息的被緩存版本
如果它不存在:
1、執行一個或多個查詢來從數據庫加載信息
2、格式化適合於顯示或進一步處理的信息
3、將信息存儲到緩存內
4、使用格式化了的數據
圖 3 是對這些步驟的總結。

圖3.在使用memcached時加載適合於顯示的信息
這裏寫圖片描述

數據加載成爲了至多三個步驟的一個過程,從緩存加載數據或從數據庫(視情況而定)加載數據並存儲在緩存內。

當這個過程首次發生時,數據將正常地從數據庫或其他數據源加載,然後再存儲到 memcached 內。當下一次訪問此信息時,它就會從 memcached 拉出,而不是從數據庫加載,節省了時間和 CPU 循環。

問題的另一個方面是要確保如果更改了要存儲在 memcached 內的信息,在更新後端信息的同時還要更新 memcached 的版本。這會讓圖 4 內所示的這個典型順序發生稍許變化,如 圖 5 所示。

圖4.在一個典型的應用程序內更新或存儲數據

這裏寫圖片描述

圖 5 顯示了使用 memcached 後發生了變化的流程。

圖5.在使用memcached時更新或存儲數據
這裏寫圖片描述

比如,仍以博客站點爲例,在博客系統更新數據庫內的類別列表時,更新應該遵循如下順序:

更新數據庫內的類別列表
格式化信息
將信息存儲到 memcached 內
將信息返回至客戶機
memcached 內的存儲操作是原子的,所以信息的更新不會讓客戶機只獲得部分數據;它們獲得的或者是老版本,或者是新版本。

對於大多數應用程序,這兩個操作是您惟一需要注意的。在訪問他人使用的數據時,它會自動被添加到這個緩存內,而且如果對該數據進行了更改,此緩存內也會自動進行更新。

七、鍵、名稱空間和值

memcached 另一個需要重點考慮的因素是如何組織和命名存儲在緩存內的這些數據。從之前博客站點的例子中,不難看出需要使用一種一致的命名結構以便您能加載博客類別、歷史和其他信息,然後再在加載信息(並更新緩存)時或者在更新數據(同樣也要更新緩存)時使用。

使用的何種具體的命名系統特定於應用程序,但通常可以使用一種與現有應用程序類似的結構,並且這種結構很可能基於某種惟一識別符。當從數據庫拉出信息或在整理信息集時,就會發生這種情況。

以 blog post 爲例,可以在一個具有鍵 category-list 的項中存儲類別列表。與此 post ID 對應的單個 post,比如 blogpost-29 相關的值都可以使用,而該項的註釋則可以存儲在 blogcomments-29內,其中 29 就是這個 blog post 的 ID。這樣一來, 您就可以將各種各樣的信息存儲在緩存內,使用不同的前綴來標識這些信息。

memcached 鍵/值存儲的簡便性(以及安全性的缺乏)意味着如果您想要在使用同一個 memcached 服務器的同時支持多個應用程序,那麼就可以考慮使用其他格式的量詞來標識數據屬於某種特定的應用程序。比如,可以添加像 blogapp:blogpost-29 這樣的應用程序前綴。這些鍵是沒有格式的,所以可以使用任何字符串作爲鍵的名稱。

在存儲值的方面,應該確保存儲在緩存內的信息適合於您的應用程序。比如,對於這個博客系統,您可能想要存儲被博客應用程序使用的對象以便格式化博客信息,而不是原始的 HTML。如果同一個基礎結構用在應用程序內的多個地方,這一點更具實用性。

大多數語言的接口,包括 Java™、Perl、PHP 等,都能串行化語言對象以便存儲在 memcached 內。這就讓您可以存儲並隨後從內存存儲恢復全部對象,而不是在您的應用程序內手動重構它們。 很多對象,或它們使用的結構,都基於某種散列或數組結構。對於跨語言的環境,比如在 JSP 環境和 JavaScript 環境間共享相同信息,可以使用一種架構中立的格式,比如 JavaScript Object Notation (JSON) 甚或 XML。

八、填充並使用memcached

作爲一種開源產品以及一種最初開發用來工作於現有開源環境內的產品,memcached 受大量環境和平臺支持。與 memcached 服務器通信的接口有很多,並常常具有針對所有語言的多個實現。參見參考資料 以獲得常用的庫和工具箱。

要列出所有受支持的接口和環境不太可能,但它們均支持 memcached 協議提供的基礎 API。這些描述已經被簡化並應用在不同語言的上下文內,在這些語言中,使用不同的值可指示錯誤。主要的函數有:

get(key) — 從存儲了特定鍵的 memcached 獲得信息。 如果鍵不存在,就返回錯誤。
set(key, value [, expiry]) — 使用緩存內的標識符鍵存儲這個特定的值。如果鍵已經存在,那麼它就會被更新。期滿時間的單位爲秒,並且如果值小於 30 天 (30*24*60*60),那麼就用作相對時間,如果值大於 30 天,那麼就用作絕對時間 (epoch)。
add(key, value [, expiry]) — 如果鍵不存在就將這個鍵添加到緩存內,如果鍵已經存在就返回錯誤。如果您想要顯式地添加一個新鍵而又不會因它已經存在而更新它,那麼這個函數將十分有用。
replace(key, value [, expiry]) — 更新此特定鍵的值,如果鍵不存在就返回一個錯誤。
delete(key [, time]) — 從緩存中刪除此鍵/值對。如果您提供一個時間,那麼添加具有此鍵的一個新值就會被阻塞這個特定的時期。超時讓您可以確保此值總是可以重新讀取自您的數據中心。
incr(key [, value]) — 爲特定的鍵增 1 或特定的值。只適用於數值。
decr(key [, value]) — 爲特定的鍵減 1 或特定的值,只適用於數值。
flush_all — 讓緩存內的所有當前條目無效(或到期失效)。
比如,在 Perl 內,基本 set 操作可以如清單 1 所示的那樣處理。

九、彈性和可用性

有關 memcached 最常見的一個問題是:“若緩存不可用了,會發生什麼情況呢?”正如之前章節中明示的,緩存內的信息不應該成爲信息的的惟一資源。必須要能夠從其他位置加載存儲在緩存內的數據。

雖然,無法從緩存訪問信息將會減緩應用程序的性能,但它不應該阻止應用程序的運轉。可能會發生這樣幾個場景:

如果 memcached 服務宕掉,應用程序應該回退到從原始數據源加載信息並對信息進行顯示所需的格式化。此應用程序還應繼續嘗試在 memcached 內加載和存儲信息。
一旦 memcached 服務器恢復可用,應用程序就應該自動嘗試存儲數據。沒有必要強制重載已緩存了的數據,可以使用標準的訪問來用信息加載和填充緩存。最終,緩存將會被最常用的數據重新填充。
再次重申,memcached 是信息的緩存但並非惟一的數據源。memcached 服務器不可用不應該是應用程序的終結,雖然這意味着在 memcached 服務器恢復正常之前性能會有所降低。實際上,memcached 服務器相對簡單,並且雖然不是絕對無故障的,但它的簡單性的結果就是它很少會出錯。

十、分配緩存

memcached 服務器只是網絡上針對一些鍵存儲值的一個緩存。如果有多臺機器,那麼很自然地會想要在所有多餘機器上設置一個 memcached 的實例來提供一個超大的聯網 RAM 緩存存儲。

有了這個想法後,還有一種想當然是需要使用某種分配或複製機制來在機器之間複製鍵/值對。這種方式的問題是如果這麼做反而會減少可用的 RAM 緩存,而不是增加。如圖 6 所示,可以看出這裏有三個應用程序服務器,每個服務器都可以訪問一個 memcached 實例。

圖6.多重memcached實例的不正確使用

這裏寫圖片描述

儘管每個 memcached 實例都是 1 GB 的大小(產生 3 GB 的 RAM 緩存),但如果每個應用程序服務器只有其自己的緩存(或者在 memcached 之間存在着數據的複製),那麼整個安裝也仍只能有 1 GB 的緩存在每個實例間複製。

由於 memcached 通過一個網絡接口提供信息,因此單個的客戶機可以從它所能訪問的任何一個 memcached 實例訪問數據。如果數據沒有跨每個實例被複制,那麼最終在每個應用程序服務器上,就可以有 3 GB 的 RAM 緩存可用,如圖 7 所示。

圖7.多重memcached實例的正確使用

這裏寫圖片描述

這個方法的問題是選擇哪個服務器來儲存鍵/值對,以及當想要重新獲得一個值時,如何決定要與哪個 memcached 服務器對話。問題的解決方案就是忽略複雜的東西,比如查找表,或是寄望 memcached 服務器來爲您處理這個過程。而 memcached 客戶機則必須要力求簡單。

memcached 客戶機不必決定此信息,它只需對在存儲信息時指定的鍵使用一個簡單的散列算法。當想要從一列 memcached 服務器存儲或獲取信息時,memcached 客戶機就會用一個一致的散列算法從這個鍵獲取一個數值。舉個例子,鍵 mykey 被轉換成數值 23875 。是保存還是獲取信息無關緊要,這個鍵將總是被用作惟一標識符來從 memcached 服務器加載,因此在本例中,“mykey” 散列轉化後對應的值總是 23875。

如果有兩個服務器,那麼 memcached 客戶機將對這個數值進行一個簡單的運算(例如,係數)來決定它應將此值存儲在第一個還是第二個配置了的 memcached 實例上。

當存儲一個值時,客戶機會從這個鍵確定出散列值以及它原來存儲在哪個服務器上。當獲取一個值時,客戶機會從這個鍵確定出相同的散列值並會選擇相同的服務器來獲取信息。

如果在每個應用程序服務器上使用的是相同的服務器列表(並且順序相同),那麼當需要保存或檢索同一個鍵時,每個應用程序服務器都將選擇同一個 服務器。現在,在這個例子中,有 3GB 的 memcached 空間可以共享,而不是同一個 1 GB 的空間的複製,這就帶來了更多的可用緩存,並很有可能會提高有多個用戶情況下的應用程序的性能。

十一、如何能不使用memcached?

儘管 memcached 很簡單,但 memcached 實例有時候還是會被不正確地使用。

  memcached不是一個數據庫

最常見的 memcached 誤用就是把它用作一個數據存儲,而不是一個緩存。memcached 的首要目的就是加快數據的響應時間,否則數據從其他數據源構建或恢復需要很長時間。一個典型的例子就是從一個數據庫中恢復信息,特別是在信息顯示給用戶前 需要對信息進行格式化或處理的時候。Memcached 被設計用來將信息存儲在內存中以避免每次在數據需要恢復時重複執行相同的任務。

切不可將 memcached 用作運行應用程序所需信息的惟一信息源;數據應總是可以從其他信息源獲取。此外,要記住 memcached 只是一個鍵/值的存儲。不能在數據上執行查詢,或者對內容進行迭代來提取信息。應該使用它來存儲數據塊或對象以備批量使用。

不要緩存數據庫行或文件

雖然可以使用 memcached 存儲加載自數據庫的數據行,但這實際上是查詢緩存,並且大多數數據庫都提供各自的查詢緩存的機制。其他的對象,比如文件系統的圖像或文件的情況與此相同。很多應用程序和 web 服務器針對此類工作已經有了一些很好的解決方案。

如果在加載和格式化後,使用它來存儲全部信息塊,就可以從 memcached 獲得更多的實用工具和性能上的改善。仍以我們的博客站點爲例,存儲信息的最佳點是在將博客類別格式化爲對象,甚至是在格式化成 HTML 後。博客頁面的構造可通過從 memcached 加載各個組件(比如 blog post、category list、post history 等)並將完成的 HTML 寫回至客戶機實現。

memcached並不安全

爲了確保最佳性能,memcached 並未提供任何形式的安全性,沒有身份驗證,也沒有加密。這意味着對 memcached 服務器的訪問應該這麼處理:一是通過將它們放到應用程序部署環境相同的私有側,二是如果安全性是必須的,那麼就使用 UNIX® socket 並只允許當前主機上的應用程序訪問此 memcached 服務器。

這多少犧牲了一些靈活性和彈性,以及跨網絡上的多臺機器共享 RAM 緩存的能力,但這是在目前的情況下確保 memcached 數據安全性的惟一一種解決方案。

十二、不要限制自己

除了不應該使用 memcached 實例的情況外,memcached 的靈活性不應忽視。由於 memcached 與應用程序處於相同的架構水平,所以很容易集成並連接到它。並且更改應用程序以便利用 memcached 也並不複雜。此外,由於 memcached 只是一個緩存,所以在出現問題時它不會停止應用程序的執行。如果使用正確的話,它所做的是減輕其餘服務器基礎設施的負載(減少對數據庫和數據源的讀操 作),這意味着無需更多的硬件就可以支持更多的客戶機。

但請記住,它僅僅是個緩存!

結束語

在本文中,我們瞭解了 memcached 以及如何最佳地使用它。我們看到了信息如何存儲、如何選擇合理的鍵以及如何選擇要存儲的信息。我們還討論了所有 memcached 用戶都要遇到的一些關鍵的部署問題,包括多服務器的使用、當 memcached 實例消亡時該怎麼做,以及(也許最爲重要的)在哪些情況下不能使用 memcached。

作爲一種開源的應用程序並且是目的簡單而直白的應用程序,memcached 的功能和實用性均來自於這種簡單性。通過爲信息提供巨大的 RAM 存儲空間、讓它在網絡上可用,然後再讓它可通過各種不同的接口和語言訪問到,memcached 可被集成到多種多樣的安裝和環境中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章