運維在上線,無聊寫博客。最近看了下Spring的緩存框架,這里寫一下
1.Spring 緩存框架 原理淺談
2.Spring 緩存框架 注解使用說明
3.Spring 緩存配置 + Ehcache(默認)
4.Spring 緩存配置 + Ehcache(自己實現)
5.Spring 緩存配置 + Memcache
6.Ehcache和Memcache的資料收集
Spring提供的緩存注解,通過對CacheManager管理Cache,實現對緩存的操作。Spring提供的CacheManager和Cache的關系,可以類比Ehcache里面的Cache和Element的關系。例如存儲用戶的緩存,對應的數據接口是:CacheManager中管理着一個Map<key,Cache>結構的Cache集合(參考:ConcurrentMapCacheManager.cacheMap),Map的key值為@Cacheable注解中的name屬性,存儲內容(Cache)對應的則是同一個name對應的一類數據。這一類數據會根據@Cacheable中key的屬性,在Cache里面存儲成Map<key,Element>結構的對象集合(參考:ConcurrentMapCache.store)。
可以簡單的說,在Spring的@Cache注解中,管理的是一個Map1<name, Map2<key, value>>的存儲結構,Map1對應的是CacheManager實現,Map2對應的是Cache實現,在實現中CacheManager和Cache都可以通過配置的方式,實現不同的緩存策略,如下圖:
在如上結構中,主要應用了策略模式【面向接口,而不是面向實現】實現業務與具體實現的隔離;通過具體的不同策略實現【開閉原則】,可以方便的增加多個具體實現;業務代碼只依賴接口(此處依賴注解),不依賴具體的實現【依賴倒轉原則】,高層的業務模塊不依賴底層的具體算法。
在底層的具體實現上面,Spring通過配置不同的動態代理的實現【代理工廠】對實現方式進行管理。
在這個框架中Map1<name, Map2<key, value>>的局限性在於,存儲結構是一個二層的樹狀結構,但是現在大部分的緩存例如Memcache和Redis都是<K,V>結構。而且如果把Memcache存儲成<K,Map<key,val>>結構的話,在判斷緩存(K_key)是否存在的時候,需要把整個K對應的Map從緩存服務器中放到本地環境進行判斷,對於寬帶和效率上都有比較大的影響。
因此在具體實現的時候,針對集中是緩存,最好不要簡單的使用CacheManager和Cache的Map1<name,Map2<key,value>>結構來實現。而是通過其他的方式,將需要存儲的值,最終存儲成<K,V>結構來提升效率(PS:不使用Map1<name,Map2<key,value>>會導致CacheEvict的allEntries屬性失效,后面文章細說)。