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

MySQL的緩存策略方式

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

一、MySQL 緩存方案用來干什么

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

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

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

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

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

二、提升MySQL訪問性能的方式

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

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

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

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

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

2、連接池

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

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

3、異步連接

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

四、緩存方案問題的解決方法

1、緩存穿透

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

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

2、緩存擊穿

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

解決:我們可以將過熱的數(shù)據(jù)設(shè)置成不過期的狀態(tài)。或者是添加分布式鎖,將并發(fā)的請求操作,變成串行執(zhí)行。

3、緩存雪崩

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

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

五、緩存方案的弊端

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

總結(jié)

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

相關(guān)文章

最新評論