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