Guava Cache本地緩存在 Spring Boot應(yīng)用中的實(shí)踐

ZenBook S13 97%屏占比

概述

在如今高并發(fā)的互聯(lián)網(wǎng)應(yīng)用中二驰,緩存的地位舉足輕重毛仪,對(duì)提升程序性能幫助不小糯笙。而 3.x開始的 Spring也引入了對(duì) Cache的支持惧蛹,那對(duì)于如今發(fā)展得如火如荼的 Spring Boot來說自然也是支持緩存特性的带膀。當(dāng)然 Spring Boot默認(rèn)使用的是 SimpleCacheConfiguration志珍,即使用 ConcurrentMapCacheManager 來實(shí)現(xiàn)的緩存。但本文將講述如何將 Guava Cache緩存應(yīng)用到 Spring Boot應(yīng)用中垛叨。

Guava Cache是一個(gè)全內(nèi)存的本地緩存實(shí)現(xiàn)伦糯,而且提供了線程安全機(jī)制,所以特別適合于代碼中已經(jīng)預(yù)料到某些值會(huì)被多次調(diào)用的場景

下文就上手來摸一摸它,結(jié)合對(duì)數(shù)據(jù)庫的操作敛纲,我們讓 Guava Cache作為本地緩存來看一下效果喂击!

注: 本文首發(fā)于 My Personal Blog:CodeSheep·程序羊,歡迎光臨 小站


準(zhǔn)備工作

  • 準(zhǔn)備好數(shù)據(jù)庫和數(shù)據(jù)表并插入相應(yīng)實(shí)驗(yàn)數(shù)據(jù)(MySQL)

比如我這里準(zhǔn)備了一張用戶表淤翔,包含幾條記錄:

準(zhǔn)備好MySQL數(shù)據(jù)庫和數(shù)據(jù)表

我們將通過模擬數(shù)據(jù)庫的存取操作來看看 Guava Cache緩存加入后的效果翰绊。


搭建工程:Springboot + MyBatis + MySQL + Guava Cache

pom.xml 中添加如下依賴:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--for mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!--for Mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- Spring boot Cache-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <!--for guava cache-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0.1-jre</version>
        </dependency>

    </dependencies>

建立 Guava Cache配置類

引入 Guava Cache的配置文件 GuavaCacheConfig

@Configuration
@EnableCaching
public class GuavaCacheConfig {

    @Bean
    public CacheManager cacheManager() {
        GuavaCacheManager cacheManager = new GuavaCacheManager();
        cacheManager.setCacheBuilder(
                CacheBuilder.newBuilder().
                        expireAfterWrite(10, TimeUnit.SECONDS).
                        maximumSize(1000));
        return cacheManager;
    }
}

Guava Cache配置十分簡潔,比如上面的代碼配置緩存存活時(shí)間為 10 秒旁壮,緩存最大數(shù)目為 1000 個(gè)


配置 application.properties

server.port=82

# Mysql 數(shù)據(jù)源配置
spring.datasource.url=jdbc:mysql://121.116.23.145:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=xxxxxx
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# mybatis配置
mybatis.type-aliases-package=cn.codesheep.springbt_guava_cache.entity
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

編寫數(shù)據(jù)庫操作和 Guava Cache緩存的業(yè)務(wù)代碼

  • 編寫 entity
public class User {

    private Long userId;
    private String userName;
    private Integer userAge;

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getUserAge() {
        return userAge;
    }

    public void setUserAge(Integer userAge) {
        this.userAge = userAge;
    }
}
  • 編寫 mapper
public interface UserMapper {

    List<User> getUsers();
    int addUser(User user);
    List<User> getUsersByName( String userName );
}
  • 編寫 service
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public List<User> getUsers() {
        return userMapper.getUsers();
    }

    public int addUser( User user ) {
        return userMapper.addUser(user);
    }

    @Cacheable(value = "user", key = "#userName")
    public List<User> getUsersByName( String userName ) {
        List<User> users = userMapper.getUsersByName( userName );
        System.out.println( "從數(shù)據(jù)庫讀取监嗜,而非讀取緩存!" );
        return users;
    }
}

看得很明白了抡谐,我們?cè)?getUsersByName接口上添加了注解:@Cacheable裁奇。這是 緩存的使用注解之一,除此之外常用的還有 @CachePut@CacheEvit麦撵,分別簡單介紹一下:

  1. @Cacheable:配置在 getUsersByName方法上表示其返回值將被加入緩存框喳。同時(shí)在查詢時(shí),會(huì)先從緩存中獲取厦坛,若不存在才再發(fā)起對(duì)數(shù)據(jù)庫的訪問
  2. @CachePut:配置于方法上時(shí)五垮,能夠根據(jù)參數(shù)定義條件來進(jìn)行緩存,其與 @Cacheable不同的是使用 @CachePut標(biāo)注的方法在執(zhí)行前不會(huì)去檢查緩存中是否存在之前執(zhí)行過的結(jié)果杜秸,而是每次都會(huì)執(zhí)行該方法放仗,并將執(zhí)行結(jié)果以鍵值對(duì)的形式存入指定的緩存中,所以主要用于數(shù)據(jù)新增和修改操作上
  3. @CacheEvict:配置于方法上時(shí)撬碟,表示從緩存中移除相應(yīng)數(shù)據(jù)诞挨。
  • 編寫 controller
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    CacheManager cacheManager;

    @RequestMapping( value = "/getusersbyname", method = RequestMethod.POST)
    public List<User> geUsersByName( @RequestBody User user ) {
        System.out.println( "-------------------------------------------" );
        System.out.println("call /getusersbyname");
        System.out.println(cacheManager.toString());
        List<User> users = userService.getUsersByName( user.getUserName() );
        return users;
    }

}

