最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis和MySQL保證雙寫一致性的問題解析

 更新時(shí)間:2023年11月17日 09:43:21   作者:仍沫  
Redis和MySQL的雙寫一致性指的是在同時(shí)使用緩存和數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)的時(shí)候,保證Redis和MySQL中數(shù)據(jù)的一致性,那么如何才能保證他們的一致性呢,下面小編就來為大家詳細(xì)講講

Redis和MySQL的雙寫一致性指的是在同時(shí)使用緩存和數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)的時(shí)候,保證Redis和MySQL中數(shù)據(jù)的一致性。

用戶發(fā)起請(qǐng)求,先從Redis中查取數(shù)據(jù),有數(shù)據(jù)就直接返回,沒有數(shù)據(jù)就從MySQL中查詢數(shù)據(jù),并且存儲(chǔ)到Redis中,然后返回。從MySQL中查詢到數(shù)據(jù)再存入Redis中這個(gè)步驟稱為回寫。

上述這種有回寫的緩存稱為讀寫緩存,僅僅用于查詢的緩存稱為只讀緩存,只讀緩存中的數(shù)據(jù)是通過命令或者批量腳本從MySQL中寫到Redis的。

對(duì)于讀寫緩存,如果需要盡可能保證數(shù)據(jù)庫和緩存數(shù)據(jù)一致,使用同步直寫策略,寫數(shù)據(jù)庫后也同步寫Redis緩存;如果數(shù)據(jù)庫和緩存的數(shù)據(jù)同步容許有一定的時(shí)間間隔,比如倉庫系統(tǒng),就可以使用異步緩寫策略,寫數(shù)據(jù)庫的一段時(shí)間后再同步緩存,當(dāng)出現(xiàn)異常情況需要對(duì)數(shù)據(jù)進(jìn)行修補(bǔ)的時(shí)候,也可能需要使用異步換寫策略,比如用Kafka或RabbitMQ之類的消息中間件重寫數(shù)據(jù)。

源碼地址,文中只展示關(guān)鍵代碼。

雙檢加鎖策略

從緩存中查詢兩次,并且加上互斥鎖。

func (dao *UserDAO) FindByID(c context.Context, userID int64) (u domain.User, err error) {
	db := dao.db
	rdb := dao.rdb
	key := fmt.Sprintf("user:%v", userID)

	// 1. 從緩存中查詢數(shù)據(jù),如果有數(shù)據(jù)就返回
	var user domain.User
	val, err := rdb.Get(c, key).Result()
	if val != "" && err == nil {
		err := json.Unmarshal([]byte(val), &user)
		if err == nil {
			return user, nil
		}
	}
	// 2. 沒有查到數(shù)據(jù)就加鎖再查一次
	mu.Lock()
	defer mu.Unlock()
	val, err = rdb.Get(c, key).Result()
	// 2.1 從緩存中查到數(shù)據(jù)就直接返回
	if val != "" && err == nil {
		err := json.Unmarshal([]byte(val), &user)
		if err == nil {
			return user, nil
		}
	}
	// 2.2 沒有從緩存中查到數(shù)據(jù)就從數(shù)據(jù)庫中查詢
	err = db.Where("id=?", userID).First(&user).Error
	if err != nil {
		return user, err
	}
	// 3. 將從數(shù)據(jù)庫中拿到的數(shù)據(jù)寫到緩存中
	userStr, err := json.Marshal(user)
	if err == nil {
		rdb.Set(c, key, userStr, 1000*time.Second)
	}
	return user, nil
}

數(shù)據(jù)庫和緩存一致性的幾種更新策略

上面說的是查詢策略,接下來說一下數(shù)據(jù)庫和緩存一致性的更新策略。

可以停機(jī)的情況:

? 比如先往MySQL中灌入1萬條數(shù)據(jù),再同步到Redis中,可以在凌晨升級(jí),給出升級(jí)提示。

不可以停機(jī)的情況:

