<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

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

    Author:文初

    Email: wenchu.cenwc@alibaba-inc.com

    Blog: http://blog.csdn.net/cenwenchu79/

     

             MemCached Cache在大型網(wǎng)站被應(yīng)用得越來(lái)越廣泛,不同語(yǔ)言的客戶端也都在官方網(wǎng)站上有提供,但是Java的選擇并不多。由于現(xiàn)在的MemCached Cache服務(wù)端是用C寫(xiě)的,因此我這個(gè)C不太熟悉的人也就沒(méi)有辦法去優(yōu)化它,當(dāng)然對(duì)于它的內(nèi)存分配機(jī)制等細(xì)節(jié)還是有所了解,因此在使用的時(shí)候也會(huì)十分注意,這些文章Google一把應(yīng)該也有很多了。這里就說(shuō)說(shuō)對(duì)于MemCache Java客戶端的優(yōu)化的兩個(gè)階段。

     

    First Stage

           我也和其他使用Memcached Cache的同學(xué)一樣,看了官方網(wǎng)站的內(nèi)容,然后去下載了whalin memcached Client,后來(lái)Stat的時(shí)候遇到問(wèn)題,就給作者發(fā)了郵件說(shuō)明了情況,作者讓我下載 2.0.1 版本,這個(gè)版本也是比較不錯(cuò)的一個(gè)版本,后續(xù)的封裝也是基于這個(gè)版本之上。

             第一階段主要是在whalin的客戶端作了再次封裝。

    1.       Cache服務(wù)接口化。

    定義了IMemCache接口,在應(yīng)用部分僅僅只是使用接口,為將來(lái)替換Cache服務(wù)實(shí)現(xiàn)提供基礎(chǔ)。

    2.       使用配置代替代碼初始化客戶端。

    通過(guò)配置客戶端和SocketIO Pool屬性,直接交管由CacheManager來(lái)維護(hù)Cache Client Pool的生命周期,方便實(shí)用以及單元測(cè)試。

    3.       KeySet的實(shí)現(xiàn)。

    對(duì)于MemCached來(lái)說(shuō)本身是不提供KeySet的方法的,在接口封裝初期,同事向我提出這個(gè)需求的時(shí)候,我個(gè)人覺(jué)得也是沒(méi)有必要提供,因?yàn)?/span>Cache輪詢是比較低效的,同時(shí)這類場(chǎng)景,往往可以去數(shù)據(jù)源獲取KeySet,而不是從MemCached去獲取。但是SIP的一個(gè)場(chǎng)景的出現(xiàn),讓我不得不去實(shí)現(xiàn)了KeySet

    SIP在作服務(wù)訪問(wèn)頻率控制的時(shí)候需要記錄在控制間隔期內(nèi)的訪問(wèn)次數(shù)和流量,此時(shí)由于是集群,因此數(shù)據(jù)必須放在集中式的存儲(chǔ)或者緩存中,數(shù)據(jù)庫(kù)肯定是撐不住這樣大數(shù)據(jù)量的更新頻率的,因此考慮使用Memcached的很出彩的操作,全局計(jì)數(shù)器(storeCounter,getCounter,inc,dec),但是在檢查計(jì)數(shù)器的時(shí)候如何去獲取當(dāng)前所有的計(jì)數(shù)器,曾考慮使用DB或者文件,但是效率還是問(wèn)題,同時(shí)如果放在一個(gè)字段中并發(fā)還是有問(wèn)題。因此不得不實(shí)現(xiàn)了KeySet,在使用KeySet的時(shí)候有一個(gè)參數(shù),類型是Boolean,這個(gè)字段的存在是因?yàn)椋?/span>Memcached中數(shù)據(jù)的刪除并不是直接刪除,而是標(biāo)注一下,這樣會(huì)導(dǎo)致實(shí)現(xiàn)keySet的時(shí)候取出可能已經(jīng)刪除的數(shù)據(jù),如果對(duì)于數(shù)據(jù)嚴(yán)謹(jǐn)性要求低,速度要求高,那么不需要再去驗(yàn)證key是否真的有效,如果要求key必須正確存在,就需要再多一次的輪詢查找。

    4.       Cluster的實(shí)現(xiàn)。

    Memcached作為集中式Cache,就存在著集中式的致命問(wèn)題:?jiǎn)吸c(diǎn)問(wèn)題,Memcached支持多Instance分布在多臺(tái)機(jī)器上,僅僅只是解決了數(shù)據(jù)全部丟失的問(wèn)題,但是當(dāng)其中一臺(tái)機(jī)器出錯(cuò)以后,還是會(huì)導(dǎo)致部分?jǐn)?shù)據(jù)的丟失,一個(gè)籃子掉在地上還是會(huì)把部分的雞蛋打破。

    因此就需要實(shí)現(xiàn)一個(gè)備份機(jī)制,能夠保證Memcached在部分失效以后,數(shù)據(jù)還能夠依然使用,當(dāng)然大家很多時(shí)候都用Cache不命中就去數(shù)據(jù)源獲取的策略,但是在SIP的場(chǎng)景中,如果部分信息找不到就去數(shù)據(jù)庫(kù)查找,那么要把SIP弄垮真的是很容易,因此SIP對(duì)于Memcached中的數(shù)據(jù)認(rèn)為是可信的,因此做Cluster也是必要的。



    (1)              應(yīng)用傳入需要操作的key,通過(guò)CacheManager獲取配置在Cluster中的客戶端。

    (2)              當(dāng)獲得Cache Client以后,執(zhí)行Cache操作。

    (3)              A.如果是讀取操作,當(dāng)不能命中時(shí)去集群其他Cache客戶端獲取數(shù)據(jù),如果獲取到數(shù)據(jù),嘗試寫(xiě)入到本次獲得的Cache客戶端,并返回結(jié)果。(達(dá)到數(shù)據(jù)恢復(fù)的作用)

    B.如果是更新操作,在本次獲取得Cache客戶端執(zhí)行更新操作以后,立即返回,將更新集群其他機(jī)器命令提交給客戶端的異步更新線程對(duì)列去異步執(zhí)行。(由于如果是根據(jù)key來(lái)獲取Cache,那么異步執(zhí)行不會(huì)影響到此主鍵的查詢操作)

    存在的問(wèn)題:如果是設(shè)置了Timeout的數(shù)據(jù),那么在丟失以后被復(fù)制的過(guò)程中就會(huì)變成永久有效的內(nèi)容。

    5.       LocalCache結(jié)合Memcached使用,提高數(shù)據(jù)獲取效率。

    在第一次壓力測(cè)試過(guò)程中,發(fā)現(xiàn)和原先預(yù)料的一樣,Memcached并不是完全無(wú)損失的,Memcached是通過(guò)Socket數(shù)據(jù)交互來(lái)進(jìn)行通信的,因此機(jī)器的帶寬,網(wǎng)絡(luò)IOSocket連接數(shù)都是制約Memcached發(fā)揮其作用的障礙。Memcache的一個(gè)突出優(yōu)點(diǎn)就是Timeout的設(shè)置,也就是放入進(jìn)去的數(shù)據(jù)可以設(shè)置有效期,自動(dòng)會(huì)失效,這樣對(duì)于一些不敏感的數(shù)據(jù)就可以在一定的容忍時(shí)間內(nèi)不去更新,提高效率。根據(jù)這個(gè)思想,其實(shí)在集群中的每一個(gè)Memcached客戶端也可以使用本地的Cache,來(lái)緩存獲取過(guò)的數(shù)據(jù),設(shè)置一定的失效時(shí)間,來(lái)減少對(duì)于Memcached的訪問(wèn)次數(shù),提高整體性能。

             因此,在每一個(gè)客戶端中內(nèi)置了一個(gè)有超時(shí)機(jī)制的本地緩存(采用lazy timeout機(jī)制),在獲取數(shù)據(jù)的時(shí)候,首先在本地查詢數(shù)據(jù)是否存在,如果不存在則再向Memcache發(fā)起請(qǐng)求,獲得數(shù)據(jù)以后,將其緩存在本地,并設(shè)置有效時(shí)間。方法定義如下:

    /**

                * 降低memcache的交互頻繁造成的性能損失,因此采用本地cache結(jié)合memcache的方式

                * @param key

                * @param 本地緩存失效時(shí)間單位秒

                * @return

         */

        public Object get(String key,int localTTL);

     

     

    Second Stage

             第一階段的封裝基本上已經(jīng)可以滿足現(xiàn)有的需求,也被自己的項(xiàng)目和其他產(chǎn)品線使用,但是不經(jīng)意的一句話,讓我開(kāi)始了第二階段的優(yōu)化。單位里面有個(gè)同學(xué)說(shuō)Memcache客戶端里面在SocketIO代碼里面有太多的synchronized,多多少少會(huì)影響性能。雖然過(guò)去看過(guò)這部分代碼,但是當(dāng)時(shí)只是關(guān)注里面的Hash算法,那天回去后一看,果然有不少的synchronized,可能是與客戶端當(dāng)時(shí)寫(xiě)的時(shí)候Jdk版本較早的緣故造成的,現(xiàn)在Concurrent包被廣泛應(yīng)用,因此優(yōu)化并不是一件很難的事情。但是由于原有whalin沒(méi)有提供擴(kuò)展的接口,因此不得不將whalin除了SockIO部分全部納入到封裝過(guò)的客戶端中,然后改造SockIO部分。

    因此也有了這個(gè)放在Google上的

    open source: http://code.google.com/p/memcache-client-forjava/

     

    一.              優(yōu)化synchronized部分。在原有代碼中SockIO的資源池分成三個(gè)池(普通Map實(shí)現(xiàn)),FreeBusyDead,然后根據(jù)SockIO使用情況來(lái)維護(hù)這三個(gè)資源池。

    優(yōu)化方式,首先簡(jiǎn)化資源池,只有一個(gè)資源池,設(shè)置一個(gè)狀態(tài)池,在變更資源狀態(tài)的過(guò)程時(shí)僅僅變更資源池中的內(nèi)容。再次,用ConcurrentMap來(lái)替代Map,同時(shí)使用putIfAbsent方法來(lái)簡(jiǎn)化Synchronized,具體的代碼可以看open source的代碼部分。

    二.              原以為這優(yōu)化后,效率應(yīng)該會(huì)有很大的提高,但是在初次壓力測(cè)試后發(fā)現(xiàn),并沒(méi)有明顯的提高,看來(lái)有其他地方的耗時(shí)遠(yuǎn)遠(yuǎn)大于連接池資源維護(hù),因此用JProfiler作了性能分析,發(fā)現(xiàn)了最大的一個(gè)瓶頸:read數(shù)據(jù)部分,原有設(shè)計(jì)中讀取數(shù)據(jù)是按照單字節(jié)讀取,然后逐步分析,為的僅僅就是遇到協(xié)議中的分割符可以識(shí)別,但是循環(huán)read單字節(jié)和批量分頁(yè)read性能相差很大,因此內(nèi)置了讀入緩存頁(yè)(可設(shè)置大小),然后再按照協(xié)議的需求去讀取和分析數(shù)據(jù),效率得到了很大的提高。具體的看最后部分的壓力測(cè)試結(jié)果。

     

    上面兩部分的工作不論是否提升了性能,但是對(duì)于客戶端本身來(lái)說(shuō)都是有意義的,當(dāng)然提升性能給應(yīng)用帶來(lái)的吸引力更大。這部分細(xì)節(jié)內(nèi)容可以參看代碼實(shí)現(xiàn)部分,對(duì)于調(diào)用者來(lái)說(shuō)完全沒(méi)有任何功能影響,僅僅只是性能。

     

     

    壓力測(cè)試

             在這個(gè)壓力測(cè)試之前,其實(shí)已經(jīng)做過(guò)很多次壓力測(cè)試了,測(cè)試中的數(shù)據(jù)本身并沒(méi)有衡量Memcached的意義,因?yàn)闇y(cè)試是使用我自己的機(jī)器,性能,帶寬,內(nèi)存,網(wǎng)絡(luò)IO都不是服務(wù)器級(jí)別的,這里僅僅是將使用原有的第三方客戶端和改造后的客戶端作一個(gè)比較。場(chǎng)景就是模擬多用戶多線程在同一時(shí)間發(fā)起Cache操作,然后記錄下操作的結(jié)果。

     

    Client版本在測(cè)試中有兩個(gè):2.02.22.0是封裝調(diào)用whalin memcached Client 2.0.1版本的客戶端實(shí)現(xiàn)。2.2是使用了新SockIO的無(wú)第三方依賴的客戶端實(shí)現(xiàn)。

             checkAlive指的是在使用連接資源以前是否需要驗(yàn)證連接資源有效(發(fā)送一次請(qǐng)求并接受響應(yīng)),因此打開(kāi)對(duì)于性能來(lái)說(shuō)會(huì)有不少的影響,不過(guò)建議還是使用這個(gè)檢查。

     

    One Cache Server instance各種配置和操作下比較:

    Cache配置

    User

    操作

    Client 版本

    總耗時(shí)(ms)

    單線程耗時(shí)(ms)

    提高處理能力百分比

    checkAlive

    100

    1000 put simple obj

    1000 get simple obj

    2.0

    13242565

    132425

    +41.3%

    2.2

    7772767

    77727

    No checkAlive

    100

    1000 put simple obj

    1000 get simple obj

    2.0

    7200285

    72002

    +35.2%

    2.2

    4667239

    46672

    checkAlive

    100

    1000 put simple obj

    2000 get simple obj

    2.0

    20385457

    203854

    +43.6%

    2.2

    11494383

    114943

    No checkAlive

    100

    1000 put simple obj

    2000 get simple obj

    2.0

    11259185

    112591

    +35.6%

    2.2

    7256594

    72565

    checkAlive

    100

    1000 put complex obj

    1000 get complex obj

    2.0

    15004906

    150049

    +36.7%

    2.2

    9501571

    95015

    No checkAlive

    100

    1000 put complex obj

    1000 get complex obj

    2.0

    9022578

    90225

    +24.9%

    2.2

    6775981

    67759

    從上面的壓力測(cè)試可以看出這么幾點(diǎn),首先優(yōu)化SockIO提升了不少性能,其次SockIO優(yōu)化的是get的性能,對(duì)于put沒(méi)有太大的作用。原本以為獲取數(shù)據(jù)越大性能效果提升越明顯,但結(jié)果并不是這樣,這部分在這幾天在看看是否還有更加耗時(shí)的部分存在。

     

     

     

     

     

    One Cache instance Two Cache instance的測(cè)試比較:

    Cache配置

    User

    操作

    Client 版本

    總耗時(shí)(ms)

    單線程耗時(shí)(ms)

    提高處理能力百分比

    One Cache instance

    checkAlive

    100

    1000 put simple obj

    1000 get simple obj

    2.0

    13242565

    132425

    +41.3%

    2.2

    7772767

    77727

    Two Cache instance

    checkAlive

    100

    1000 put simple obj

    1000 get simple obj

    2.0

    13596841

    135968

    +43.4%

    2.2

    7696684

    76966

    單個(gè)客戶端對(duì)應(yīng)多個(gè)服務(wù)端實(shí)例性能提升略高于單客戶端對(duì)應(yīng)單服務(wù)端實(shí)例。

     

     

    Cache Cluster的測(cè)試比較:

    Cache配置

    User

    操作

    Client 版本

    總耗時(shí)(ms)

    單線程耗時(shí)(ms)

    提高處理能力百分比

    No Cluster

    checkAlive

    100

    1000 put simple obj

    1000 get simple obj

    2.0

    13242565

    132425

    +41.3%

    2.2

    7772767

    77727

    Cluster

    checkAlive

    100

    1000 put simple obj

    1000 get simple obj

    2.0

    25044268

    250442

    +66.5%

    2.2

    8404606

    84046

    這部分和SocketIO優(yōu)化無(wú)關(guān)。2.0采用的是向集群中所有Client更新成功以后才返回的策略,2.2采用了異步更新,并且是分布式Client Node獲取的方式來(lái)分散壓力,因此提升效率很多。

     

     

    開(kāi)源:

             其實(shí)封裝后的客戶端一直在內(nèi)部使用,現(xiàn)在作了二次優(yōu)化以后,覺(jué)得應(yīng)該Open出來(lái),一來(lái)可以完善自己的客戶端代碼,二來(lái)也可以和更多的同學(xué)交流使用心得。

             Google Code上傳了這應(yīng)用的代碼,范例,說(shuō)明,有興趣的同學(xué)可以下載下來(lái)測(cè)試一下,比較一下現(xiàn)在用的Java Memcached客戶端的使用方便程度以及性能。

    open source: http://code.google.com/p/memcache-client-forjava/

    期待更多人能夠分享~~~

    posted on 2008-09-25 16:34 岑文初 閱讀(6789) 評(píng)論(3)  編輯  收藏

    評(píng)論

    # re: MemCached Cache Java Client封裝優(yōu)化歷程 2008-09-25 17:47 dennis
    不知道有沒(méi)有跟spymemcached這個(gè)客戶端的對(duì)比數(shù)據(jù)?  回復(fù)  更多評(píng)論
      

    # re: MemCached Cache Java Client封裝優(yōu)化歷程 2008-09-25 18:00 岑文初
    沒(méi)有,如果可以,你可以用這兩個(gè)包在同樣的環(huán)境試試看。  回復(fù)  更多評(píng)論
      

    # re: MemCached Cache Java Client封裝優(yōu)化歷程 2008-09-25 18:10 Jack.Wang
    不錯(cuò)!  回復(fù)  更多評(píng)論
      


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲精品影院久久久久久| 两性色午夜免费视频| 人禽杂交18禁网站免费| 亚洲情a成黄在线观看动漫尤物| 欧洲美女大片免费播放器视频 | 国产成人A亚洲精V品无码| 色九月亚洲综合网| 四虎成人免费网站在线| 国产成人精品日本亚洲网址| 在线免费观看国产| 亚洲国产第一页www| 精品成人免费自拍视频| 亚洲中文字幕无码日韩| caoporm碰最新免费公开视频| 亚洲精品456播放| 一级一级毛片免费播放| 亚洲va中文字幕无码| 午夜亚洲国产精品福利| 国产嫩草影院精品免费网址| 无码天堂va亚洲va在线va| 国产精品无码一二区免费| 亚洲AV无码国产剧情| 免费观看大片毛片| 亚洲成a∧人片在线观看无码| 国产美女精品视频免费观看 | 亚洲精品无码久久久久| 成人免费ā片在线观看| 好看的电影网站亚洲一区| 在线观看肉片AV网站免费| 精品国产综合成人亚洲区| 女人隐私秘视频黄www免费| 亚洲精品国产精品乱码不99 | 黄页视频在线观看免费| 亚洲А∨精品天堂在线| 一级毛片大全免费播放| 国产亚洲精品无码专区| 中国国产高清免费av片| 久久久久亚洲AV成人无码| 小草在线看片免费人成视久网| 亚洲黑人嫩小videos| 国产精品色拉拉免费看|