【JAVA今法修真】 第四章 redis特性 擊穿雪崩!

今法修真.jpg

感謝這段時間大家的支持,關(guān)注我的微信號:南橘ryc ,回復(fù)云小霄,就可以獲取到最新的福利靚照一張,還等什么,趕快來加入我們吧~

“明日便是決賽了,咋只會用法器沒練過法術(shù)呢?!薄?/p>

選手休息室內(nèi),一臉嫉妒的陳彥宇盯著正在擦拭(炫耀)法器的李小庚,揶揄道。

陳彥宇,通遼州可汗市人,三年前突破筑基期,在去往天道劍宗的路上被兇人擄走,待醒來時已經(jīng)出現(xiàn)在了萬法仙門里。當(dāng)時身邊站著一個聲音像極了綁架自己的兇人的人,他自稱是萬法仙門教研室主任。據(jù)那人描述當(dāng)時正在行俠仗義,發(fā)現(xiàn)陳彥宇被邪惡的天道劍宗的邪修抓住,便怒從心生,與其大戰(zhàn)了三百回合,最后解救下自己,同時并且為了補償自己便強行將自己收入門下。

“你知道人與動物最大的區(qū)別是什么嗎?”李小庚沒有理會這個未來手下敗將的挑釁。

“你知道作為數(shù)據(jù)庫類型的法器,最害怕的是什么嗎?”陳彥宇見李小庚如此目中無人,沒有再在休息室待下去,轉(zhuǎn)頭走向擂臺:“希望你回去不要被你師父打屁股?!?/p>

“額,也不是不行。”

“?”


決賽現(xiàn)場,因為是筑基期比賽,所以來的觀眾并不多,主要分為三部分:李小庚的迷妹和少量迷弟,之前的陳彥宇和李小庚的手下敗將,還有級別不夠無法觀看結(jié)丹期比賽的煉氣期弟子。

“李小庚師兄好帥!李小庚師兄必勝!”

“哼,要不是我當(dāng)初棋差一招,今天臺上的兩人之中必有我?!?/p>

“解說呢?解說快點就位,馬上開始了!”

作為傳統(tǒng)老牌強派,萬法仙門門派大比的基本秩序還是有的,至少不會出現(xiàn)什么賣瓜子花生潛水艇之類的流動小販。

擂臺上。

李小庚還是那一襲白衣(云霄殿專屬校服),配上背后若隱若現(xiàn)的如羽毛般的紅白飛劍,如同天使降臨,一瞥一笑皆是畫卷。

陳彥宇那邊則顯得普通很多,普通的萬法仙門弟子服裝加上手上普通的小盒子。

望著擂臺下最大的組織“李小庚后援會”,陳彥宇心中暗暗想到:“三十年河?xùn)|,三十年河西,平日里只教你李小庚放火,今日我陳彥宇也要點燈!”

“李小庚,你可知JMeter?”陳彥宇舉起手中的小盒子,活脫脫就像銀角大王拿著葫蘆。

“知道怎樣,不知又怎樣?”李小庚撇了撇灰蒙蒙的盒子,又看了看自己背后的天使之翼,笑麻了。

“好!”陳彥宇被李小庚的囂張給震驚到了,不氣反笑:“我今日便好好給你講講什么是JMeter?!?/p>

JMeter忽然自己漂浮在空中,陳彥宇則像是在進行鋼琴演奏一般,雙手在上面揮舞出了殘影,無數(shù)只有修真人士才能看見的電磁波從盒子上向李小庚激蕩而出。

jmeter -n -t testplan/RedisLock.jmx -l testplan/result/result.txt -e -o testplan/webreport

“不知道你用了那么久的數(shù)據(jù)庫類法器,知不知道什么叫擊穿、雪崩和穿透!”陳彥宇仿佛已經(jīng)看見了自己的勝利。

作為一個正常的筑基期弟子,參加普通的門派大比,一路打敗各殿優(yōu)秀弟子終于走到了決賽,卻發(fā)現(xiàn)決賽的對手不僅帥的慘絕人寰,還從一開始就拿出了很多金丹真人都沒有的大殺器redis集群,對于任何人來說都是崩潰的。不過,針對這種數(shù)據(jù)庫類型的法器,陳彥宇還是有過了解的,只需要通過大量的數(shù)據(jù)擊穿對方一點,便能夠讓其超載重啟。那個時候,這個自己和小白臉就可以正面對決了,甚至法器超載還會影響對方的處理能力。

