天天看點

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

【JAVA今法修真】 第四章 redis特性 擊穿雪崩!
感謝這段時間大家的支援,關注我的微信号:南橘ryc ,回複雲小霄,就可以擷取到最新的福利靓照一張,還等什麼,趕快來加入我們吧~

“明日便是決賽了,咋隻會用法器沒練過法術呢。”。

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

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

“你知道人與動物最大的差別是什麼嗎?”李小庚沒有理會這個未來手下敗将的挑釁。

“你知道作為資料庫類型的法器,最害怕的是什麼嗎?”陳彥宇見李小庚如此目中無人,沒有再在休息室待下去,轉頭走向擂台:“希望你回去不要被你師父打屁股。”

“額,也不是不行。”

“?”

決賽現場,因為是築基期比賽,是以來的觀衆并不多,主要分為三部分:李小庚的迷妹和少量迷弟,之前的陳彥宇和李小庚的手下敗将,還有級别不夠無法觀看結丹期比賽的煉氣期弟子。

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

“哼,要不是我當初棋差一招,今天台上的兩人之中必有我。”

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

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

擂台上。

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

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

望着擂台下最大的組織“李小庚後援會”,陳彥宇心中暗暗想到:“三十年河東,三十年河西,平日裡隻教你李小庚放火,今日我陳彥宇也要點燈!”

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

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

“好!”陳彥宇被李小庚的嚣張給震驚到了,不氣反笑:“我今日便好好給你講講什麼是JMeter。”

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

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

“不知道你用了那麼久的資料庫類法器,知不知道什麼叫擊穿、雪崩和穿透!”陳彥宇仿佛已經看見了自己的勝利。

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

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

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

1、1 緩存雪崩

顧名思義,大家應該都見過雪崩,無論是現實中還是網絡上。那場景,頗有種天崩地裂的感覺,而對于資料庫來說,緩存雪崩,也說得上是一種天崩地裂了。

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

緩存雪崩如何出現的?

  • 大量的緩存同時失效,可能是同時間生成,同時間到期
  • 緩存同時被删除
  • 緩存層出現了錯誤,不能正常工作了
解決辦法:
  • 1、批量往Redis存資料的時候,把每個KEY失效時間都增加随機值,保證不會同時失效
  • 2、設定熱點資料永不過期,有更新操作就更新緩存(但是這個方法不好,永不過期導緻緩存大量堆積,很多緩存不一定有用)
  • 3、Redis叢集部署,将熱點資料均勻分布在不同Redis庫中也能避免全部失效,避免了Redis出現問題導緻緩存雪崩

1、2緩存擊穿

有一個Key非常熱點,在不停扛着大并發,大并發集中對這一點進行通路,當這個Key失效的瞬間、大量并發擊穿緩存,直接通路資料庫。

其實緩存擊穿,真的算不上什麼特别大的問題,畢竟不是每個公司都在同一個Key上都有那麼大的熱點,隻需要設定好過期時間,穩定好Redis叢集,緩存擊穿不難避免。

  • 1、設定熱點資料永不過期
  • 2、增加互斥鎖【簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作傳回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作傳回成功時,再進行load db的操作并回設緩存】
在我的經驗來看,設定互斥鎖顯然沒有必要,一個熱點永不過期就能解決的問題,為什麼還要用到鎖?這不是平白增加複雜度嗎?也許在特殊場景能看到,但是對于我這個小白來說,僅僅能在各位大牛的部落格裡看到這個觀點。

1、3緩存穿透

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

緩存穿透的概念很簡單,使用者想要查詢一個資料,發現redis記憶體資料庫沒有,也就是緩存沒有命中,于是向持久層資料庫查詢。發現也沒有,于是本次查詢失敗。當使用者很多的時候,緩存都沒有命中,于是都去請求了持久層資料庫。這會給持久層資料庫造成很大的壓力,這時候就相當于出現了緩存穿透。

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

如果一個黑客每次故意查詢一個在緩存内必然不存在的資料,導緻每次請求都要去存儲層去查詢,這樣緩存就失去了意義。如果在大流量下資料庫可能挂掉,這也是緩存擊穿。

  • 1、增加參數校驗
  • 2、從網關層Nginx增加配置項,對單個IP每秒通路次數超出門檻值的拉黑處理
  • 3、Bloom Filter 能很好地防止緩存穿透、他的原理也很簡單的就是利用高效的資料結構和算法快速判斷出你這個Key是否在資料庫,不存在直接return、存在就直接去DB重新整理KV再return
redis利用布隆過濾器來防止緩存擊穿,主要是通過将已存在的緩存放到布隆過濾器中,當黑客通路不存在的緩存時迅速傳回避免緩存及DB挂掉。

1、4布隆過濾器

