自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

蝦皮一面:如何保證數(shù)據(jù)雙寫一致?

數(shù)據(jù)庫
數(shù)據(jù)庫和緩存雙寫一致性問題是一道經(jīng)典的面試題,最初解決方案是先更新數(shù)據(jù)庫、再刪除緩存,然而如果發(fā)生掉電情況,只執(zhí)行了前一步操作,那么緩存和數(shù)據(jù)庫就出現(xiàn)了不一致性的問題。

年關(guān)將至,又到了準備面試跳槽的季節(jié)了。據(jù)不完全統(tǒng)計,跳槽是漲薪最快的方式,沒有之一。而跳槽成功與否的關(guān)鍵是“面試”,所以認真準備面試 = 快速漲薪。

準備面試,自然就少不了刷面試真題了,而今天這份剛出爐的蝦皮 Java 后端面試題就非常典型,它的難度適中,面試結(jié)構(gòu)分為:半小時八股 + 半小時手撕代碼,是目前典型的大公司的面試方式,真題如下:

面試問題很多,一篇文章肯定是寫不完的(大部分面試題可以在我的網(wǎng)站上找到答案:www.javacn.site),咱們今天就拿里面最經(jīng)典,最常見的面試題來聊一聊:如何保證緩存和數(shù)據(jù)庫的雙寫一致性?

1、什么是雙寫一致性?

在分布式系統(tǒng)中,數(shù)據(jù)庫和緩存會搭配一起使用,以此來保證程序的整體查詢性能。

也就說,分布式系統(tǒng)為了緩解數(shù)據(jù)庫查詢的壓力,會將查出來的數(shù)據(jù)保存在緩存中,下次再查詢時,直接走緩存系統(tǒng),而不再查詢數(shù)據(jù)庫,這樣就極大的提高了整體的查詢性能。

(1)為什么緩存比數(shù)據(jù)庫快?

緩存之所以比數(shù)據(jù)庫快的主要原因有以下 3 點:

  • 內(nèi)存訪問速度快:緩存通常將數(shù)據(jù)存儲在內(nèi)存中,而數(shù)據(jù)庫將數(shù)據(jù)存儲在磁盤上。相比于磁盤訪問,內(nèi)存訪問速度更快,可以達到納秒級別的讀取速度,遠遠快于數(shù)據(jù)庫的毫秒級別的讀取速度。
  • IO 操作次數(shù)少:數(shù)據(jù)庫通常需要進行磁盤 IO 操作,包括讀取和寫入磁盤數(shù)據(jù)。而緩存將數(shù)據(jù)存儲在內(nèi)存中,避免了磁盤 IO 的開銷。內(nèi)存訪問不需要進行磁盤尋址和機械運動,相對來說速度更快。
  • 特殊的數(shù)據(jù)結(jié)構(gòu):緩存的數(shù)據(jù)結(jié)構(gòu)通常為 key-value 形式的,也就是說緩存可以做到任何數(shù)據(jù)量級下的查詢數(shù)據(jù)復(fù)雜度為 O(1),所以它的查詢效率是非常高的;而數(shù)據(jù)庫采用的是傳統(tǒng)數(shù)據(jù)結(jié)構(gòu)設(shè)計,可能需要查詢二叉樹、或全文搜索、或回表查詢等操作,所以其查詢性能是遠低于緩存系統(tǒng)的。

(2)緩存一致性問題

雖然緩存可以極大的提高查詢性能,但同時也帶來的新的問題:數(shù)據(jù)庫和緩存一致性的問題。

具體來說,在一個常見的應(yīng)用場景中,當更新數(shù)據(jù)庫的操作完成后,需要同步更新緩存,以保證緩存中的數(shù)據(jù)與數(shù)據(jù)庫中的數(shù)據(jù)保持一致。然而,由于數(shù)據(jù)庫和緩存是兩個不同的組件,它們的數(shù)據(jù)更新操作是異步的,可能存在以下問題:

  • 數(shù)據(jù)延遲:數(shù)據(jù)庫更新和緩存更新之間存在時間延遲,導(dǎo)致緩存中的數(shù)據(jù)不是最新的。這可能會引起數(shù)據(jù)的不一致,當其他請求讀取數(shù)據(jù)時,可能會讀取到舊的數(shù)據(jù)。
  • 更新失敗:在嘗試更新緩存時,可能出現(xiàn)更新失敗的情況。例如,緩存節(jié)點暫時不可用,網(wǎng)絡(luò)故障等。如果更新緩存失敗而未進行適當?shù)奶幚?,也會?dǎo)致數(shù)據(jù)庫和緩存之間的數(shù)據(jù)不一致。

也就說,因為以上原因,可能會導(dǎo)致 A 用戶和 B 用戶執(zhí)行了同一個查詢操作,但是得到了完全不同的結(jié)果,這就是數(shù)據(jù)庫和緩存的一致性問題。