“看來你對redis的了解實在是太少了。”李小庚甚至直接背對著陳彥宇,背后紅白小劍組成的翅膀無風(fēng)自動,完全無視了陳彥宇的攻擊。

一、redis解決緩存雪崩、擊穿、穿透問題

1、1 緩存雪崩

顧名思義,大家應(yīng)該都見過雪崩,無論是現(xiàn)實中還是網(wǎng)絡(luò)上。那場景,頗有種天崩地裂的感覺,而對于數(shù)據(jù)庫來說,緩存雪崩,也說得上是一種天崩地裂了。

同一時間Redis緩存大面積失效,那一瞬間Redis跟不存在一樣,這個時候數(shù)據(jù)直接請求到數(shù)據(jù)庫。你想想,緩存的意義就是減少DB,如果緩存沒有了,大量的請求還不直接打爆數(shù)據(jù)庫?

緩存雪崩如何出現(xiàn)的?

  • 大量的緩存同時失效,可能是同時間生成,同時間到期
  • 緩存同時被刪除
  • 緩存層出現(xiàn)了錯誤,不能正常工作了

解決辦法:

  • 1、批量往Redis存數(shù)據(jù)的時候,把每個KEY失效時間都增加隨機值,保證不會同時失效
  • 2、設(shè)置熱點數(shù)據(jù)永不過期,有更新操作就更新緩存(但是這個方法不好,永不過期導(dǎo)致緩存大量堆積,很多緩存不一定有用)
  • 3、Redis集群部署,將熱點數(shù)據(jù)均勻分布在不同Redis庫中也能避免全部失效,避免了Redis出現(xiàn)問題導(dǎo)致緩存雪崩

1、2緩存擊穿

有一個Key非常熱點,在不??钢蟛l(fā),大并發(fā)集中對這一點進行訪問,當(dāng)這個Key失效的瞬間、大量并發(fā)擊穿緩存,直接訪問數(shù)據(jù)庫。

其實緩存擊穿,真的算不上什么特別大的問題,畢竟不是每個公司都在同一個Key上都有那么大的熱點,只需要設(shè)置好過期時間,穩(wěn)定好Redis集群,緩存擊穿不難避免。

解決辦法:

  • 1、設(shè)置熱點數(shù)據(jù)永不過期
  • 2、增加互斥鎖【簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當(dāng)操作返回成功時,再進行l(wèi)oad db的操作并回設(shè)緩存】

在我的經(jīng)驗來看,設(shè)置互斥鎖顯然沒有必要,一個熱點永不過期就能解決的問題,為什么還要用到鎖?這不是平白增加復(fù)雜度嗎?也許在特殊場景能看到,但是對于我這個小白來說,僅僅能在各位大牛的博客里看到這個觀點。

1、3緩存穿透

從名字上來看,緩存擊穿和緩存穿透很像,實際上頁比較像,但是既然區(qū)分了出來,自然有一些不同的地方

緩存穿透的概念很簡單,用戶想要查詢一個數(shù)據(jù),發(fā)現(xiàn)redis內(nèi)存數(shù)據(jù)庫沒有,也就是緩存沒有命中,于是向持久層數(shù)據(jù)庫查詢。發(fā)現(xiàn)也沒有,于是本次查詢失敗。當(dāng)用戶很多的時候,緩存都沒有命中,于是都去請求了持久層數(shù)據(jù)庫。這會給持久層數(shù)據(jù)庫造成很大的壓力,這時候就相當(dāng)于出現(xiàn)了緩存穿透。

但是,緩存穿透真正要防止的是黑客。

如果一個黑客每次故意查詢一個在緩存內(nèi)必然不存在的數(shù)據(jù),導(dǎo)致每次請求都要去存儲層去查詢,這樣緩存就失去了意義。如果在大流量下數(shù)據(jù)庫可能掛掉,這也是緩存擊穿。
解決辦法:

  • 1、增加參數(shù)校驗
  • 2、從網(wǎng)關(guān)層Nginx增加配置項,對單個IP每秒訪問次數(shù)超出閾值的拉黑處理
  • 3、Bloom Filter 能很好地防止緩存穿透、他的原理也很簡單的就是利用高效的數(shù)據(jù)結(jié)構(gòu)和算法快速判斷出你這個Key是否在數(shù)據(jù)庫,不存在直接return、存在就直接去DB刷新KV再return

