欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL的緩存策略方式

 更新時(shí)間:2024年09月23日 14:25:20   作者:小辛學(xué)西嘎嘎  
MySQL緩存方案主要用于減輕數(shù)據(jù)庫(kù)讀寫壓力,通過(guò)使用Redis緩存用戶定義的熱點(diǎn)數(shù)據(jù),用戶可以直接從緩存中獲取數(shù)據(jù),文章還討論了如何通過(guò)讀寫分離、連接池和異步連接等技術(shù)提升MySQL的訪問(wèn)性能,此外,還探討了緩存方案中的一致性問(wèn)題、讀寫策略以及緩存穿透

一、MySQL 緩存方案用來(lái)干什么

用來(lái)緩存用戶定義的熱點(diǎn)數(shù)據(jù),用戶直接從緩存獲取熱點(diǎn)數(shù)據(jù),降低數(shù)據(jù)庫(kù)的讀寫壓力。

我們都知道內(nèi)存的讀取速度是磁盤訪問(wèn)速度的十萬(wàn)倍,那么這個(gè)緩存方案適用于什么場(chǎng)景呢?

1、既然讀取速度這么高,那么肯定就是讀的需求遠(yuǎn)大于寫的需求。

2、MySQL自身的緩沖層跟業(yè)務(wù)無(wú)關(guān)。MySQL中的緩存層也是用來(lái)緩存熱點(diǎn)數(shù)據(jù),但是這些數(shù)據(jù)包括索引、記錄等。mysql 緩沖層是從自身出發(fā),跟具體的業(yè)務(wù)無(wú)關(guān),而不是緩存我們用戶自己定義的熱點(diǎn)數(shù)據(jù)。

3、因此我們采用Redis作為我們的緩沖數(shù)據(jù)庫(kù),存放用戶定義的熱點(diǎn)數(shù)據(jù)。而MySQL只是作為項(xiàng)目的主要數(shù)據(jù)庫(kù),便于統(tǒng)計(jì)分析。

二、提升MySQL訪問(wèn)性能的方式

1、讀寫分離(MySQL的主從復(fù)制)

什么是讀寫分離?我們?cè)O(shè)置多個(gè)從數(shù)據(jù)庫(kù),從數(shù)據(jù)庫(kù)分布在多個(gè)不同的機(jī)器中,我們寫的操作依然是在主數(shù)據(jù)庫(kù),而讀的操作分給了從數(shù)據(jù)庫(kù),從數(shù)據(jù)庫(kù)的數(shù)據(jù)都是來(lái)自主數(shù)據(jù)庫(kù)。

這樣將讀寫進(jìn)行分離,會(huì)解決主數(shù)據(jù)庫(kù)讀的壓力。

我之前的文章講過(guò)主從之間如何進(jìn)行同步。我們得知主從之間可能會(huì)存在數(shù)據(jù)不一致的情況,但是最終的數(shù)據(jù)是一樣的,也就是可能會(huì)有延遲。比如博主寫了一篇文章并且剛剛發(fā)布,但是我的朋友說(shuō)還沒(méi)有看到,我說(shuō)你等個(gè)幾秒就好了。對(duì)于這種情況就很適合這種方案(讀取從數(shù)據(jù)庫(kù))。

但是對(duì)于讀的時(shí)效性很強(qiáng)的時(shí)候(一致性),我們就不可以讀取從數(shù)據(jù)庫(kù)了,而是直接讀取主數(shù)據(jù)庫(kù)。

2、連接池

在MySQL中存在連接池的組件,比如兩個(gè)客戶端連接上來(lái),但是我們使用多個(gè)線程去服務(wù)這幾個(gè)客戶端,可以大大提高并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)的能力,并且,連接池的資源是可以復(fù)用的,我們可以避免連接建立或斷開(kāi),以及安全驗(yàn)證的開(kāi)銷。

他的網(wǎng)絡(luò)模型采用的并不是Reactor,而是select+阻塞io模型。對(duì)于上面所說(shuō)的多個(gè)線程服務(wù)客戶端,這里要特別注意,如果我們開(kāi)啟一個(gè)事務(wù)的話,一個(gè)事務(wù)內(nèi)不是包含很多SQL語(yǔ)句嘛,我們要保證這些事務(wù)語(yǔ)句全部在一個(gè)線程內(nèi)執(zhí)行。

