放翁(文初)的一畝三分地

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            210 隨筆 :: 1 文章 :: 320 評論 :: 0 Trackbacks
           

                 服務(wù)集成平臺5.6的性能測試進入尾聲,這期的優(yōu)化也算告一段落。這次主要的優(yōu)化工作還是在三個方面:應(yīng)用服務(wù)器(Apache,JBoss)配置,業(yè)務(wù)流程,Cache Client包(http://code.google.com/p/memcache-client-forjava/ )。這里把過去和這次優(yōu)化對于Cache的使用作一個經(jīng)驗分享,希望大家能夠用好Cache,提速你的應(yīng)用。

                 這里還是通過一些點滴的啟示來介紹優(yōu)化的一些心得,很多時候還是要根據(jù)具體情況來判斷如何去具體實施,因此這里所說的僅僅是在一些場景下適用,并非放之四海皆準的教條。同時也希望看此文的各位同學,如果有更好的思路可以給我反饋,技術(shù)在交流中才會有發(fā)展。

          積少成多,集腋成裘

                 性能提不上去,多半是在一些容易成為瓶頸的“暗點”(IO,帶寬,連接數(shù),資源競爭等等)。Memcached Cache現(xiàn)在已經(jīng)被大家廣泛使用,但是千萬不要認為對Cache的操作是低損耗的,要知道這類集中式CacheSocket連接數(shù)(會牽涉到linux操作系統(tǒng)文件句柄可用數(shù)),帶寬,網(wǎng)絡(luò)IO都是有要求的,有要求就意味著會有損失,因此積少成多,集腋成裘。服務(wù)集成平臺是一個高速的服務(wù)路由器,其大部分的業(yè)務(wù)數(shù)據(jù),訪問控制策略,安全策略以及對應(yīng)的一些控制閥值被緩存在Cache服務(wù)端,因此對于Cache的依賴性很強。每一次對于客戶端的性能提升,總會給服務(wù)集成平臺性能帶來不小的影響,但是每一次優(yōu)化速度后,客戶端可以優(yōu)化的空間越來越小,這時候需要一些策略來配合,提升應(yīng)用整體性能。當前主要采用了以下幾點策略:

          1.  從數(shù)據(jù)獲取角度來做優(yōu)化,采用本地數(shù)據(jù)緩存。(因為大家的應(yīng)用需要能夠線形擴展,支持集群,所以才不使用應(yīng)用服務(wù)器本地緩存,但是在某些緩存數(shù)據(jù)時間性不敏感或者修改幾率較小的情況下,可以采用本地緩存結(jié)合集中式緩存,減少對遠端服務(wù)器訪問次數(shù),提升應(yīng)用性能)。

          Cache ClientIMemcachedCache 接口中的public Object get(String key,int localTTL)方法就是本地數(shù)據(jù)緩存結(jié)合遠程Cache獲取數(shù)據(jù)的接口。具體流程參看下圖:

           

           

          2.  從數(shù)據(jù)更新角度,采用異步數(shù)據(jù)更新。(即不等待數(shù)據(jù)更新結(jié)果,直接進行其他業(yè)務(wù)流程)。這類操作使用場景比較局限,首先數(shù)據(jù)不會用作判斷(特別是高并發(fā)系統(tǒng)中的閥值),其次不需要返回結(jié)果作為后續(xù)流程處理輸入(例如計數(shù)器),時時性要求比較低。(這類操作其實是采用了集群數(shù)據(jù)傳播的一種策略,原先對于集群中所有節(jié)點都想即時傳播到,但是這樣對于性能損失很大,因此采用key對應(yīng)的主Node采用即時設(shè)置數(shù)據(jù),其他的通過后臺任務(wù)數(shù)據(jù)傳播來實現(xiàn),由于key對應(yīng)的主Node是數(shù)據(jù)第一操作和讀取節(jié)點,因此這類數(shù)據(jù)傳播操作時時性要求較低,適合這樣處理)。具體接口參見Cache Client 使用文檔。

          3.  一次獲取,多次使用。這點和系統(tǒng)設(shè)計有關(guān),當前服務(wù)集成平臺的安全流程是鏈狀的,一次請求會經(jīng)歷很多安全攔截器,而在每一個安全攔截器中會根據(jù)情況獲取具體的業(yè)務(wù)數(shù)據(jù)或者流程控制策略等緩存數(shù)據(jù),每一個安全攔截器都是彼此獨立的,在很早以前是每一個安全攔截器各自在需要數(shù)據(jù)的時候去遠程獲取,但是壓力測試下來發(fā)現(xiàn)請求次數(shù)相當多,而且好些重復獲取,因此將這些業(yè)務(wù)數(shù)據(jù)作為上下文在鏈式檢查中傳遞,按需獲取和設(shè)置,最大程度上復用了數(shù)據(jù)。(其實也是一種減少數(shù)據(jù)獲取的方式)。

          4.  規(guī)劃好你的Cache區(qū)。有些同學在使用Cache的時候問我是否有什么需要注意的,我覺得在使用Cache之前,針對需要緩存的數(shù)據(jù)需要做好規(guī)劃。那些數(shù)據(jù)需要放在一個Cache虛擬節(jié)點上,那些數(shù)據(jù)必須分開放。一方面是根據(jù)自己業(yè)務(wù)系統(tǒng)的數(shù)據(jù)耦合程度(未來系統(tǒng)是否需要合并或者拆分),另一方面根據(jù)數(shù)據(jù)量及讀寫頻繁度來合理分配(畢竟網(wǎng)絡(luò)IO還是稀缺資源)。當然有時候業(yè)務(wù)系統(tǒng)設(shè)計者自己也不知道未來的發(fā)展,那么最簡單的方式給Key加上前綴,當前可以合并,未來也可以拆分。同時數(shù)據(jù)粒度也需要考慮,粒度設(shè)計太小,那么交互頻繁度就會很高,如果粒度太大,那么網(wǎng)絡(luò)流量就會很大,同時將來業(yè)務(wù)模塊拆分就會有問題。

           

           

          巧用Memcached Cache特有接口

                 Memcached Cache提供了計數(shù)器一整套接口和addreplace兩個接口。這些特有接口可以很好的滿足一些應(yīng)用的高并發(fā)性處理需求。例如對于資源訪問次數(shù)控制,采用Cache的計數(shù)器接口就可以實現(xiàn)在集群中的數(shù)量控制,原本通過Cachegetput是無法解決并發(fā)問題的(就算是本地緩存一樣),這就是一組原子操作的接口。而AddReplace可以滿足無需通過get方法獲取內(nèi)容,就可以對于key是否存在的不同情況作出相應(yīng)處理,也是一種原子性操作。這些原子操作接口對于高并發(fā)系統(tǒng)在集群中的設(shè)計會很有幫助。

           

          Cache Client Cluster

                 Memcached Cache是集中式Cache,它僅僅是支持將數(shù)據(jù)能夠分片分區(qū)的存儲到一臺或者多臺的Cache Server實例中,但是這些數(shù)據(jù)并沒有作冗余,因此任何一個服務(wù)實例不可用,都會導致部分緩存數(shù)據(jù)丟失。當然很多人采取持久化等方式來保證數(shù)據(jù)的完整性,但是這種方式對于效率以及恢復的復雜性都會有影響。

                 簡單的來想,為什么不把數(shù)據(jù)在多保存一份或者多份呢,當其中一份不可用的情況下,就用另外一份補上。這就是最原始的Cache Client Cluster的構(gòu)想。在這里具體的設(shè)計細節(jié)就不多說了,主要說一下幾個要點,也讓使用Cache Client Cluster的同學有大致的一個了解。

                 先來看看Cache Cluster的結(jié)構(gòu)圖:




                 這張圖上需要注意四個角色:Application(使用Cache的應(yīng)用),Cache ClusterCache配置的虛擬集群),Cache NodeCache的虛擬節(jié)點,在同一個Cluster中的Cache Node數(shù)據(jù)保持完全一致),Cache InstanceCache虛擬節(jié)點中實際包含的Memcached Cache服務(wù)端實例)。

                 應(yīng)用僅僅操作Cache Node,不了解具體數(shù)據(jù)存儲或數(shù)據(jù)獲取是操作哪一個Cache 服務(wù)端實例。(這點也就是Memcached Cache可擴展性的基礎(chǔ)設(shè)計)。Cache Cluster又將多個Cache Node組成了虛擬的集群,通過數(shù)據(jù)冗余,保證了服務(wù)可用性和數(shù)據(jù)完整性。

           

                 當前 Cache Client Cluster主要有兩種配置模式:active standby。(這里是借鑒了硬件的名詞,其實并不完全一樣,因為還是考慮到了效率問題)

                 Cache Client Cluster主要的功能點:

          1.  容錯。當被分配到讀取或者操作數(shù)據(jù)的Cache虛擬節(jié)點不可用的情況下,集群其他節(jié)點支持代替錯誤節(jié)點服務(wù)于客戶端應(yīng)用。

          2.  數(shù)據(jù)冗余。當操作集群中某一個Cache虛擬節(jié)點時,數(shù)據(jù)會異步傳播到其他集群節(jié)點。

          3.  軟負載。客戶端通過對操作的key作算法(當前采用簡單的key hash再取余的方式)選擇集群中的節(jié)點,達到集群中節(jié)點簡單的負載分擔。同時也由于這種模式,可以使得key都有默認的第一操作節(jié)點,此節(jié)點的操作保持時時更新,而其他節(jié)點可以通過客戶端異步更新來實現(xiàn)效率提升。

          4.  數(shù)據(jù)恢復。當集群中某一節(jié)點失效后恢復時,其數(shù)據(jù)可能已經(jīng)完全丟失,此時通過配置成為Active模式可以將其他節(jié)點上冗余的數(shù)據(jù)Lazy復制到該節(jié)點(獲取一個復制一個,同時只支持一個冗余節(jié)點的數(shù)據(jù)獲取(不采取遍歷,防止低效))。

           

          Active模式擁有1,2,3,4的特性。Standby模式擁用1,2,3特性。(其實本來只考慮讓Standby擁有1特性)。未來不排除還會有更多需要的特性加入。Activekey不存在的情況下會有些低效,因為會判斷一個冗余節(jié)點是否存在內(nèi)容,然后決定是否修復當前節(jié)點。(考慮采用短期失敗標示之類的,不過效率不一定高,同時增加了復雜度)

           

           

          運行期動態(tài)擴容部署

                 Memcached cache客戶端算法中比較出名的是Consistent Hashing算法,其目的也就是為了在節(jié)點增加或者減少以后,通過算法盡量減小數(shù)據(jù)重新分布的代價。采用虛擬節(jié)點,環(huán)狀和二叉樹等方式可以部分降低節(jié)點增加和減少對于數(shù)據(jù)分布的影響,但是始終還是有部分數(shù)據(jù)會失效,這點還是由于Memcached Cache是集中式Cache所決定的。

                 但如果有了Cache Cluster的話,數(shù)據(jù)有了冗余,就可以通過逐步修改集群中虛擬節(jié)點配置,達到對于單個虛擬節(jié)點的配置動態(tài)擴容。

                 支持動態(tài)部署前提:

          配置文件動態(tài)加載。(配置文件可以在Classpath中,也可以是Http資源的方式)通過Cache Client Cache Manager可以停止Cache 服務(wù),重新加載配置文件,即時生效。

          當前動態(tài)部署的兩種方式:

          1.              修改集群配置中某一套虛擬節(jié)點的服務(wù)實例配置(socketPool配置),增加或者減少后端數(shù)據(jù)存儲實例。然后動態(tài)加載新的配置文件(可以通過指定遠端的http配置作為新的配置文件),通過集群的lazy的修復方式,逐漸的將數(shù)據(jù)從冗余節(jié)點復制到新的節(jié)點上來,最終實現(xiàn)數(shù)據(jù)遷移。

          2.              修改集群配置中某一套虛擬節(jié)點的服務(wù)實例配置(socketPool配置),增加或者減少后端數(shù)據(jù)存儲實例。然后動態(tài)加載新的配置文件(可以通過指定遠端的http配置作為新的配置文件),在調(diào)用Cache Manager主動將數(shù)據(jù)由某一虛擬節(jié)點復制到指定的集群中,實現(xiàn)數(shù)據(jù)批量遷移,然后根據(jù)需要看是否需要修改其他幾套虛擬節(jié)點配置。

           

          存在的問題:

          1.       當前沒有做到不停止服務(wù)來動態(tài)部署。(后續(xù)考慮實現(xiàn),當前將編譯配置和重新啟動服務(wù)器的工作節(jié)省了)

          2.       不論是lazy復制還是批量數(shù)據(jù)遷移,都是會將原本有失效時間的數(shù)據(jù)變成了無失效時間的數(shù)據(jù)。(這個問題暫時還沒有一種可行的高效的方式解決)

           

           

          后話

                 性能優(yōu)化這點事還是那句老話,需要了再去做也不遲。同時如果你開發(fā)的是一個每天服務(wù)訪問量都是上億,甚至更高的系統(tǒng),那么有時候斤斤計較會收獲不少。(當然是不影響系統(tǒng)本身業(yè)務(wù)流程的基礎(chǔ))。

                 Cache客戶端自從作為開源放在Google上也收到了不少朋友的支持和反饋,同時自己業(yè)務(wù)系統(tǒng)以及其他部門同學的使用促使我不斷的去優(yōu)化和滿足必要的一些功能擴展(但是對于Cache來說,還是那句話,簡單就是美,高效是使用Cache的最原始的需求)。

                 當前Cache Client版本已經(jīng)到了2.5版本,在Google上有詳細的Demo(單元測試,壓力測試,集群測試)和說明使用文檔。是否速度會慢于其他Memcached客戶端,這不好說的很絕對,反正大家自己拉下去比較一下看看就知道了,當然為了集群和其他的一些必要的附加功能還是做了一些性能犧牲。

           

          項目地址在:http://code.google.com/p/memcache-client-forjava/

          在首頁的右側(cè)有demo,doc,binary,src的鏈接,直接可以下載使用和察看。希望對需要的同學有幫助。

          posted on 2009-04-28 23:19 岑文初 閱讀(3383) 評論(6)  編輯  收藏

          評論

          # re: 用好Cache,優(yōu)化應(yīng)用 2009-04-29 05:33 estetik
          thank you very good site  回復  更多評論
            

          # re: 用好Cache,優(yōu)化應(yīng)用 2009-04-29 18:36 BeanSoft
          yeah baby, good intro.  回復  更多評論
            

          # re: 用好Cache,優(yōu)化應(yīng)用 2009-04-30 16:49 fanweixiao
          Concurrent Hashing這里似乎應(yīng)該是Consistent Hashing吧?  回復  更多評論
            

          # re: 用好Cache,優(yōu)化應(yīng)用 2009-04-30 17:12 岑文初
          寫錯了,真是的啊。  回復  更多評論
            

          # re: 用好Cache,優(yōu)化應(yīng)用 2009-06-23 16:12 kimfly
          您好,看了你的文章后,受益很大,動手一試,遇到問題希望能夠解答下
          我定義了兩個cache
          <client name="mclient0" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0"> <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler> </client>
          <client name="mclient1" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0"> <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler> </client>
          如果這兩個cache緩存了同一個key的對象,好像后面的那個put動作會把前面那個沖掉,請問下Memcached中各個cache不是隔離的嗎,原來用ehcache是可以put同一個key,各個緩存是隔離開的。
            回復  更多評論
            

          # 幾個問題 2009-07-16 17:54 gengmao
          1.local cache如何invalidate?
          2.cache cluster的架構(gòu)和terracotta類似,有沒有測試replication的開銷?能夠scale到很多數(shù)量的節(jié)點嗎?
          3.花這么大力氣確保cache高可用性有實際意義么?cache難免會失效,即使丟失一部分cache也不應(yīng)該是很嚴重的事。處理memcached故障可以很簡單,重啟或啟動配用memcached服務(wù)器即可。cluster的恢復能這么簡單么?
            回復  更多評論
            


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 乐昌市| 泽库县| 山阳县| 任丘市| 平湖市| 东城区| 化州市| 南陵县| 合阳县| 高青县| 成安县| 蓝山县| 彰化市| 沭阳县| 永嘉县| 峨山| 望都县| 桦川县| 余姚市| 阜平县| 和龙市| 县级市| 资源县| 江津市| 都匀市| 遵义市| 固始县| 互助| 东安县| 饶阳县| 淅川县| 罗城| 鹤壁市| 鲁甸县| 涟水县| 隆回县| 资中县| 奇台县| 调兵山市| 于都县| 湘潭市|