成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

緩存與數據庫雙寫一致性

數據庫
這篇文章就來詳細聊聊雙寫一致性。首先我們知道,現在將高速緩存應用于業務當中已經十分常見了,甚至可能跟數據庫的頻率不相上下。你的用戶量如果上去了,直接將一個裸的 MySQL 去扛住所有壓力明顯是不合理的。

[[405182]]

這幾天瞎逛,不知道在哪里瞟到了緩存的雙寫,就突然想起來這塊雖然簡單,但是細節上還是有足夠多我們可以去關注的點。這篇文章就來詳細聊聊雙寫一致性。

首先我們知道,現在將高速緩存應用于業務當中已經十分常見了,甚至可能跟數據庫的頻率不相上下。你的用戶量如果上去了,直接將一個裸的 MySQL 去扛住所有壓力明顯是不合理的。

這里的高速緩存,目前業界主流的就是 Redis 了,關于 Redis 相關的文章,之前也有聊過,在此就不贅述,感興趣的可以看看:

  • Redis 基礎數據結構和用法
  • Redis 數據持久化
  • Redis 主從同步
  • Redis Sentinel 高可用
  • Redis Cluster 集群詳解

額,不列出來我都沒感覺關于 Redis 我居然寫了這么多...言歸正傳。

在我們的業務中,普遍都會需要將一部分常用的熱點數據(或者說不經常變但是又比較多的數據)放入 Redis 中緩存起來。下次業務來請求查詢時,就可以直接將 Redis 中的數據返回,以此來減少業務系統和數據庫的交互。

這樣有兩個好處,一個是能夠降低數據庫的壓力,另一個自不必說,對相同數據來說能夠有效的降低 API 的 RT(Response Time)。

后者其實還好,降低數據庫的壓力顯得尤為重要,因為我們的業務服務雖然能夠以較低的成本做到橫向擴展,但數據庫不能。

這里的不能,其實不是指數據庫不能擴展。MySQL 在主從架構下,通過擴展 Slave 節點的數量可以有效的橫向擴展讀請求。而 Master 節點由于不是無狀態的,所以擴展起來很麻煩。

對,是很麻煩,也不是不能橫向擴展。但是在那種架構下,我舉個例子,主-主架構下,會帶來很多意向不到的數據同步問題,并且對整個的架構引入了新的復雜性。

就像我在之前寫的MySQL 主從原理中提到過的一樣,雙主架構更多的意義在于 HA,而不是做負載均衡。

所以,相同的數據會同時存在 Redis 和 MySQL 中,如果該數據并不會改變,那就完美的一匹。可現實很骨感,這個數據99.9999%的概率是一定會變的。

為了維護 Redis 和 MySQL 中數據的一致性,雙寫的問題的就誕生了。

Cache Aside Pattern

其中最經典的方案就是 Cache Aside Pattern ,這套定義了一套緩存和數據庫的讀寫方案,以此來保證緩存和數據庫中的數據一致性。

具體方案

Cache Aside Pattern 具體又分為兩種 Case,分別是讀和寫。

對于讀請求,會先去 Redis 中查詢數據,如果命中了就會直接返回數據。而如果沒有從緩存中獲取到,就會去 DB 中查詢,將查詢到的數據寫回 Redis,然后返回響應。

而更新則相對簡單,但是也是最具有爭議。當收到寫請求時,會先更新 DB 中的數據,成功之后再將緩存中的數據刪除。

注意這里是刪除,而不是更新。因為實際生產中,緩存中存放的可能不僅僅是單一的像 true、false或者1、19這種值。

為什么是刪除

還有可能在緩存中存放一整個結構體,其中包含了非常多的字段。那么是不是每次有一個字段更新就都需要去把數據從緩存中讀取出來,解析成對應的結構體,然后更新對應字段的值,再寫回緩存呢?又或者你是直接將原緩存刪除,然后又將最新的數據寫入緩存?

其實乍一看,好像沒有毛病。我更新難道不應該這么更新嗎?在這里,我們的關注點更多的放在了更新的方式上,而把更多的必要性給忽略到了。我們更新了這個值之后,在接下來的一段時間內,它會被頻繁訪問到嗎?可能會,但也可能根本不會被訪問到了。

那既然有可能不會被訪問到, 那我們為啥還要去更新它?而且,更新緩存所帶來的開銷有時侯會非常大。

然而這還只是緩存數據源單一的情況,如果緩存中緩存的是某個讀模型,其數據是通過多張表的數據計算得出的,其開銷會更大。

讀模型,簡單理解就是用現有數據,計算、統計出來的一些數據。

這個思路就類似于懶加載的方式,只在需要的時候去計算它。

爭議在哪兒?