3、異步連接

我們上面的連接池中講到了網(wǎng)絡(luò)模型采用的是 select + 非阻塞IO 。如果是阻塞IO的話也就是同步方式,我們發(fā)送多個(gè)SQL語(yǔ)句的話,他需要一個(gè)一個(gè)進(jìn)行執(zhí)行并且一個(gè)一個(gè)進(jìn)行返回。

但是我們采用異步的方式(非阻塞IO),我們發(fā)送多個(gè)命令,那么這些命令會(huì)異步執(zhí)行,誰(shuí)執(zhí)行完畢,誰(shuí)就通過(guò)回調(diào)函數(shù)進(jìn)行返回,大大節(jié)省網(wǎng)絡(luò)傳輸?shù)臅r(shí)間。

三、緩存方案是怎么解決的

1、緩存與MySQL一致性狀態(tài)分析

可行方案不可行方案
MySQL有,Redis無(wú)MySQL無(wú),Redis有
都有,數(shù)據(jù)一致都有,數(shù)據(jù)不一致
都沒(méi)有

我們根據(jù)上面所講述的主從復(fù)制,可以得知,MySQL中必須保存全部的數(shù)據(jù),而Redis從數(shù)據(jù)庫(kù)只是保存熱點(diǎn)數(shù)據(jù)。那么我們來(lái)討論上面這個(gè)表格的情況。

可行方案中:MySQL有,Redis無(wú)。MySQL沒(méi)有熱點(diǎn)數(shù)據(jù)需要進(jìn)行存儲(chǔ),所以Redis中沒(méi)有數(shù)據(jù),也就是說(shuō),用戶查找的這個(gè)數(shù)據(jù)并不是熱點(diǎn)數(shù)據(jù)。

  • 第二種方案:都有,數(shù)據(jù)一致。MySQL中包含熱點(diǎn)數(shù)據(jù),而且Redis中也包含熱點(diǎn)數(shù)據(jù),并且是一致的數(shù)據(jù)。這樣我們查找從數(shù)據(jù)庫(kù)的時(shí)候,就不會(huì)出現(xiàn)與主數(shù)據(jù)庫(kù)查詢不同的情況了。
  • 第三種:都沒(méi)有。也就是說(shuō)用戶查找的這個(gè)數(shù)據(jù)是不存在的,所以在MySQL中也不存在。

不可行方案:MySQL無(wú),Redis有。我們講的主從復(fù)制,需要保證寫數(shù)據(jù)是寫在主數(shù)據(jù)庫(kù)中的,所以主數(shù)據(jù)庫(kù)包含全部的信息,而從數(shù)據(jù)庫(kù)是從主數(shù)據(jù)庫(kù)中進(jìn)行同步的。所以這種情況是不允許的。

  • 不可行方案:都有,數(shù)據(jù)不一致。我們講的主從復(fù)制中也說(shuō)到了從數(shù)據(jù)庫(kù)與主數(shù)據(jù)庫(kù)進(jìn)行同步可能會(huì)有延遲,但是最終數(shù)據(jù)是一致的。這樣就會(huì)導(dǎo)致我們可能讀取從數(shù)據(jù)庫(kù)的時(shí)候(讀取熱點(diǎn)數(shù)據(jù))可能會(huì)導(dǎo)致與主數(shù)據(jù)庫(kù)的數(shù)據(jù)不一致。

2、制定熱點(diǎn)數(shù)據(jù)的讀寫策略

對(duì)于讀的策略比較簡(jiǎn)單,由于是熱點(diǎn)數(shù)據(jù),我們直接讀取緩存(Redis),如果在Redis中找到了數(shù)據(jù),那就直接返回。如果未找到,那就讀取MySQL,如果在MySQL中讀到數(shù)據(jù),并且返回后,那就寫入Redis。這里寫入Redis中的是熱點(diǎn)數(shù)據(jù),并不是說(shuō),一查沒(méi)有,一查沒(méi)有,就全部寫入Redis中。

寫的策略分兩種,一種是安全為主,一種是效率為主。

