0. 引言
在實際應(yīng)用中,并不是單一的使用本地緩存或者redis,更多是組合使用來滿足不同的業(yè)務(wù)場景,于是如何優(yōu)雅的組合本地緩存和遠程緩存就成了我們要研究的問題,而這一點,阿里開源的jetcache組件幫我們實現(xiàn)了
1. jetcache簡介
jetcache是阿里開源的基于java開發(fā)的緩存框架,支持多種緩存類型:本地緩存、分布式緩存、多級緩存。能夠滿足不同業(yè)務(wù)場景的緩存需求。
jetcache具有上手簡單、性能高效、拓展性強的特點。支持緩存預(yù)熱 、緩存key前綴等功能。結(jié)合spring-cache使用,可以實現(xiàn)十分優(yōu)雅的緩存類型切換
2. jetcache使用
1、引入依賴,這里我們使用sringboot項目框架,同時使用redis作為遠程緩存。于是我們引入jetcache-starter-redis依賴,這里我的springboot版本為2.6.13
如果是非springboot項目可以參考官網(wǎng)說明配置
com.alicp.jetcache jetcache-starter-redis 2.7.0 redis.clients jedis 4.3.1
對應(yīng)的版本說明如下:springboot與jetcache版本關(guān)系
2、修改配置文件,配置redis地址和線程數(shù)
jetcache: #統(tǒng)計間隔,0表示不統(tǒng)計,開啟后定期在控制臺輸出緩存信息 statIntervalMinutes:15 #是否把cacheName作為遠程緩存key前綴 areaInCacheName:false #本地緩存配置 local: default:#default表示全部生效,也可以指定某個cacheName #本地緩存類型,其他可選:caffeine/linkedhashmap type:linkedhashmap keyConvertor:fastjson #遠程緩存配置 remote: default:#default表示全部生效,也可以指定某個cacheName type:redis #key轉(zhuǎn)換器方式n keyConvertor:fastjson broadcastChannel:projectA #redis序列化方式 valueEncoder:java valueDecoder:java #redis線程池 poolConfig: minIdle:5 maxIdle:20 maxTotal:50 #redis地址與端口 host:127.0.0.1 port:6379
更詳細的參數(shù)配置
3、啟動類添加注解@EnableCreateCacheAnnotation,開啟緩存,添加@EnableMethodCache(basePackages = "com.example.jetcachedemo")注解,配置緩存方法掃描路徑
4、使用緩存可以通過三種方式:
方式一(推薦)AOP模式:通過@Cached,@CacheUpdate,@CacheInvalidate注解
@RestController @RequestMapping("user") publicclassUserController{ @GetMapping("getRemote") @Cached(name="userCache:",key="#id",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.REMOTE) publicUsergetRemote(Longid){ //直接新建用戶,模擬從數(shù)據(jù)庫獲取數(shù)據(jù) Useruser=newUser(); user.setId(id); user.setName("用戶remote"+id); user.setAge(23); user.setSex(1); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @GetMapping("getLocal") @Cached(name="userCache:",key="#id",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.LOCAL) publicUsergetLocal(Longid){ //直接新建用戶,模擬從數(shù)據(jù)庫獲取數(shù)據(jù) Useruser=newUser(); user.setId(id); user.setName("用戶local"+id); user.setAge(23); user.setSex(1); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @GetMapping("getBoth") @Cached(name="userCache:",key="#id",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.BOTH) publicUsergetBoth(Longid){ //直接新建用戶,模擬從數(shù)據(jù)庫獲取數(shù)據(jù) Useruser=newUser(); user.setId(id); user.setName("用戶both"+id); user.setAge(23); user.setSex(1); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @PostMapping("updateUser") @CacheUpdate(name="userCache:",key="#user.id",value="#user") publicBooleanupdateUser(@RequestBodyUseruser){ //TODO更新數(shù)據(jù)庫 returntrue; } @PostMapping("deleteUser") @CacheInvalidate(name="userCache:",key="#id") publicBooleandeleteUser(Longid){ //TODO從數(shù)據(jù)庫刪除 returntrue; } }
這里要注意實體類User一定要實現(xiàn)序列化,即聲明Serializable
@Data publicclassUserimplementsSerializable{ privateLongid; privateStringname; privateIntegerage; privateIntegersex; }
方式二 API模式:通過@CreateCache,注:在jetcache 2.7 版本CreateCache注解已廢棄,不推薦使用
@RestController @RequestMapping("user2") publicclassUser2Controller{ @CreateCache(name="userCache:",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.BOTH) privateCacheuserCache; @GetMapping("get") publicUserget(Longid){ if(userCache.get(id)!=null){ return(User)userCache.get(id); } Useruser=newUser(); user.setId(id); user.setName("用戶both"+id); user.setAge(23); user.setSex(1); userCache.put(id,user); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @PostMapping("updateUser") publicBooleanupdateUser(@RequestBodyUseruser){ //TODO更新數(shù)據(jù)庫 userCache.put(user.getId(),user); returntrue; } @PostMapping("deleteUser") publicBooleandeleteUser(Longid){ //TODO從數(shù)據(jù)庫刪除 userCache.remove(id); returntrue; } }
方式三 高級API模式:通過CacheManager,2.7 版本才可使用
(1)添加依賴
com.alibaba fastjson 2.0.25
(2)書寫配置類
@Configuration publicclassJetcacheConfig{ @Autowired privateCacheManagercacheManager; privateCacheuserCache; @PostConstruct publicvoidinit(){ QuickConfigqc=QuickConfig.newBuilder("userCache:") .expire(Duration.ofSeconds(3600)) .cacheType(CacheType.BOTH) //本地緩存更新后,將在所有的節(jié)點中刪除緩存,以保持強一致性 .syncLocal(false) .build(); userCache=cacheManager.getOrCreateCache(qc); } @Bean publicCache getUserCache(){ returnuserCache; } }
(3)調(diào)用代碼
@RestController @RequestMapping("user3") publicclassUser3Controller{ @Autowired JetcacheConfigjetcacheConfig; @Autowired privateCacheuserCache; @GetMapping("get") publicUserget(Longid){ if(userCache.get(id)!=null){ return(User)userCache.get(id); } Useruser=newUser(); user.setId(id); user.setName("用戶both"+id); user.setAge(23); user.setSex(1); userCache.put(id,user); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @PostMapping("updateUser") publicBooleanupdateUser(@RequestBodyUseruser){ //TODO更新數(shù)據(jù)庫 userCache.put(user.getId(),user); returntrue; } @PostMapping("deleteUser") publicBooleandeleteUser(Longid){ //TODO從數(shù)據(jù)庫刪除 userCache.remove(id); returntrue; } }
多級緩存的形式,會先從本地緩存獲取數(shù)據(jù),本地獲取不到會從遠程緩存獲取
5、啟動redis,啟動演示項目
注意,如果啟動出現(xiàn)NoClassDefFoundError: redis/clients/util/Pool或NoClassDefFoundError: redis/clients/jedis/UnifiedJedis報錯,說明springboot與jetcache版本不一致,對應(yīng)關(guān)系可參考上述第一步中的說明 同時如果使用的是jetcache2.7.x版本,因為該版本中有jedis包的依賴,需要額外添加如下依賴,或者將jetcache版本將至2.6.5以下
redis.clients jedis 4.3.1
3. 測試
3.1 方式一測試
1、訪問localhost:8088/user/getRemote?id=1
因為配置的是遠程緩存,在redis中也能看到對應(yīng)的key
2、訪問localhost:8088/user/getLocal?id=1,這個方法是從本地緩存獲取的,現(xiàn)在只有遠程緩存上有數(shù)據(jù),我們調(diào)用發(fā)現(xiàn)緩存數(shù)據(jù)還是拿到了,這說明當我們在配置文件中配置了本地緩存和遠程緩存后,方式一中本地緩存和遠程緩存會自動相互調(diào)用
比如本地緩存有這個key,redis中沒有,通過遠程緩存方式訪問時,會先從redis獲取,如果沒有會自動獲取本地緩存,但是數(shù)據(jù)還是存儲在本地緩存,并不會同步到redis上,這樣更加靈活的實現(xiàn)了多級緩存架構(gòu)
3.2 方式二測試
1、再測試下CreateCache的形式:localhost:8088/user2/get?id=4
正常獲取了,并且redis中也有了對應(yīng)的值
而當我們把緩存方式更改為LOCAL后,再訪問localhost:8088/user2/get?id=5
@CreateCache(name="userCache:",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.LOCAL)
會發(fā)現(xiàn)redis中就沒有對應(yīng)緩存了,只在本地緩存存在,說明我們指定本地緩存的形式成功了
3.3 方式三測試
1、調(diào)用localhost:8088/user3/get?id=11
redis中緩存設(shè)置成功!
4. 常見報錯
1、 ClassNotFoundException: com.alibaba.fastjson.JSON 解決:添加依賴
com.alibaba fastjson 2.0.25
2、NoClassDefFoundError: redis/clients/jedis/UnifiedJedis 解決: 添加依賴
redis.clients jedis 4.3.1
或者將jetcache版本降低至2.6.5以下
演示源碼
https://gitee.com/wuhanxue/wu_study/tree/master/demo/jetcache-demo
審核編輯:湯梓紅
-
JAVA
+關(guān)注
關(guān)注
19文章
2966瀏覽量
104702 -
緩存
+關(guān)注
關(guān)注
1文章
239瀏覽量
26669 -
開源
+關(guān)注
關(guān)注
3文章
3309瀏覽量
42471 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14338 -
Redis
+關(guān)注
關(guān)注
0文章
374瀏覽量
10871
原文標題:jetcache:阿里這款多級緩存框架一定要掌握
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論