秒殺系統(tǒng) | 多級(jí)查詢緩存 | 基于 Guava Cache 的本地?zé)狳c(diǎn)緩存

本地?zé)狳c(diǎn)緩存的特點(diǎn)

  • 只有熱點(diǎn)數(shù)據(jù)才能進(jìn)入本地?zé)狳c(diǎn)緩存获枝;
  • 本地?zé)狳c(diǎn)緩存對(duì)臟讀要非常不敏感伞访,比如商品名稱在 MySQL 中的變更,這個(gè)變更沒有更新到本地緩存中,這是 OK 的,用戶下單時(shí)的商品名稱和用戶看到的商品名稱不一樣屡律,這是 OK 的笨触;
  • 本地?zé)狳c(diǎn)緩存內(nèi)存要可控:
    • 當(dāng)商品信息在 MySQL 中變更時(shí)扭弧,Redis 中的過期數(shù)據(jù)只需清除即可咬清;
    • 但對(duì)本地?zé)狳c(diǎn)緩存來說,很少有方法能清除掉 JVM 中的數(shù)據(jù)的淑廊,因?yàn)橐宄?JVM 中的數(shù)據(jù)逗余,需要每臺(tái)應(yīng)用服務(wù)器都清除掉數(shù)據(jù)才行,可以使用 MQ 做廣播消息的發(fā)送來實(shí)現(xiàn)蒋纬,但這種操作是得不償失的猎荠;
  • 本地?zé)狳c(diǎn)緩存的生命周期不會(huì)特別長(zhǎng)坚弱,比 Redis 中 key 的生命周期要短很多,這樣才能做到被動(dòng)失效造成的臟讀非常少关摇;

本地?zé)狳c(diǎn)緩存的設(shè)計(jì)考量

  • 本地?zé)狳c(diǎn)緩存的本質(zhì)其實(shí)就是維護(hù)一個(gè) HashMap 的數(shù)據(jù)結(jié)構(gòu)荒叶,但維護(hù)這個(gè)結(jié)構(gòu)是不容易的:
    • 首先要支持并發(fā)讀寫,ConcurrentHashMap 的性能不夠理想输虱;
    • 要考慮失效時(shí)間和內(nèi)存容量限制的淘汰機(jī)制些楣,比如10分鐘自動(dòng)失效、先進(jìn)先出宪睹、最少訪問頻次 LRU愁茁;

Guava Cache 的特點(diǎn)

  • Guava Cache 可控制大小和超時(shí)時(shí)間,本質(zhì)上也是可支持并發(fā)的 HashMap亭病;
  • Guava Cache 可配置 LRU(最近最少訪問的 key 優(yōu)先被淘汰) 的策略鹅很;
  • Guava Cache 是線程安全的;

基于 Cuava Cache 的本地?zé)狳c(diǎn)緩存的實(shí)現(xiàn)

  • 依賴
<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>18.0</version>
</dependency>
  • 對(duì)本地緩存操作的封裝
public interface CacheService {

    void setCommonCache(String key, Object value);

    Object getFromCommonCache(String key);

}
package com.lixinlei.miaosha.service.impl;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.lixinlei.miaosha.service.CacheService;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

@Service
public class CacheServiceImpl implements CacheService {

    private Cache<String, Object> commonCache = null;

    @PostConstruct
    public void init() {
        commonCache = CacheBuilder.newBuilder()
                .initialCapacity(10)
                .maximumSize(100)
                .expireAfterWrite(60, TimeUnit.SECONDS).build();
    }

    @Override
    public void setCommonCache(String key, Object value) {
        commonCache.put(key, value);
    }

    @Override
    public Object getFromCommonCache(String key) {
        return commonCache.getIfPresent(key);
    }

}
  • Controller 層引入本地緩存邏輯
@RequestMapping(value = "/get", method = {RequestMethod.GET})
@ResponseBody
public CommonReturnType get(@RequestParam(name = "id") Integer id) {
    ItemModel itemModel = null;

    // 先從本地緩存中找
    itemModel = (ItemModel)cacheService.getFromCommonCache("item_" + id);
    if (itemModel == null) {
        // 再?gòu)?Redis 中找
        itemModel = (ItemModel)redisTemplate.opsForValue().get("item_" + id);
        if (itemModel == null) {
            // 最后從 MySQL 中找
            itemModel = itemService.getItemById(id);
            redisTemplate.opsForValue().set("item_" + id, itemModel);
            redisTemplate.expire("item_" + id, 10, TimeUnit.MINUTES);
        }
        cacheService.setCommonCache("item_" + id, itemModel);
    }

    ItemVO itemVO = this.convertFromItemModel(itemModel);
    return CommonReturnType.create(itemVO);
}

引入本地緩存性能提升

  • 相對(duì)于 Redis 緩存罪帖,在本地緩存全部命中的情況下促煮,TPS 從 2000 提升到 4000 +(2核8G);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末整袁,一起剝皮案震驚了整個(gè)濱河市菠齿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坐昙,老刑警劉巖绳匀,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異炸客,居然都是意外死亡疾棵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門痹仙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陋桂,“玉大人,你說我怎么就攤上這事蝶溶。” “怎么了宣渗?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵抖所,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我痕囱,道長(zhǎng)田轧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任鞍恢,我火速辦了婚禮傻粘,結(jié)果婚禮上每窖,老公的妹妹穿的比我還像新娘。我一直安慰自己弦悉,他們只是感情好窒典,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著稽莉,像睡著了一般瀑志。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上污秆,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天劈猪,我揣著相機(jī)與錄音,去河邊找鬼良拼。 笑死战得,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庸推。 我是一名探鬼主播常侦,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼予弧!你這毒婦竟也來了刮吧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤掖蛤,失蹤者是張志新(化名)和其女友劉穎杀捻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚓庭,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡致讥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了器赞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垢袱。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖港柜,靈堂內(nèi)的尸體忽然破棺而出请契,到底是詐尸還是另有隱情,我是刑警寧澤夏醉,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布爽锥,位于F島的核電站,受9級(jí)特大地震影響畔柔,放射性物質(zhì)發(fā)生泄漏氯夷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一靶擦、第九天 我趴在偏房一處隱蔽的房頂上張望腮考。 院中可真熱鬧雇毫,春花似錦、人聲如沸踩蔚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寂纪。三九已至席吴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捞蛋,已是汗流浹背孝冒。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拟杉,地道東北人庄涡。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像搬设,于是被迫代替她去往敵國(guó)和親穴店。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359