redis利用布隆過濾器來防止緩存擊穿,主要是通過將已存在的緩存放到布隆過濾器中,當(dāng)黑客訪問不存在的緩存時迅速返回避免緩存及DB掛掉。

1、4布隆過濾器

布隆過濾器本質(zhì)上布隆過濾器是一種數(shù)據(jù)結(jié)構(gòu),比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu)(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你 “某樣?xùn)|西一定不存在或者可能存在”。

布隆過濾器是由一個很長的bit數(shù)組和一系列哈希函數(shù)組成的。

數(shù)組的每個元素都只占1bit空間,并且每個元素只能為0或1。

布隆過濾器擁有k個哈希函數(shù),當(dāng)一個元素加入布隆過濾器時,會使用k個哈希函數(shù)對其進行k次計算,得到k個哈希值,并且根據(jù)得到的哈希值,在位數(shù)組中把對應(yīng)下標的值置位1。

判斷某個數(shù)是否在布隆過濾器中,就對該元素進行k次哈希計算,得到的值在位數(shù)組中判斷每個元素是否都為1,如果每個元素都為1,就說明這個值在布隆過濾器中。

當(dāng)插入的元素越來越多時,當(dāng)一個不在布隆過濾器中的元素,經(jīng)過同樣規(guī)則的哈希計算之后,得到的值在位數(shù)組中查詢,有可能這些位置因為其他的元素先被置1了。

所以布隆過濾器存在誤判的情況,但是如果布隆過濾器判斷某個元素不在布隆過濾器中,那么這個值就一定不在。

讓我們繼續(xù)深入

1、5布谷鳥過濾器

為了解決布隆過濾器不能刪除元素的問題, 論文《Cuckoo Filter:Better Than Bloom》作者提出了布谷鳥過濾器。相比布隆過濾器,布谷鳥過濾器有以下幾點:查詢性能更強、空間利用效率更高、支持反向操作(刪除)以及計數(shù)。

布谷鳥過濾器名稱源于采取了一種和布谷鳥一樣的養(yǎng)娃方法,最原始的布谷鳥哈希方法是使用兩個哈希函數(shù)對一個key進行哈希,得到桶中的兩個位置。

  • 如果兩個位置都為為空則將key隨機存入其中一個位置
  • 如果只有一個位置為空則存入為空的位置
  • 如果都不為空,則隨機踢出一個元素,踢出的元素再重新計算哈希找到相應(yīng)的位置

布谷鳥過濾器源于布谷鳥哈希算法,他巧妙的設(shè)計了一個獨特的 hash 函數(shù),使得可以根據(jù) p1 和 元素指紋 直接計算出 p2,而不需要完整的 x 元素。

從下面的公式中可以看出,當(dāng)我們知道 fp 和 p1,就可以直接算出 p2。同樣如果我們知道 p2 和 fp,也可以直接算出 p1。

fp = fingerprint(x)
p1 = hash(x)
p2 = p1 ^ hash(fp)  // 異或

所以我們根本不需要知道當(dāng)前的位置是 p1 還是 p2,只需要將當(dāng)前的位置和 hash(fp) 進行異或計算就可以得到對偶位置。而且只需要確保 hash(fp) != 0 就可以確保 p1 != p2,如此就不會出現(xiàn)自己踢自己導(dǎo)致死循環(huán)的問題。

聽完李小庚的介紹后,陳彥宇突然啞然失笑:“原來如此,我以為我的JMeter可以克制數(shù)據(jù)庫,所以大數(shù)據(jù)攻擊可以擊穿你的數(shù)據(jù)庫,沒想到小丑竟是我自己?!?/p>

“其實你不必懊惱,你的想法是沒錯的,克制數(shù)據(jù)庫最好的武器就是大量的數(shù)據(jù),只是要擊穿我整個redis集群,你這單臺服務(wù)器運行的JMeter還是不夠看。”陳彥宇安慰道,作為勝利者自然應(yīng)該有著勝利者的體面。

“即使我有足夠的JMeter服務(wù)器,你肯定還有后手對吧?!标悘┯畈桓市牡膯枴?/p>

“bingo!”李小庚一步一步接近被redis集群鎖住氣息的陳彥宇,輕輕取下失去主人法力支持只能安靜漂浮在空中的盒子:“既然Redis能儲存數(shù)據(jù),自然也能實時的刪除多余的數(shù)據(jù)?!?/p>

二、內(nèi)存淘汰機制