前面提到過,更新時順序為先更新 DB 中的數據,成功之后再刪除緩存。但是也有人認為應該先刪除緩存,再去更新 DB 中的數據。

乍一看,可能并不能發現問題。甚至覺得還有那么一絲絲合理。因為如果先刪除緩存,如果刪除操作失敗,DB 中的數據也不會更新,這樣緩存和 DB 中數據也能保證一致性。而且,如果刪除緩存成功,但更新 DB 失敗了,大不了下次獲取時,再將數據寫回緩存即可,可以說十分的合理。

但,這只是單線程的情況下,如果在多線程下,會直接造成致命的數據不一致。

上面的流程圖詳細的描述了情況,更新請求1剛剛把緩存中的數據刪除,查詢請求2就過來了,查詢請求2會發現緩存中是空的,所以按照 Cache Aside Pattern 的讀請求標準,會從 DB 中加載最新的數據并將其寫入緩存。而此時更新請求1還沒有對 DB 進行更新操作,所以查詢請求2寫入到緩存中的數據仍然是舊數據。

這樣一來,查詢請求3在下一次更新之前,讀取到的就都會是老數據。然后,更新請求1將最新的數據更新至 DB,緩存和 DB 的數據就不一致了。

其實 Cache Aside Pattern 中的模式,仍然會在某些 case 下造成數據不一致。但是這個概率非常的低,因為觸發這個不一致的情況的條件太苛刻了。

首先是緩存要失效,然后讀請求、寫請求并發的執行,并且讀請求要比寫請求后執行完。為啥說概率不大呢,首先在實際生產中,讀請求一般都要比寫請求快得多。除此之外,讀請求去 DB 請求數據的時間一定要早于寫請求,并且寫緩存的時間還要一定晚于寫請求,比起最開始的那種情況來說,條件已經是非常的嚴格了。

如果完全不能容忍,可以通過 2PC 的模式去保證數據的一致性,也可以通過將請求串行化的方式來解決,但這樣的代價就是會犧牲并發量。

End

其實還有其他的幾種方案,比如 Read Throught Pattern 、Write Through Pattern、Write Around、Write Behind Caching Pattern 等等。但是這些相對于 Cache Aside Pattern 來說比較簡單,可以自己去了解一下就好。

 

責任編輯:姜華 來源: SH的全棧筆記
相關推薦

2020-09-03 09:45:38

緩存數據庫分布式

2022-03-31 08:21:14

數據庫緩存雙寫數據一致性

2018-05-16 16:10:28

數據庫緩存MySQL

2022-12-05 08:24:32

mongodb數據庫數據

2024-05-08 16:37:17

MySQLRedis數據庫

2022-12-14 08:23:30

2022-03-29 10:39:10

緩存數據庫數據

2024-10-28 12:41:25

2021-04-24 16:58:03

數據庫工具技術

2018-09-11 10:46:10

緩存數據庫一致性

2022-04-01 16:55:22

數據庫緩存日志

2019-09-20 21:50:47

數據庫緩存

2020-09-04 06:32:08

緩存數據庫接口

2025-04-27 08:52:21

Redis數據庫緩存

2017-07-25 14:38:56

數據庫一致性非鎖定讀一致性鎖定讀

2020-05-12 10:43:22

Redis緩存數據庫

2021-12-01 08:26:27

數據庫緩存技術

2024-12-26 15:01:29

2022-10-08 00:00:09

數據庫緩存系統

2017-07-02 16:28:06

MySQL數據庫集群
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91亚洲一区| 久久免费观看一级毛片 | 久久99精品久久久久久国产越南 | 欧美综合国产精品久久丁香 | 999久久久精品 | 国产成人综合在线 | 欧美日日 | 日韩亚洲一区二区 | 国产三级一区二区三区 | 国产午夜精品一区二区三区四区 | 中文字幕精品一区 | 亚洲一区二区三区免费在线观看 | 国产精品特级毛片一区二区三区 | 精品视频一区二区三区在线观看 | 国产高清亚洲 | 久草在线 | 中文日韩在线 | 日韩欧美国产一区二区三区 | 国产精品久久久久久久久久三级 | 中文字幕日韩欧美 | 欧美黄色精品 | 免费久久久久久 | 国产真实精品久久二三区 | 在线a视频 | 欧美色欧美亚洲另类七区 | 亚洲精品播放 | 六月婷婷久久 | av男人的天堂在线 | 久久久黑人 | 国产韩国精品一区二区三区 | 欧美国产日韩在线 | 人妖videosex高潮另类 | 欧美在线色视频 | 草b视频| 黄免费看| 欧美日韩一区二区在线播放 | 美女久久久久 | 日本高清不卡视频 | 亚洲免费三级 | 中文字幕 在线观看 | www.99热这里只有精品 |