SpringBoot中引入Ehcache3.x

1.Ehcache介紹java

Ehcache是一個用Java實現的簡單、高速、線程安全的緩存管理類庫。具體快速、簡單、低消耗、依賴性小、擴展性強、支持對象或序列化緩存、支持緩存或元素的失效、提供LRU/LFU/FIFO緩存策略、支持內存緩存及磁盤緩存、採用分佈式緩存機制等特色。redis

2.引入依賴spring

在項目的pom.xml中添加下面這三個依賴:數據庫

< dependency>api

< groupId>javax.cache < /groupId>瀏覽器

< artifactId>cache-api < /artifactId>緩存

< /dependency>安全

< dependency>服務器

< groupId>org.ehcache< /groupId>app

< artifactId>ehcache< /artifactId>

< version>3.7.0< /version>

< /dependency>

< dependency>

< groupId>org.springframework.boot< /groupId>

< artifactId>spring-boot-starter-cache< /artifactId>

< /dependency>

cache-api是JSR-107 Cache的規範,定義了一列接口規範(可是這只是一種規範,須要使用它的實現,例如ehcache3.x、Hazelcast等)。 ehcache是ehcache的功能包。

springBoot要支持第三方緩存的話,還須要引入spring-boot-starter-cache。

3.配置屬性

3.1 配置application.properties

在application.properties添加以下配置:

可選,配置了spring.cache.jcache.config屬性會自動裝配JCacheCacheManager

spring.cache.type=jcache

指定ehcache的配置文件所在的位置

spring.cache.jcache.config=classpath:ehcache-3.x.xml

3.2配置ehcache-3.x.xml

在resources文件夾下新建ehcache-3.x.xml,添加以下內容:

< ?xml version="1.0" encoding="UTF-8" ?>

< eh:config

xmlns:xsi='www.w3.org/2001/XMLSch…'

xmlns:eh='www.ehcache.org/v3'

xsi:schemaLocation="www.ehcache.org/v3 www.ehcache.org/schema/ehca…">

< !--指定緩存目錄-->

< eh:persistence directory="${java.io.tmpdir}/cache-data"/>

< !--緩存模板-->

< eh:cache-template name="default">

< eh:expiry>

< eh:ttl unit="seconds">600< /eh:ttl>

< /eh:expiry>

< eh:resources>

< !--堆內內存能夠放2000個條目,超出部分堆外100MB-->

< eh:heap unit="entries">2000< /eh:heap>

< eh:offheap unit="MB">100< /eh:offheap>

< /eh:resources>

< /eh:cache-template>

< !--實際的緩存區間,繼承了default緩存模板,sample徹底使用模板默認-->

< eh:cache alias="sample" uses-template="default">< /eh:cache>

< !--下面兩個繼承了default緩存模板,但覆蓋了緩存的過時時間--> < eh:cache alias="authority_service" uses-template="default">

< eh:expiry>

< eh:ttl unit="hours">1< /eh:ttl>

< /eh:expiry>

< /eh:cache>

< eh:cache alias="shop_service" uses-template="default">

< eh:expiry>

< eh:ttl unit="hours">24< /eh:ttl>

< /eh:expiry>

< /eh:cache>

< /eh:config>

更多配置知識,請參考ehcache官網:ehcache XML配置

4.使用示例

4.1 準備一個controller

該controller只有一個方法,得到某類商品的列表:

@RestController

@Validated

@RequestMapping("/v1.0/api/shop")

public class ShopController {

@Autowired

ShopService shopService;

@RequestMapping(value = {"/commodity"}, method = RequestMethod.GET)

public List listCommodity (@RequestParam String type) {

System.out.println("ShopController: type is " + type);

return shopService.listCommodity(type);

}

}

4.2 準備一個service

在須要使用緩存的Bean上面添加@EnableCaching註解,那該bean具備緩存功能。 在須要使用緩存的方法上添加@Cacheable註解,那該方法具備緩存功能(前提是該bean具備緩存的功能)。 注意: 1和2配合起來才能使某個bean的某個方法具備緩存的功能。

package com.example.demo.service;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.stereotype.Service;

import java.util.ArrayList;

import java.util.List;

@Service

@EnableCaching