1.先更新數(shù)據(jù)庫,再更新緩存(不可行)

異常情況1:

更新Redis出現(xiàn)異常時(shí)導(dǎo)致的問題。

異常情況2:

并發(fā)情況下執(zhí)行順序的不確定性導(dǎo)致的問題。

2.先更新緩存,再更新數(shù)據(jù)庫(不可行)

和1一樣,因?yàn)椴l(fā)可能造成MySQL和Redis中的數(shù)據(jù)不一致。并且一般要把MySQL作為底單數(shù)據(jù),保證最后解釋。

3.先刪除緩存,再更新數(shù)據(jù)庫(不可行)

兩個(gè)并發(fā)操作,一個(gè)時(shí)更新操作,一個(gè)是查詢操作,由于執(zhí)行順序的不確定性,可能導(dǎo)致緩存中存儲(chǔ)的是舊數(shù)據(jù),并且一直是舊數(shù)據(jù)。

可以悲觀地認(rèn)為在A更新數(shù)據(jù)期間,一定會(huì)有B來讀取數(shù)據(jù),在A寫完數(shù)據(jù)庫之后,延遲一段時(shí)間,再次刪除緩存中的數(shù)據(jù)。但是當(dāng)業(yè)務(wù)中讀取數(shù)據(jù)庫和寫緩存的時(shí)間不好估算時(shí),這個(gè)延遲的時(shí)間不好設(shè)置。

4.先更新數(shù)據(jù)庫,再刪除緩存

先更新數(shù)據(jù)庫也不是完全能保證數(shù)據(jù)一致性的,但是造成的影響比較小。只是在緩存刪除失敗或者來不及刪除的時(shí)候,導(dǎo)致查詢請(qǐng)求訪問Redis時(shí)緩存命中,讀取到的是緩存舊值。

func (dao *UserDAO) UpdateUserData(c context.Context, userID int64, name string) (user User, err error) {
   db := dao.db
   rdb := dao.rdb
   key := fmt.Sprintf("user:%v", userID)
   user.ID = userID

   // 先更新數(shù)據(jù)庫中的數(shù)據(jù)
   u := User{
   	Name: name,
   }
   err = db.Model(&user).
   	Select("Name").
   	Where("id=?", userID).Updates(u).Error
   if err != nil {
   	return user, err
   }

   // 再刪除緩存中的數(shù)據(jù)
   err = rdb.Del(c, key).Err()
   if err != nil {
   	return user, err
   }
   return user, nil
}

5.比較穩(wěn)妥的方式

通過非業(yè)務(wù)代碼訂閱MySQL的binlog日志,將對(duì)應(yīng)的緩存刪除,如果沒有刪除成功,就將未成功的數(shù)據(jù)發(fā)送到消息隊(duì)列中,從消息隊(duì)列中讀取數(shù)據(jù)進(jìn)行刪除緩存的重試,刪除緩存成功就把對(duì)應(yīng)數(shù)據(jù)從消息隊(duì)列中刪掉,重試超過一定次數(shù)后向業(yè)務(wù)層報(bào)錯(cuò),提醒開發(fā)或者運(yùn)維人員進(jìn)行處理。

