Redis緩存擊穿疾牲、穿透植捎、雪崩解決方案

1、緩存處理流程

接收到查詢數(shù)據(jù)請(qǐng)求時(shí)阳柔,優(yōu)先從緩存中查詢焰枢,若緩存中有數(shù)據(jù),則直接返回,若緩存中查不到則從DB中查詢济锄,將查詢的結(jié)果更新到緩存中暑椰,并返回查詢結(jié)果,若DB中查不到拟淮,則返回空數(shù)據(jù)


緩存處理流程.png

2干茉、緩存穿透

當(dāng)緩存與數(shù)據(jù)庫(kù)中都不存在該數(shù)據(jù)時(shí),由于當(dāng)數(shù)據(jù)庫(kù)查詢不到數(shù)據(jù)就不會(huì)寫入緩存很泊,這個(gè)時(shí)候如果用戶不斷的惡意發(fā)起請(qǐng)求角虫,就會(huì)導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都會(huì)查詢DB,請(qǐng)求量大的情況下委造,就會(huì)導(dǎo)致DB壓力過(guò)大戳鹅,直接掛掉。

解決方案:

1昏兆、當(dāng)查詢返回一個(gè)空數(shù)據(jù)時(shí)枫虏,直接將這個(gè)空數(shù)據(jù)存到緩存中,過(guò)期時(shí)間不宜設(shè)置過(guò)長(zhǎng)爬虱,建議不超過(guò)5分鐘
2隶债、采用布隆過(guò)濾器:將所有可能存在數(shù)據(jù),分別通過(guò)多個(gè)哈希函數(shù)生成多個(gè)哈希值跑筝,然后將這些哈希值存到一個(gè)足夠大的bitmap中死讹,此時(shí)一個(gè)一定不存在的數(shù)據(jù)就會(huì)被這個(gè)bitmap攔截,從而減少了數(shù)據(jù)庫(kù)的查詢壓力曲梗。
參考鏈接:http://www.reibang.com/p/2104d11ee0a2

3赞警、緩存擊穿

某一個(gè)數(shù)據(jù)緩存中沒(méi)有但數(shù)據(jù)庫(kù)中有的數(shù)據(jù)(一般是緩存時(shí)間到期),這時(shí)由于并發(fā)用戶特別多虏两,同時(shí)讀緩存沒(méi)讀到數(shù)據(jù)愧旦,又同時(shí)去數(shù)據(jù)庫(kù)去取數(shù)據(jù),引起數(shù)據(jù)庫(kù)壓力瞬間增大定罢,嚴(yán)重情況下會(huì)直接掛掉笤虫。

解決方案:

1、添加互斥鎖:

  • ReentrantLock公平鎖
  • 根據(jù)key值加鎖引颈,這樣線程之間會(huì)不影響耕皮,不會(huì)因?yàn)槟骋粋€(gè)線程獲取了鎖,其它線程就處于等待時(shí)間蝙场,也就是線程A從數(shù)據(jù)庫(kù)取key1的數(shù)據(jù)并不妨礙線程B取key2的數(shù)據(jù)
    2凌停、設(shè)置熱點(diǎn)數(shù)據(jù)永不過(guò)期(物理上的不過(guò)期、“邏輯上”的不過(guò)期(緩存到期動(dòng)態(tài)構(gòu)建緩存))