如果要以安全為主,我們就要避免主數(shù)據(jù)庫(kù)和從數(shù)據(jù)庫(kù)讀取的數(shù)據(jù)不同的問(wèn)題。當(dāng)我們先寫入MySQL后,必然會(huì)出現(xiàn)MySQL與Redis數(shù)據(jù)不同的問(wèn)題,那么我們就不能先寫入MySQL。而是要先刪除Redis中的數(shù)據(jù),然后再寫入MySQL,最后將MySQL中的數(shù)據(jù)同步到Redis中去,這樣就保證兩方的數(shù)據(jù)一致了。但是我們的緩存方案就是為了提升效率,現(xiàn)在卻為了安全而降低了效率,這是我們不愿看到的。

如果要以效率為主,我們可以先寫入緩存,并且設(shè)置過(guò)期時(shí)間(大約是200毫秒),然后再寫入MySQL,當(dāng)寫入MySQL后,我們?cè)賹ySQL中的數(shù)據(jù)同步到Redis中去。當(dāng)同步到Redis中去的時(shí)候,這個(gè)過(guò)期時(shí)間也就到期了。過(guò)期時(shí)間是與MySQL網(wǎng)絡(luò)傳輸時(shí)間+MySQL處理時(shí)間+MySQL同步到Redis的時(shí)間。有個(gè)問(wèn)題是如果當(dāng)寫入MySQL寫入失敗,這個(gè)時(shí)候Redis中含有數(shù)據(jù),那么他就會(huì)提供臟數(shù)據(jù)。但是這個(gè)問(wèn)題也就200毫秒的存活時(shí)間,因?yàn)閺臄?shù)據(jù)庫(kù)會(huì)找主數(shù)據(jù)庫(kù)進(jìn)行同步。

四、緩存方案問(wèn)題的解決方法

1、緩存穿透

問(wèn)題:如果黑客讓客戶端一直讀取MySQL和Redis中都不存在的數(shù)據(jù),那么所有的讀取操作都落在了MySQL中,那么就會(huì)造成MySQL中訪問(wèn)的性能急劇降低。

解決:如果在Redis和MySQL中讀取的數(shù)據(jù)都不存在,那么就在Redis中設(shè)置一個(gè)<Key,nil>,代表查找的這個(gè)熱點(diǎn)數(shù)據(jù)不存在?;蛘卟渴?strong>布隆過(guò)濾器(類似于哈希表),使這些數(shù)據(jù)只能增加,不能刪除,具體可以搜一搜。

2、緩存擊穿

問(wèn)題:如果Redis中沒(méi)有,但是MySQL中有,也就是說(shuō)本來(lái)一個(gè)熱點(diǎn)數(shù)據(jù),在Redis中存在,但是過(guò)期了,那么大量的并發(fā)請(qǐng)求讀取操作就會(huì)落到MySQL中,這樣就造成MySQL訪問(wèn)的性能急劇降低。

解決:我們可以將過(guò)熱的數(shù)據(jù)設(shè)置成不過(guò)期的狀態(tài)?;蛘呤翘砑?strong>分布式鎖,將并發(fā)的請(qǐng)求操作,變成串行執(zhí)行。

3、緩存雪崩

問(wèn)題:我們?cè)趯懭隦edis中的數(shù)據(jù)是需要加入過(guò)期時(shí)間的,但是當(dāng)我們不小心將多個(gè)過(guò)熱數(shù)據(jù)的過(guò)期時(shí)間設(shè)置成統(tǒng)一時(shí)間,就會(huì)面臨大量熱點(diǎn)數(shù)據(jù)集中失效的問(wèn)題,雖然失效,但是在MySQL中還是存在這個(gè)數(shù)據(jù),所以大量的請(qǐng)求讀取操作就會(huì)落到MySQL中去,就會(huì)造成MySQL訪問(wèn)性能急劇降低。

解決:我們可以將這個(gè)過(guò)期時(shí)間給錯(cuò)開(kāi),避免同時(shí)過(guò)期。當(dāng)然我們可以在重啟MySQL的時(shí)候,先將一些熱數(shù)據(jù)先緩存到Redis中。

五、緩存方案的弊端

我們上面講到一個(gè)問(wèn)題就是,不能支持多語(yǔ)句的事務(wù),如果要支持的話,需要保證begin到commit之間的全部語(yǔ)句都在一條線程中執(zhí)行。而且Redis不支持回滾,并且有時(shí)候會(huì)造成Redis與MySQL數(shù)據(jù)不一致。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論