本地緩存
當系統(tǒng)中需要有一些基礎(chǔ)數(shù)據(jù)時,往往會使用本地緩存將這些數(shù)據(jù)緩存在內(nèi)存中,以減少對數(shù)據(jù)庫的查詢,提升系統(tǒng)性能,但是本地緩存如何處理數(shù)據(jù)更新的情況呢?當應(yīng)用集群中某臺機器更新了數(shù)據(jù),其它機器如何快速響應(yīng)?
一般更新本地緩存有如下 方式:
- 定時更新,這種方式延遲比較大
- 通過消息廣播機制更新
- 使用協(xié)調(diào)者,比如zookeeper,適用于更新頻率低的場景
本文介紹第三種方式,如何利用zookeeper做緩存的即時更新
基本思路
假設(shè)應(yīng)用有三臺機器,分別標記為A\B\C,整個過程遵循如下邏輯:
- 應(yīng)用在創(chuàng)建本地緩存時,向zookeeper注冊一個節(jié)點
- 注冊監(jiān)聽器,監(jiān)聽數(shù)據(jù)變化
- 當其中一臺機器更新緩存后(假設(shè)是機器A),修改zookeeper上的節(jié)點的數(shù)據(jù),標識有緩存更新
- 集群中所有機器都會收到節(jié)點數(shù)據(jù)更新的回調(diào),隨后刷新緩存
整體邏輯如下圖:

image
實現(xiàn)
將實現(xiàn)分為兩部分,第一部分基于zk實現(xiàn)一個可復(fù)用的通知服務(wù),用于通知集群中的其它機器,第二部分基于通知服務(wù)實現(xiàn)對緩存的封裝
通知服務(wù)
通知服務(wù)抽象出一個資源的概念,用String表示資源Id,一個資源Id對應(yīng)于zookeeper上的一個節(jié)點,針對資源id觸發(fā)通知服務(wù)實際上就是修改資源id對應(yīng)的節(jié)點上的數(shù)據(jù),接口如下:

image
接口定義中包含三個方法:
- Register:注冊資源
- Unregister:刪除資源
- Notify:通知,目前只接受String類型的值

image
緩存封裝
因為本地緩存有多種實現(xiàn)方式:
- Guava
- ConcurrentHashMap
- 其它…
為了支持各種類型的local cache實現(xiàn),定義CacheProvider接口,用于創(chuàng)建緩存:

image
為zookeeper提供抽象類的支持:

image
不同的local cache實現(xiàn)從此abstract類繼承,例如guava的實現(xiàn):

image
基于ConcurrentHashMap的local cache實現(xiàn):

image
最后通過一個工具類提供的工廠方法來使用:

image
使用方式
最后看一下使用方式:

image.png