既然Redis能儲存數(shù)據(jù),自然也就需要能刪除多余的數(shù)據(jù),不然,空間都被占滿了,新的內(nèi)容放在哪里?聰明的程序員提出了兩個個辦法解決Redis的內(nèi)存問題。

  • 1、定時刪除——通過定時器刪除過期的數(shù)據(jù)
  • 2、惰性刪除——查詢后如果過期就不返回、過期則刪除。這種情況容易出現(xiàn)很多冗余數(shù)據(jù)導(dǎo)致占用大量空間

2、1、定時刪除

創(chuàng)建一個定時器,當(dāng)key設(shè)置有過期時間,且過期時間到達時,由定時器任務(wù)立即執(zhí)行對鍵的刪除操作,默認100ms就隨機抽一些key判斷是否過期,過期的話就刪除,用處理器性能換取存儲空間(拿時間換空間)

  • 優(yōu)點:節(jié)約內(nèi)存,到時就刪除,快速釋放掉不必要的內(nèi)存占用

  • 缺點:CPU壓力很大,無論CPU此時負載量多高,均占用CPU,會影響redis服務(wù)器響應(yīng)時間和指令吞吐量

2、2惰性刪除

當(dāng)Redis中的數(shù)據(jù)到了過期時間,我們先不做處理。等下次訪問該數(shù)據(jù)時進行一次判斷,如果未過期,就正常返回,如果發(fā)現(xiàn)數(shù)據(jù)已過期,立刻刪除,然后返回不存在,用存儲空間換取處理器性能(拿空間換時間)

  • 優(yōu)點:節(jié)約CPU性能,發(fā)現(xiàn)必須刪除的時候才刪除

  • 缺點:內(nèi)存壓力很大,出現(xiàn)長期占用內(nèi)存的數(shù)據(jù)

不知道大家不知道發(fā)現(xiàn)了沒有,大部分的算法,不是時間換空間,就是空間換時間。剛剛發(fā)現(xiàn)這個秘密的我簡直驚呆了,這就是人類的終極奧秘之一了,只要我們知道這個訣竅,就能解決大部分的問題。

2、3淘汰機制

在Redis的redis.config文件中還可通過搜索maxmemory-policy來設(shè)置淘汰機制

noeviction:當(dāng)內(nèi)存使用達到閾值的時候,所有引起申請內(nèi)存的命令會報錯。
allkeys-lru:在主鍵空間中,優(yōu)先移除最近未使用的key。
volatile-lru:在設(shè)置了過期時間的鍵空間中,優(yōu)先移除最近未使用的key。
allkeys-random:在主鍵空間中,隨機移除某個key。
volatile-random:在設(shè)置了過期時間的鍵空間中,隨機移除某個key。
volatile-ttl:在設(shè)置了過期時間的鍵空間中,具有更早過期時間的key優(yōu)先移除。

“你練習(xí)過線程池神功,所以你也知道,一個適合的淘汰策略能解決許多的問題,而對于redis也一樣,我只需要適當(dāng)?shù)匦薷膮?shù),讓最近存儲的數(shù)據(jù)都快速淘汰掉,便能防止內(nèi)存壓力過大?!崩钚「粋€響指解除了redis集群對陳彥宇的鎖定,又將JMeter放到他的手中:“說到底,硬件差距太大,再好的策略也沒有用?!?/p>

“你要做甚?”陳彥宇很不解的看著李小庚的行為:“你是在羞辱我嗎?”

“你不是要和我正面對決嗎?我給你這個機會!”說罷,redis集群像一群小蜜蜂一樣,回到了李長庚的空間戒指內(nèi)。

陳彥宇已經(jīng)被李小庚的才學(xué)與氣度所折服,本來想就此認輸,但是為了給對方留下一個好印象,便最大程度運起《Java真經(jīng)》,全力以赴道:“長庚師兄,雖然我知道無論是否使用法器,你的修為都在我之上,但是你也要小心哦,我不會差你太多的!”

(注:在門派同屆內(nèi)修為更高者為師兄)

您好,我是南橘,萬法仙門的掌門,剛剛從九州世界穿越到地球,因為時空亂流的影響導(dǎo)致我的法力全失,現(xiàn)在不得不通過這個平臺向廣大修真天才們借去力量。你們的每一個點贊,每一個關(guān)注都是讓我回到九州世界的助力,兄弟萌來為我注入修為吧!關(guān)注WX號:南橘ryc 。

等我回去以后,大家都是萬法仙門的長老,我會給大家數(shù)不盡的天材地寶,人人如龍,全民飛升。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容