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

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

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

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

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

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

對于讀寫緩存,如果需要盡可能保證數(shù)據(jù)庫和緩存數(shù)據(jù)一致,使用同步直寫策略,寫數(shù)據(jù)庫后也同步寫Redis緩存;如果數(shù)據(jù)庫和緩存的數(shù)據(jù)同步容許有一定的時間間隔,比如倉庫系統(tǒng),就可以使用異步緩寫策略,寫數(shù)據(jù)庫的一段時間后再同步緩存,當出現(xiàn)異常情況需要對數(shù)據(jù)進行修補的時候,也可能需要使用異步換寫策略,比如用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ù)庫和緩存一致性的更新策略。

可以停機的情況:

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

不可以停機的情況:

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

異常情況1:

更新Redis出現(xiàn)異常時導致的問題。

異常情況2:

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

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

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

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

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

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

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

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

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日志,將對應的緩存刪除,如果沒有刪除成功,就將未成功的數(shù)據(jù)發(fā)送到消息隊列中,從消息隊列中讀取數(shù)據(jù)進行刪除緩存的重試,刪除緩存成功就把對應數(shù)據(jù)從消息隊列中刪掉,重試超過一定次數(shù)后向業(yè)務(wù)層報錯,提醒開發(fā)或者運維人員進行處理。

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

相關(guān)文章

  • Redis分片集群存儲的搭建到使用

    Redis分片集群存儲的搭建到使用

    這篇文章主要介紹了Redis分片集群存儲的搭建到使用,分片集群顧名思義,將數(shù)據(jù)分開存儲到Redis集群中,這樣能夠存儲更多的數(shù)據(jù),避免浪費資源,需要的朋友可以參考下
    2022-06-06
  • Redis實現(xiàn)延遲任務(wù)的三種方法詳解

    Redis實現(xiàn)延遲任務(wù)的三種方法詳解

    延遲任務(wù)(Delayed Task)是指在未來的某個時間點,執(zhí)行相應的任務(wù),本文為大家整理了三種常見的實現(xiàn)方法,感興趣的小伙伴可以參考一下
    2025-04-04
  • 淺談Redis的異步機制

    淺談Redis的異步機制

    命令操作、系統(tǒng)配置、關(guān)鍵機制、硬件配置等會影響 Redis 的性能,還要提前準備好應對異常的方案,本文主要介紹了Redis的異步機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • Redis Cluster Pipeline導致的死鎖問題解決

    Redis Cluster Pipeline導致的死鎖問題解決

    本文主要介紹了Redis Cluster Pipeline導致的死鎖問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-10-10
  • Redis高效率原因及數(shù)據(jù)結(jié)構(gòu)分析

    Redis高效率原因及數(shù)據(jù)結(jié)構(gòu)分析

    這篇文章主要為大家詳細的介紹了Redis高效的原因以及分析了Redis高效的數(shù)據(jù)結(jié)構(gòu),有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • redis中redis-cli使用小結(jié)

    redis中redis-cli使用小結(jié)

    redis-cli 是Redis命令行界面,一個簡單的程序,允許直接從終端向Redis發(fā)送命令,并讀取服務(wù)器發(fā)送的回復,本文主要介紹了redis中redis-cli使用小結(jié),感興趣的可以了解一下
    2023-10-10
  • Redis高可用梳理詳解

    Redis高可用梳理詳解

    高可用的本質(zhì)是有備份,在出現(xiàn)故障的時候,有backup可以提供服務(wù),本文詳細介紹了Redis的高可用,感興趣的同學可以參考閱讀
    2023-05-05
  • Redis中的連接命令與鍵命令操作詳解

    Redis中的連接命令與鍵命令操作詳解

    Redis連接命令主要是用于客戶端與服務(wù)器建立連接的,Redis是一種流行的內(nèi)存數(shù)據(jù)庫,支持多種數(shù)據(jù)結(jié)構(gòu),其中鍵命令是核心操作之一,在Redis中,鍵(Key)是用來存儲數(shù)據(jù)的主要元素,每個鍵都有一個唯一的名稱,本文給大家介紹了Redis中的連接命令與鍵命令操作
    2024-09-09
  • Redis刪除策略的三種方法及逐出算法

    Redis刪除策略的三種方法及逐出算法

    這篇文章主要介紹了Redis刪除策略的三種方法及逐出算法,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • 完美解決linux上啟動redis后配置文件未生效的問題

    完美解決linux上啟動redis后配置文件未生效的問題

    今天小編就為大家分享一篇完美解決linux上啟動redis后配置文件未生效的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05

最新評論