簡(jiǎn)單的互斥鎖例子:
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private Jedis               jedis;
    private final String        MUTEX_KEY = "MUTEX_";

    public String getData(String key) throws InterruptedException {
        String value = stringRedisTemplate.opsForValue().get(key);
        //緩存失效
        if (StringUtils.isBlank(value)) {
            //設(shè)置分布式鎖售滤,只允許一個(gè)線程去查詢DB罚拟,同時(shí)指定過(guò)期時(shí)間為1min台诗,防止del操作失敗,導(dǎo)致死鎖赐俗,緩存過(guò)期無(wú)法加載DB數(shù)據(jù)
            if (tryLock(MUTEX_KEY + key, 60L)) {
                //從數(shù)據(jù)庫(kù)查詢數(shù)據(jù),將查詢的結(jié)果緩存起來(lái)
                value = getValueFromDB();
                stringRedisTemplate.opsForValue().set(key, value);

                //釋放分布式鎖
                stringRedisTemplate.delete(MUTEX_KEY + key);
            } else {
                //當(dāng)鎖被占用時(shí)拉队,睡眠5s繼續(xù)調(diào)用獲取數(shù)據(jù)請(qǐng)求
                Thread.sleep(5000);
                getData(key);}
        }
        return value;
    }

    /**
     * redis實(shí)現(xiàn)分布式事務(wù)鎖 嘗試獲取鎖
     * 
     * @param lockName  鎖
     * @param expireTime 過(guò)期時(shí)間
     * @return
     */
    public Boolean tryLock(String lockName, long expireTime) {
        //RedisCallback redis事務(wù)管理,將redis操作命令放到事務(wù)中處理阻逮,保證執(zhí)行的原子性
        String result = stringRedisTemplate.opsForValue().getOperations().execute(new RedisCallback<String>() {

            /**
             * @param key 使用key來(lái)當(dāng)鎖粱快,因?yàn)閗ey是唯一的。
             * @param value 請(qǐng)求標(biāo)識(shí)叔扼,可通過(guò)UUID.randomUUID().toString()生成,解鎖時(shí)通value參數(shù)可識(shí)別出是哪個(gè)請(qǐng)求添加的鎖
             * @param nx 表示SET IF NOT EXIST事哭,即當(dāng)key不存在時(shí),我們進(jìn)行set操作瓜富;若key已經(jīng)存在鳍咱,則不做任何操作
             * @param ex 表示過(guò)期時(shí)間的單位是秒
             * @param time 表示過(guò)期時(shí)間
             */
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                return jedis.set(lockName, UUID.randomUUID().toString(), "NX", "EX", expireTime);
            }
        });

        if ("OK".equals(result)) {
            return true;
        }
        return false;
    }

    public String getValueFromDB() {
        return "";
    }

3、緩存雪崩

緩存中大批量的數(shù)據(jù)都到了過(guò)期時(shí)間与柑,從而導(dǎo)致查詢數(shù)據(jù)量巨大谤辜,引起數(shù)據(jù)庫(kù)壓力過(guò)大甚至down機(jī)。和緩存擊穿不同价捧,緩存擊穿是指某一條數(shù)據(jù)到了過(guò)期時(shí)間丑念,大量的并發(fā)請(qǐng)求都來(lái)查詢這一條數(shù)據(jù),緩存雪崩是不同數(shù)據(jù)都過(guò)期了结蟋,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫(kù)

解決方案:

1渠欺、設(shè)置熱點(diǎn)數(shù)據(jù)永不過(guò)期
2、緩存數(shù)據(jù)的過(guò)期時(shí)間設(shè)置隨機(jī)椎眯,可以在原有的過(guò)期時(shí)間上加上一個(gè)隨機(jī)值,比如1-3min胳岂,防止同一時(shí)間大量緩存數(shù)據(jù)集體失效编整,導(dǎo)致數(shù)據(jù)庫(kù)壓力過(guò)大。
3乳丰、如果是分布式部署緩存數(shù)據(jù)庫(kù)掌测,可將熱點(diǎn)數(shù)據(jù)分別存放到不同的緩存數(shù)據(jù)庫(kù)中,避免某一點(diǎn)由于壓力過(guò)大而down掉产园。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末汞斧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子什燕,更是在濱河造成了極大的恐慌粘勒,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屎即,死亡現(xiàn)場(chǎng)離奇詭異庙睡,居然都是意外死亡事富,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門乘陪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)统台,“玉大人,你說(shuō)我怎么就攤上這事啡邑〖” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵谤逼,是天一觀的道長(zhǎng)贵扰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)森缠,這世上最難降的妖魔是什么拔鹰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮贵涵,結(jié)果婚禮上列肢,老公的妹妹穿的比我還像新娘。我一直安慰自己宾茂,他們只是感情好瓷马,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著跨晴,像睡著了一般欧聘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上端盆,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天怀骤,我揣著相機(jī)與錄音,去河邊找鬼焕妙。 笑死蒋伦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焚鹊。 我是一名探鬼主播痕届,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼末患!你這毒婦竟也來(lái)了研叫?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤璧针,失蹤者是張志新(化名)和其女友劉穎嚷炉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體陈莽,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡渤昌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年虽抄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片独柑。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡迈窟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忌栅,到底是詐尸還是另有隱情车酣,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布索绪,位于F島的核電站湖员,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瑞驱。R本人自食惡果不足惜娘摔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唤反。 院中可真熱鬧凳寺,春花似錦、人聲如沸彤侍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)盏阶。三九已至晒奕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間名斟,已是汗流浹背脑慧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留砰盐,地道東北人漾橙。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像楞卡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脾歇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355