到此這篇關(guān)于Redis和MySQL保證雙寫一致性的問題解析的文章就介紹到這了,更多相關(guān)Redis MySQL雙寫一致性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis-cli -p 6379 info命令詳解

    redis-cli -p 6379 info命令詳解

    這篇文章主要介紹了redis-cli -p 6379 info命令詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 解讀Redis秒殺優(yōu)化方案(阻塞隊(duì)列+基于Stream流的消息隊(duì)列)

    解讀Redis秒殺優(yōu)化方案(阻塞隊(duì)列+基于Stream流的消息隊(duì)列)

    該文章介紹了使用Redis的阻塞隊(duì)列和Stream流的消息隊(duì)列來優(yōu)化秒殺系統(tǒng)的方案,通過將秒殺流程拆分為兩條流水線,使用Redis緩存緩解數(shù)據(jù)庫壓力,并結(jié)合Lua腳本進(jìn)行原子性判斷,使用阻塞隊(duì)列和消息隊(duì)列異步處理訂單,有效提高了系統(tǒng)的并發(fā)處理能力和可用性
    2025-02-02
  • Redis通過scan查找不過期的 key(方法詳解)

    Redis通過scan查找不過期的 key(方法詳解)

    SCAN 命令是一個(gè)基于游標(biāo)的迭代器,每次被調(diào)用之后, 都會(huì)向用戶返回一個(gè)新的游標(biāo), 用戶在下次迭代時(shí)需要使用這個(gè)新游標(biāo)作為 SCAN 命令的游標(biāo)參數(shù), 以此來延續(xù)之前的迭代過程,對(duì)Redis scan 查找 key相關(guān)知識(shí)感興趣的朋友一起看看吧
    2021-08-08
  • Redis獲取某個(gè)前綴的key腳本實(shí)例

    Redis獲取某個(gè)前綴的key腳本實(shí)例

    這篇文章主要給大家介紹了關(guān)于Redis獲取某個(gè)前綴的key腳本的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-04-04
  • 簡單粗暴的Redis數(shù)據(jù)備份和恢復(fù)方法

    簡單粗暴的Redis數(shù)據(jù)備份和恢復(fù)方法

    這里我們來講解一個(gè)簡單粗暴的Redis數(shù)據(jù)備份和恢復(fù)方法,有一個(gè)在不同主機(jī)上遷移Redis數(shù)據(jù)的示例,還有一個(gè)備份腳本實(shí)現(xiàn)的關(guān)鍵點(diǎn)提示,一起來看一下:
    2016-06-06
  • 幾分鐘教你掌握Redis簡單動(dòng)態(tài)字符串SDS

    幾分鐘教你掌握Redis簡單動(dòng)態(tài)字符串SDS

    這篇文章主要為大家介紹了幾分鐘教你掌握Redis簡單動(dòng)態(tài)字符串SDS方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Redis 搭建哨兵集群的操作步驟

    Redis 搭建哨兵集群的操作步驟

    在 主從架構(gòu)Redis搭建主從集群 中,一個(gè)slave節(jié)點(diǎn)掛了無影響,但是master節(jié)點(diǎn)掛了,就無法進(jìn)行寫操作了,影響高可用,Redis 提供了哨兵(Sentinel)機(jī)制來實(shí)現(xiàn)主從集群的自動(dòng)故障恢復(fù),本文給大家介紹了Redis 搭建哨兵集群的操作步驟,需要的朋友可以參考下
    2023-08-08
  • Redis bgsave的使用小結(jié)

    Redis bgsave的使用小結(jié)

    BGSAVE是Redis用于生成 RDB 持久化文件的核心操作,本文就來詳細(xì)的介紹一下Redis bgsave的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-04-04
  • Rocky9部署redis的實(shí)現(xiàn)示例

    Rocky9部署redis的實(shí)現(xiàn)示例

    本文主要介紹了Rocky9部署redis的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Redis基本數(shù)據(jù)類型Set常用操作命令

    Redis基本數(shù)據(jù)類型Set常用操作命令

    這篇文章主要為大家介紹了Redis基本數(shù)據(jù)類型Set常用操作命令,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05

最新評(píng)論

自治县| 滦南县| 卫辉市| 永善县| 淮北市| 凤阳县| 大洼县| 栾城县| 灯塔市| 天津市| 大埔县| 浦北县| 会理县| 海南省| 酒泉市| 祁连县| 江永县| 山西省| 兴文县| 霍林郭勒市| 永胜县| 龙泉市| 博湖县| 寻乌县| 类乌齐县| 邻水| 安义县| 尼勒克县| 泗水县| 老河口市| 浦江县| 都江堰市| 疏勒县| 洛宁县| 松潘县| 赣榆县| 清远市| 公主岭市| 洪雅县| 澄城县| 松原市|