2、如何解決一致性問題?

解決緩存和數(shù)據(jù)庫一致問題的常見解決方案有以下 4 種:

  • 先修改數(shù)據(jù)庫,后更新緩存。
  • 先更新緩存,后修改數(shù)據(jù)庫。
  • 先修改數(shù)據(jù)庫,后刪除緩存。
  • 先刪除緩存,后修改數(shù)據(jù)庫。

然而,前 3 種解決方案,有同一個問題,也就是當?shù)谝徊讲僮鲌?zhí)行完之后,第二步未執(zhí)行的情況下,就會導(dǎo)致數(shù)據(jù)庫和緩存的一致性問題,例如第一步執(zhí)行完之后,系統(tǒng)掉電了,那么一致性問題就會一直存在。

相比之下,第 4 種解決方案(先刪除緩存,后修改數(shù)據(jù)庫)相比于前三種解決方案更有優(yōu)勢,起碼它保證了雙方都未執(zhí)行成功,那么從數(shù)據(jù)一致性層面來講,第 4 種方案起碼保證了一定的數(shù)據(jù)一致性,然而第 4 種執(zhí)行方案依然存在其他問題,例如以下這幾個:

  • 業(yè)務(wù)完整性問題:程序只執(zhí)行了一半,第一步執(zhí)行完了但第二步未執(zhí)行的情況。
  • 并發(fā)保存舊值的問題:在并發(fā)環(huán)境下,第四種方案可能會導(dǎo)致緩存保存舊值的情況,例如以下執(zhí)行情況:

3、最終解決方案

所以,想要最大程度的雙寫一致性問題的最終解決方案是:消息隊列 + 延遲雙刪策略

(1)為什么要使用消息隊列?

因為消息隊列里面有消息確認機制,它可以保證我們執(zhí)行完第一步之后,即時掉電重啟的情況,依然可以執(zhí)行后續(xù)的流程,因為之前的消息,未進行消息確認,所以程序重啟之后,會繼續(xù)執(zhí)行后續(xù)的流程,這樣就保證了業(yè)務(wù)執(zhí)行的完整性。

(2)什么是延遲雙刪?

延遲雙刪指的是刪除兩次緩存(并且最后一次是延遲刪除),具體執(zhí)行流程如下:

  • 刪除緩存
  • 更新數(shù)據(jù)庫
  • 延遲一會再刪除緩存

最后一次延遲刪除緩存的原因是,為了避免上面因為并發(fā)問題導(dǎo)致保存舊值的情況發(fā)生,所以會延遲一段時間之后再進行刪除操作。這樣即使有并發(fā)問題,也能最大限度的解決保存舊值的情況,因為是延遲之后刪除的,所以即使因為并發(fā)問題保存了舊值,但延遲一段時間之后舊值就會被刪除,那么這樣就自然而然的保證了數(shù)據(jù)庫和緩存的最終一致性。

小結(jié)

數(shù)據(jù)庫和緩存雙寫一致性問題是一道經(jīng)典的面試題,最初解決方案是先更新數(shù)據(jù)庫、再刪除緩存,然而如果發(fā)生掉電情況,只執(zhí)行了前一步操作,那么緩存和數(shù)據(jù)庫就出現(xiàn)了不一致性的問題。為了解決這個問題,所以通常會采用延遲雙刪 + 消息隊列來保證業(yè)務(wù)的完整執(zhí)行和數(shù)據(jù)一致性問題。

責任編輯:姜華 來源: Java中文社群
相關(guān)推薦

2021-06-04 09:56:12

RedisMySQL美團

2024-08-06 09:42:23

2022-03-31 08:21:14

數(shù)據(jù)庫緩存雙寫數(shù)據(jù)一致性

2020-09-03 09:45:38

緩存數(shù)據(jù)庫分布式

2022-12-05 08:24:32

mongodb數(shù)據(jù)庫數(shù)據(jù)

2024-01-22 08:52:00

AQS雙異步數(shù)據(jù)一致性

2024-12-26 15:01:29

2019-08-30 12:46:10

并發(fā)扣款查詢SQL

2021-06-11 09:21:58

緩存數(shù)據(jù)庫Redis

2025-03-27 08:20:54

2023-09-07 08:11:24

Redis管道機制

2022-10-19 12:22:53

并發(fā)扣款一致性

2021-03-04 06:49:53

RocketMQ事務(wù)

2024-08-20 16:13:52

2023-05-26 07:34:50

RedisMySQL緩存

2024-04-11 08:01:24

RedisMysql分布式鎖

2021-12-14 07:15:57

MySQLRedis數(shù)據(jù)

2024-10-28 12:41:25

2024-10-16 09:53:07

2022-03-29 10:39:10

緩存數(shù)據(jù)庫數(shù)據(jù)
點贊
收藏

51CTO技術(shù)棧公眾號