public class ShopService {

// value:使用叫作'shop_service'的緩存器

// key: 緩存的key等於#type,即傳入的key值

// condition:緩存的條件,當#type等於phone時,才進行緩存

@Cacheable(cacheNames = "shop_service", key = "#type", condition = "#type == 'phone'")

public List listCommodity(String type) {

System.out.println("ShopService: 調用了listCommodity");

List commodities = new ArrayList<>();

if (type.equals("phone")) {

commodities.add("Apple");

commodities.add("HuaWei");

} else {

commodities.add("others");

}

return commodities;

}

}

4.3 啓動springBoot,進行測試

使用瀏覽器,發送4個請求:

http://localhost:8080/v1.0/api/shop/commodity?type=phone

http://localhost:8080/v1.0/api/shop/commodity?type=phone

http://localhost:8080/v1.0/api/shop/commodity?type=computer

http://localhost:8080/v1.0/api/shop/commodity?type=computer

後臺打印的日誌以下:

ShopController: type is phone

ShopService: 調用了listCommodity

ShopController: type is phone

ShopController: type is computer

ShopService: 調用了listCommodity

ShopController: type is computer

ShopService: 調用了listCommodity

4.4 結果分析

第一次發送請求,符合緩存的條件,因爲沒有緩存,因而執行了service的邏輯,並將結果緩存到了ehcache中。

第二次發送請求,符合緩存的條件,因爲已經緩存告終果,直接從ehcache中拿取緩存的結果返回,沒有進入到service的邏輯。

第三次和第四次都不符合緩存的條件,須要進入到service的邏輯計算結果。

5.Ehcache使用場景

使用的過程當中,根據優勢和缺點進行權衡後再應用到項目中去,Ehcache緩存也是如此,在實際工做有不少使用場景,一般將Ehcache做爲Redis的二次緩存使用。

5.1 Ehcache的適用場景

(1) 比較少的更新數據表的狀況下

Ehcache做爲Hibernate的緩存時,在進行修改表數據(save、update、delete等)的時候,Ehcache會自動把緩存中關於此表的全部緩存所有刪除掉,這樣作只是能達到同步,但對於數據常常修改的表來講,可能就失去了緩存的意義了。

(2)對一致性要求不高的狀況下

由於Ehcache本地緩存的特性,目前沒法很好的解決不一樣服務器緩存同步的問題,因此在一致性要求高的場合下,建議使用Redis、Memcached等集中式緩存。

5.2Ehcache的缺陷

(1) 緩存漂移

每一個應用節點只管理本身的緩存,在更新某個節點的時候,不會影響到其餘的節點,這樣數據之間可能就不一樣步了。

(2) 數據庫瓶頸

對於單實例的應用來講,緩存能夠保護數據庫的讀風暴;可是在集羣的環境下,每個應用節點都要按期保存數據更新,節點越多,要維持這樣的狀況對數據庫的開銷也越大。

5.3 Ehcache的正確打開方式

咱們在項目中使用集中式緩存(Redis或Memcached等)一般都是檢查緩存中是否存在指望的數據,若是存在直接將數據返回,若是不存在就查詢數據庫而後再將數據緩存,然後將結果返回。這時候若是緩存系統由於某些緣由宕機,形成服務沒法訪問,那麼大量的請求將直接穿透到數據庫,對數據庫形成巨大的壓力。

針對上述狀況,咱們有多種可行的解決方法,其中一種方案是將Ehcache做爲集中式緩存的二級本地緩存,這樣當緩存系統宕機後,服務器應用的本地緩存還能繼續抗住大量請求。

使用了Ehcache做爲本地緩存後,可能會出現本地緩存與緩存系統之間出現數據不一致的狀況,由於本地緩存是在服務器應用中存在,在實際生產環境中一定是多臺服務器分別部署,如何可以在更新緩存系統數據的同時,也可以更新Ehcache的緩存數據,以及保證不一樣服務器間Ehcache本地緩存數據的同步問題。

通常有兩種解決方案可供參考:

第一種:定時輪詢

每臺應用服務器定時輪詢Redis緩存,更新本地的Ehcache緩存。

第二種:主動通知

每臺應用服務器的Ehcache同步偵聽MQ消息,經過MQ推送的方式,將redis中更新的緩存數據推送到每臺應用服務器中。

針對上述的分析,可造成以下的緩存方案:

緩存方案.jpg
相關文章
相關標籤/搜索