布隆過濾器本質上布隆過濾器是一種資料結構,比較巧妙的機率型資料結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你 “某樣東西一定不存在或者可能存在”。

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

數組的每個元素都隻占1bit空間,并且每個元素隻能為0或1。

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

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

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

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

讓我們繼續深入

1、5布谷鳥過濾器

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

布谷鳥過濾器名稱源于采取了一種和布谷鳥一樣的養娃方法,最原始的布谷鳥哈希方法是使用兩個哈希函數對一個

key

進行哈希,得到桶中的兩個位置。
  • 如果兩個位置都為為空則将

    key

    随機存入其中一個位置
  • 如果隻有一個位置為空則存入為空的位置
  • 如果都不為空,則随機踢出一個元素,踢出的元素再重新計算哈希找到相應的位置

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

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

fp = fingerprint(x)
p1 = hash(x)
p2 = p1 ^ hash(fp)  // 異或
           
是以我們根本不需要知道目前的位置是 p1 還是 p2,隻需要将目前的位置和 hash(fp) 進行異或計算就可以得到對偶位置。而且隻需要確定 hash(fp) != 0 就可以確定 p1 != p2,如此就不會出現自己踢自己導緻死循環的問題。

聽完李小庚的介紹後,陳彥宇突然啞然失笑:“原來如此,我以為我的JMeter可以克制資料庫,是以大資料攻擊可以擊穿你的資料庫,沒想到小醜竟是我自己。”

“其實你不必懊惱,你的想法是沒錯的,克制資料庫最好的武器就是大量的資料,隻是要擊穿我整個redis叢集,你這單台伺服器運作的JMeter還是不夠看。”陳彥宇安慰道,作為勝利者自然應該有着勝利者的體面。

“即使我有足夠的JMeter伺服器,你肯定還有後手對吧。”陳彥宇不甘心的問。

“bingo!”李小庚一步一步接近被redis叢集鎖住氣息的陳彥宇,輕輕取下失去主人法力支援隻能安靜漂浮在空中的盒子:“既然Redis能儲存資料,自然也能實時的删除多餘的資料。”

二、記憶體淘汰機制

既然Redis能儲存資料,自然也就需要能删除多餘的資料,不然,空間都被占滿了,新的内容放在哪裡?聰明的程式員提出了兩個個辦法解決Redis的記憶體問題。
  • 1、定時删除——通過定時器删除過期的資料
  • 2、惰性删除——查詢後如果過期就不傳回、過期則删除。這種情況容易出現很多備援資料導緻占用大量空間

2、1、定時删除

建立一個定時器,當key設定有過期時間,且過期時間到達時,由定時器任務立即執行對鍵的删除操作,預設100ms就随機抽一些key判斷是否過期,過期的話就删除,用處理器性能換取存儲空間(拿時間換空間)
  • 優點:節約記憶體,到時就删除,快速釋放掉不必要的記憶體占用
  • 缺點:CPU壓力很大,無論CPU此時負載量多高,均占用CPU,會影響redis伺服器響應時間和指令吞吐量

2、2惰性删除

當Redis中的資料到了過期時間,我們先不做處理。等下次通路該資料時進行一次判斷,如果未過期,就正常傳回,如果發現資料已過期,立刻删除,然後傳回不存在,用存儲空間換取處理器性能(拿空間換時間)
  • 優點:節約CPU性能,發現必須删除的時候才删除
  • 缺點:記憶體壓力很大,出現長期占用記憶體的資料
不知道大家不知道發現了沒有,大部分的算法,不是時間換空間,就是空間換時間。剛剛發現這個秘密的我簡直驚呆了,這就是人類的終極奧秘之一了,隻要我們知道這個訣竅,就能解決大部分的問題。

2、3淘汰機制

在Redis的redis.config檔案中還可通過搜尋maxmemory-policy來設定淘汰機制
noeviction:當記憶體使用達到門檻值的時候,所有引起申請記憶體的指令會報錯。
allkeys-lru:在主鍵空間中,優先移除最近未使用的key。
volatile-lru:在設定了過期時間的鍵空間中,優先移除最近未使用的key。
allkeys-random:在主鍵空間中,随機移除某個key。
volatile-random:在設定了過期時間的鍵空間中,随機移除某個key。
volatile-ttl:在設定了過期時間的鍵空間中,具有更早過期時間的key優先移除。
           

“你練習過線程池神功,是以你也知道,一個适合的淘汰政策能解決許多的問題,而對于redis也一樣,我隻需要适當地修改參數,讓最近存儲的資料都快速淘汰掉,便能防止記憶體壓力過大。”李小庚一個響指解除了redis叢集對陳彥宇的鎖定,又将JMeter放到他的手中:“說到底,硬體差距太大,再好的政策也沒有用。”

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

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

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

(注:在門派同屆内修為更高者為師兄)

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

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