欧美一区2区三区4区公司二百,国产精品婷婷午夜在线观看,自拍偷拍亚洲精品,国产美女诱惑一区二区

歡迎來到云服務(wù)器

大數(shù)據(jù)技術(shù)

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

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

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

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

Redis 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)和用法 Redis 數(shù)據(jù)持久化 Redis 主從同步 Redis Sentinel 高可用 Redis Cluster 集群詳解

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

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

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

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

這里的不能,其實不是指數(shù)據(jù)庫不能擴展。MySQL 在主從架構(gòu)下,通過擴展 Slave 節(jié)點的數(shù)量可以有效的橫向擴展讀請求。而 Master 節(jié)點由于不是無狀態(tài)的,所以擴展起來很麻煩。

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

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

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

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

Cache Aside Pattern

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

具體方案

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

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

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

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

為什么是刪除

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

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

那既然有可能不會被訪問到, 那我們?yōu)樯哆€要去更新它?而且,更新緩存所帶來的開銷有時侯會非常大。

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

讀模型,簡單理解就是用現(xiàn)有數(shù)據(jù),計算、統(tǒng)計出來的一些數(shù)據(jù)。

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

爭議在哪兒?

前面提到過,更新時順序為先更新 DB 中的數(shù)據(jù),成功之后再刪除緩存。但是也有人認(rèn)為應(yīng)該先刪除緩存,再去更新 DB 中的數(shù)據(jù)。

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

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

騰訊云代理

Copyright © 2003-2021 MFISP.COM. 國外vps服務(wù)器租用 夢飛云服務(wù)器租用 版權(quán)所有 ? 粵ICP備11019662號

主站蜘蛛池模板: 柏乡县| 汾西县| 乌兰县| 新沂市| 金山区| 永吉县| 赣州市| 康定县| 理塘县| 德阳市| 泸溪县| 深圳市| 定陶县| 瓦房店市| 汤原县| 通辽市| 府谷县| 沙洋县| 郴州市| 辉南县| 龙陵县| 项城市| 曲麻莱县| 宁安市| 永定县| 六枝特区| 同心县| 桐乡市| 石泉县| 阿尔山市| 栖霞市| 连城县| 醴陵市| 磐石市| 五寨县| 林州市| 柏乡县| 大同县| 于都县| 江陵县| 河南省|