昨天貼了這個帖子以后,有同學說我是不是寫錯了,Memcached Cache應該是分布式的Cache,怎么變成集中式了。
這里把我另外一部分的內容貼出來。
Memcached是一種集中式Cache,支持分布式橫向擴展。這里需要有點說明,很多開發者覺得Memcached是一種分布式Cache,但是其實Memcached服務端本身是單實例的,只是在客戶端實現過程中可以根據存儲的主鍵作分區存儲,而這個區就是Memcached服務端的一個或者多個實例,如果將客戶端也囊括到Memcached中,那么可以部分概念上說是集中式的。其實回顧一下集中式的構架,無非兩種情況:1.節點均衡的網狀(JBoss Tree Cache),利用JGroup的多播通信機制來同步數據。2.Master-Slaves模式(分布式文件系統),由Master來管理Slave,如何選擇Slave,如何遷移數據,都是由Master來完成,但是Master本身也存在單點問題。
總結幾個它的特點來理解一下它的優點和限制。
Memory:內存存儲,不言而喻,速度快,對于內存的要求高,不指出的話所緩存的內容非持久化。對于CPU要求很低,所以常常采用將Memcached服務端和一些CPU高消耗Memory低消耗應用部屬在一起。(作為我們AEP正好有這樣的環境,我們的接口服務器有多臺,接口服務器對于CPU要求很高(由于WS-Security),但是對于Memory要求很低,因此可以用作Memcached的服務端部屬機器)
集中式Cache:避開了分布式Cache的傳播問題,但是需要非單點保證其可靠性,這個就是后面集成中所作的cluster的工作,可以將多個Memcached作為一個虛擬的cluster,同時對于cluster的讀寫和普通的memcached的讀寫性能沒有差別。
分布式擴展:Memcached的很突出一個優點,就是采用了可分布式擴展的模式。可以將部屬在一臺機器上的多個Memcached服務端或者部署在多個機器上的Memcached服務端組成一個虛擬的服務端,對于調用者來說完全屏蔽和透明。提高的單機器的內存利用率,也提供了scale out的方式。
Socket通信:傳輸內容的大小以及序列化的問題需要注意,雖然Memcached通常會被放置到內網作為Cache,Socket傳輸速率應該比較高(當前支持Tcp和udp兩種模式,同時根據客戶端的不同可以選擇使用nio的同步或者異步調用方式),但是序列化成本和帶寬成本還是需要注意。這里也提一下序列化,對于對象序列化的性能往往讓大家頭痛,但是如果對于同一類的Class對象序列化傳輸,第一次序列化時間比較長,后續就會優化,其實也就是說序列化最大的消耗不是對象序列化,而是類的序列化。如果穿過去的只是字符串,那么是最好的,省去了序列化的操作,因此在Memcached中保存的往往是較小的內容。
特殊的內存分配機制:首先要說明的是Memcached支持最大的存儲對象為1M。它的內存分配比較特殊,但是這樣的分配方式其實也是對于性能考慮的,簡單的分配機制可以更容易回收再分配,節省對于CPU的使用。這里用一個酒窖比喻來說明這種內存分配機制,首先在Memcached起來的時候可以通過參數設置使用的總共的Memory,這個就是建造一個酒窖,然后在有酒進入的時候,首先申請(通常是1M)的空間,用來建酒架,酒架根據這個酒瓶的大小分割酒架為多個小格子安放酒瓶,將同樣大小范圍內的酒瓶都放置在一類酒架上面。例如20cm半徑的酒瓶放置在可以容納20-25cm的酒架A上,30cm半徑的酒瓶就放置在容納25-30cm的酒架B上。回收機制也很簡單,首先新酒入庫,看看酒架是否有可以回收的地方,如果有直接使用,如果沒有申請新的地方,如果申請不到,采用配置的過期策略。這個特點來看,如果要放的內容大小十分離散,同時大小比例相差梯度很明顯,那么可能對于使用空間來說不好,可能在酒架A上就放了一瓶酒,但占用掉了一個酒架的位置。
Cache機制簡單:有時候很多開源的項目做的面面俱到,但是最后也就是因為過于注重一些非必要性的功能而拖累了性能,這里要提到的就是Memcached的簡單性。首先它沒有什么同步,消息分發,兩階段提交等等,它就是一個很簡單的Cache,把東西放進去,然后可以取出來,如果發現所提供的Key沒有命中,那么就很直白的告訴你,你這個key沒有任何對應的東西在緩存里,去數據庫或者其他地方取,當你在外部數據源取到的時候,可以直接將內容置入到Cache中,這樣下次就可以命中了。這里會提到怎么去同步這些數據,兩種方式,一種就是在你修改了以后立刻更新Cache內容,這樣就會即時生效。另一種是說容許有失效時間,到了失效時間,自然就會將內容刪除,此時再去去的時候就會命中不了,然后再次將內容置入Cache,用來更新內容。后者用在一些時時性要求不高,寫入不頻繁的情況。
客戶端的重要性:Memcached是用C寫的一個服務端,客戶端沒有規定,反正是Socket傳輸,只要語言支持Socket通信,通過Command的簡單協議就可以通信,但是客戶端設計的合理十分重要,同時也給使用者提供了很大的空間去擴展和設計客戶端來滿足各種場景的需要,包括容錯,權重,效率,特殊的功能性需求,嵌入框架等等。
幾個應用點:小對象的緩存(用戶的token,權限信息,資源信息)。小的靜態資源緩存。Sql結果的緩存(這部分用的好,性能提高相當大,同時由于Memcached自身提供scale out,那么對于db scale out的老大難問題無疑是一劑好藥)。ESB消息緩存。