天天看點

localCache與集中式cache

使用memcache緩存資料,減少對資料庫的直接通路,提高網站性能已經成了各大網站最基本的技術.如何更好的提高memcache緩存的使用率及命中次數會在後面的blog中單獨介紹,本文主要探讨為何及如何使用本地緩存(java localcache)提高網站性能.

localcache與memcache性能比較

先來個本地緩存與memcache緩存的性能比較,有個直覺上的概念

Cache 請求方式 次數 時間 平均
Localcache hashmap中get請求 1億 1344ms 0.00001344ms
Memcache 簡單的get請求,不做序列化 1萬 4437ms 0.4437ms
Db 單表查詢(有索引) 1-2ms

以上測試在開發機器.生産環境采集的資料顯示memcache的一次請求大約在0.2ms左右,如果存儲的是java object,那算上發序列化的時間在0.5ms以上.與測試資料在同一個數量級上.

通過以上資料對比,可以得知localcache的效率比memcache高1萬倍以上.這個數字讓我對使用本地緩存充滿了極大的興趣.

使用localcache會帶來哪些問題

localcache有着極大的性能優勢,單機情況下,适當使用localcache會使程式的效率得到很大的提升.但在叢集環境下localcache就存在很多問題了,主要展現在多個jvm之間cache的同步問題.

有很多架構在這上面做了很多工作,比如ehcache ,主要是通過cache複制(copy或invalidate)來解決,大概的思路是使用消息多點傳播機制,當一個jvm中的資料做了更新操作後,首先更新本jvm内的localcache,然後廣播消息,其他jvm接收到消息後更新自己的localcache. 但這種機制可能帶來并發操作時出現髒資料的問題,具體見Potential Issues with Replicated Caching.

其他cache産品也遇到類似的問題,不再一一介紹.

那有沒有很好的方法來解決localcache的同步問題,進而可以放心的品嘗localcache這塊"甜餅"呢?

這個問題我也很糾結,通過多種方案的組合及補償機制似乎可以實作一個完美的方案.但也注定成為了一個複雜的方案.類似的方案可以有如下幾種:

1.localcache作為一級緩存,通過廣播的方式同步緩存,同時設定緩存過期時間,以達到資料同步和出現髒資料後自動修複的功能.

2.localcache作為一級緩存,資料更新後發送異步消息(MQ等),其餘localcache訂閱異步消息,并根據消息來同步緩存.

3.localcache作為一級緩存,memcache中存放緩存變更的資訊,定時任務定時擷取memcache的資訊,并決定是否更新localcache.

4.localcache作為一級緩存,每次從memcache中擷取資料更改的标記位,如果标記發生變化,更新localcache

以上的這些實作方案,都在一定程度上加大了架構的複雜性,當localcache中資料出現髒資料時,排查問題及清理資料都會變得複雜.

他人經驗之談

1.sohu早期使用廣播的方式(jgroup)同步localcache,結果經常會出現髒資料的問題,在後來的架構設計上幹脆摒棄了localcache(即使使用,也不再作資料同步),全部使用memcache.

2.taobao在生産環境也很少使用localcache同步,對于非敏感性資料,隻是通過簡單的過期政策,來保證資料的一緻性.

總結

叢集環境下對于敏感性要求不高的資料可以使用localcache,隻配置簡單的失效機制來保證資料的一緻性.

對敏感性高的資料直接使用集中式緩存,減低複雜度.

複雜方案看似完美的解決了問題,實際上性能和穩定性卻很可能大打折扣.

感謝William 、放翁提出的寶貴建議。