緩存開發簡史,10年工作經驗老程序猿的心路歷程

NoSQL 程序員 Redis 技術 用Java打醬油 用Java打醬油 2017-10-03

緩存開發簡史,10年工作經驗老程序猿的心路歷程

緩存對應用來說非常重要,是提升性能的有效手段。大部分應用都有這樣的場景:

  • 用戶ID翻譯,數據庫表裡只記錄操作用戶ID,但在前端頁面顯示的卻是用戶名稱;

  • 數據字典翻譯,如性別,數據庫裡記錄的是01,02,03,但是在前端頁面顯示的是男,女,未知;

早期實現方法

以用戶ID翻譯為例,在系統啟動時調用UserCache類的init方法,將所有用戶ID和用戶名稱加載到緩存(map)裡,在需要翻譯用戶ID時調用getUserName。

緩存開發簡史,10年工作經驗老程序猿的心路歷程

這種實現方法簡單,可以滿足早期需求,存在的弊端是

  • 系統啟動的時候加載,如果在運行過程中數據發生修改,需要手動更新緩存。應用開發與緩存耦合度過高;

  • 不存在緩存穿透,應用啟動時要將緩存數據加載完成;

  • 開發人員精神割裂,UserService是用戶服務類,但是使用getUserName得通過UserCache類。

  • 一旦要採用第三方緩存如Redis,無法切換,只能修改UserCache類;

老實說,我們公司現在有些應用的緩存實現還停留在早期階段。

中期實現方法

將緩存類和服務類整合,避免開發人員精神割裂。緩存穿透的實現也優雅一些。

  • 對於用戶服務調用的開發人員來說,都是調用User的服務,無需關心其內部實現是數據庫還是緩存,性能由用戶服務保證,調用者無需關心;

  • 對於用戶服務開發人員來說,不用額外開發緩存類,統一在UserService中實現;

  • UserService的getUserName實現邏輯:先根據userId在緩存中查找,如果緩存沒有,則查詢數據庫並更新緩存,這就是我們常說的緩存穿透,優點是應用啟動時不用加載數據(或是不用加載所有數據),可以設置緩存數據存活時間,保證只有熱點數據在緩存中;

緩存開發簡史,10年工作經驗老程序猿的心路歷程

這種實現方法比早期顯得優雅一些,但是仍然有缺點:

  • 緩存實現方法比較死板,如果切換第三方緩存,則需要修改MyCacheManager類;

  • 緩存代碼與業務代碼耦合度高,如getUserName方法中就有太多緩存相關的代碼,不利於維護和變更;

現在的實現方法

Spring cache基於註釋(annotation)的緩存(cache)技術,它本質上不是一個具體的緩存實現方案(例如 EHCache 或者 Redis),而是一個對緩存使用的抽象,通過在既有代碼中添加少量它定義的各種 annotation,即能夠達到緩存方法的返回對象的效果。

Spring cache的緩存技術還具備相當的靈活性,不僅能夠使用 SpEL(Spring Expression Language)來定義緩存的 key 和各種 condition,還提供開箱即用的緩存臨時存儲方案,也支持和主流的專業緩存例如 Redis集成。

其特點總結如下:

  • 通過少量的配置 annotation 註釋即可使得既有代碼支持緩存

  • 支持開箱即用 Out-Of-The-Box,即不用安裝和部署額外第三方組件即可使用緩存

  • 支持 Spring Express Language,能使用對象的任何屬性或者方法來定義緩存的 key 和 condition

  • 支持 AspectJ,並通過其實現任何方法的緩存支持

  • 支持自定義 key 和自定義緩存管理者,具有相當的靈活性和擴展性

老程序猿下一篇文章介紹spring cache的使用,請各位客觀品嚐。

緩存開發簡史,10年工作經驗老程序猿的心路歷程

相關推薦

推薦中...