改造 Spring Boot應(yīng)用主類

主要是在啟動(dòng)類上通過 @EnableCaching注解來顯式地開啟緩存功能

@SpringBootApplication
@MapperScan("cn.codesheep.springbt_guava_cache")
@EnableCaching
public class SpringbtGuavaCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbtGuavaCacheApplication.class, args);
    }
}

最終完工的整個(gè)工程的結(jié)構(gòu)如下:

完整工程結(jié)構(gòu)

實(shí)際實(shí)驗(yàn)

通過多次向接口 localhost:82/getusersbyname POST數(shù)據(jù)來觀察效果:

向接口提交數(shù)據(jù)

可以看到緩存的啟用和失效時(shí)的效果如下所示(上文 Guava Cache的配置文件中設(shè)置了緩存 user的實(shí)效時(shí)間為 10s):

緩存的啟用和失效時(shí)的取數(shù)據(jù)效果

怎么樣,緩存的作用還是很明顯的吧呢蛤!


后 記

由于能力有限惶傻,若有錯(cuò)誤或者不當(dāng)之處,還請(qǐng)大家批評(píng)指正其障,一起學(xué)習(xí)交流银室!



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市励翼,隨后出現(xiàn)的幾起案子蜈敢,更是在濱河造成了極大的恐慌,老刑警劉巖汽抚,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抓狭,死亡現(xiàn)場離奇詭異,居然都是意外死亡造烁,警方通過查閱死者的電腦和手機(jī)否过,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門午笛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人苗桂,你說我怎么就攤上這事药磺。” “怎么了誉察?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惹谐。 經(jīng)常有香客問我持偏,道長,這世上最難降的妖魔是什么氨肌? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任鸿秆,我火速辦了婚禮,結(jié)果婚禮上怎囚,老公的妹妹穿的比我還像新娘卿叽。我一直安慰自己,他們只是感情好恳守,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布考婴。 她就那樣靜靜地躺著,像睡著了一般催烘。 火紅的嫁衣襯著肌膚如雪沥阱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天伊群,我揣著相機(jī)與錄音考杉,去河邊找鬼。 笑死舰始,一個(gè)胖子當(dāng)著我的面吹牛崇棠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丸卷,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼枕稀,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了谜嫉?” 一聲冷哼從身側(cè)響起抽莱,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骄恶,沒想到半個(gè)月后食铐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡僧鲁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年虐呻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了象泵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斟叼,死狀恐怖偶惠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情朗涩,我是刑警寧澤忽孽,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站谢床,受9級(jí)特大地震影響兄一,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜识腿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一出革、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渡讼,春花似錦骂束、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹬昌,卻和暖如春析藕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凳厢。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國打工账胧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人先紫。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓治泥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遮精。 傳聞我的和親對(duì)象是個(gè)殘疾皇子居夹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Boot緩存 《Spring Boot 實(shí)戰(zhàn)開發(fā)》—— 基于 Gradle + Kotlin的企業(yè)級(jí)...
    光劍書架上的書閱讀 5,847評(píng)論 2 18
  • 緩存是最直接有效提升系統(tǒng)性能的手段之一。個(gè)人認(rèn)為用好用對(duì)緩存是優(yōu)秀程序員的必備基本素質(zhì)本冲。 本文結(jié)合實(shí)際開發(fā)經(jīng)驗(yàn)准脂,從...
    Java小生閱讀 815評(píng)論 1 3
  • 隨著時(shí)間的積累,應(yīng)用的使用用戶不斷增加檬洞,數(shù)據(jù)規(guī)模也越來越大狸膏,往往數(shù)據(jù)庫查詢操作會(huì)成為影響用戶使用體驗(yàn)的瓶頸,此時(shí)使...
    程序猿DD閱讀 55,652評(píng)論 10 51
  • 本文基于《Spring實(shí)戰(zhàn)(第4版)》所寫添怔。 啟用對(duì)緩存的支持 Spring對(duì)緩存的支持有兩種方式: 注解驅(qū)動(dòng)的緩...
    陽光的技術(shù)小棧閱讀 1,458評(píng)論 0 1
  • 一個(gè)人湾戳,插著耳機(jī)贤旷,下午三點(diǎn)多的時(shí)候,走在校道砾脑。 好久沒有來校道了幼驶。 不知道,明天的體測(cè)會(huì)怎么樣韧衣。 也不知道為什么盅藻,...
    減肥的女孩閱讀 231評(píng)論 1 1