Redis數(shù)據(jù)一致性詳解
1、一致性
一致性是指系統(tǒng)中各節(jié)點(diǎn)數(shù)據(jù)保持一致。分布式系統(tǒng)中,可以理解為多個(gè)節(jié)點(diǎn)中的數(shù)據(jù)是一致的。
一致性根據(jù)嚴(yán)苛程度分類:
強(qiáng)一致性:寫進(jìn)去的數(shù)據(jù)是什么,讀出來的數(shù)據(jù)就是什么,對性能影響最大;
弱一致性:數(shù)據(jù)寫入成功后,系統(tǒng)不保證能立刻讀出最新的數(shù)據(jù),也不承諾多久之后數(shù)據(jù)可以達(dá)到一致,但保證到某個(gè)時(shí)間級別后,數(shù)據(jù)能達(dá)到一致;
最終一致性:最終一致性是弱一致性的一個(gè)特例,最終一致性同樣只保證數(shù)據(jù)寫入成功后,在某個(gè)時(shí)間點(diǎn)后數(shù)據(jù)會(huì)達(dá)到一致。這個(gè)系統(tǒng)無法保證強(qiáng)一致性的時(shí)間片段被稱為不一致窗口。不一致時(shí)間窗口的時(shí)間長短取決于很多因素,比如副本個(gè)數(shù)、網(wǎng)絡(luò)延遲、系統(tǒng)負(fù)載等。
最終一致性是弱一致性中非常受大眾推崇的一種一致性模型,也是目前業(yè)界在大型分布式系統(tǒng)的數(shù)據(jù)一致性上比較推崇的模型。
2、緩存使用場景
對于大部分系統(tǒng)而言,高并發(fā)常見于讀數(shù)據(jù)的場景,對于此場景我們可以使用緩存提升數(shù)據(jù)查詢速度。當(dāng)我們使用Redis作緩存的時(shí)候,常見場景如下所示:
緩存存在
如果數(shù)據(jù)在緩存中存在,則直接從緩存返回?cái)?shù)據(jù)至應(yīng)用,無需查詢數(shù)據(jù)庫
緩存不存在
如果數(shù)據(jù)在緩存中不存在,則需查詢數(shù)據(jù)庫獲取數(shù)據(jù)并更新緩存。
對于大部分系統(tǒng)而言最終數(shù)據(jù)都會(huì)存儲在數(shù)據(jù)庫中,也就是系統(tǒng)需已數(shù)據(jù)庫中數(shù)據(jù)為準(zhǔn),那么對于上圖緩存存在的場景下,當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生變化時(shí),就可能會(huì)出現(xiàn)數(shù)據(jù)不一致的問題。
實(shí)際情況下考慮網(wǎng)絡(luò)、操作、異常等種種因素,根本無法保證可以同時(shí)更新所有副本數(shù)據(jù)使得數(shù)據(jù)保持一致。因此,如何在最大程度上保證各副本數(shù)據(jù)一致的同時(shí)也不影響系統(tǒng)性能,成了各系統(tǒng)需要均衡的問題。
3、數(shù)據(jù)同步策略
為保證緩存數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)一致,主要考慮如下兩種策略實(shí)現(xiàn):
1、先刪除緩存,再更新數(shù)據(jù)庫;
2、先更新數(shù)據(jù)庫,再刪除緩存;
當(dāng)然除了這兩種策略之外,還有其他策略如將刪除緩存改為更新緩存,但考慮高頻繁更新及熱冷數(shù)據(jù)場景下緩存使用效率問題,個(gè)人不推薦更新緩存方式,所以此處不做展開。
3.1 先刪除緩存,在更新數(shù)據(jù)庫
操作流程如圖
如上圖,若先刪除緩存,再更新數(shù)據(jù)庫,則可能存在如下問題:
若步驟5、6、7順序發(fā)生在步驟3、4之前或步驟3更新失敗,則步驟8中線程B查詢出的數(shù)據(jù)為舊數(shù)據(jù),導(dǎo)致重新寫入緩存的也為舊數(shù)據(jù)。
3.1.1 解決思路
失敗重試 + 延時(shí)雙刪
如圖中紅色部分所述,線程A在步驟4數(shù)據(jù)更新成功后,延遲一段時(shí)間,再次刪除緩存,這樣即可解決并發(fā)場景下線程B并發(fā)操作導(dǎo)致緩存與數(shù)據(jù)庫數(shù)據(jù)不一致問題。延遲時(shí)間視實(shí)際業(yè)務(wù)場景對時(shí)間敏感度而定。
3.2 先更新數(shù)據(jù)庫,再刪除緩存
操作流程如圖
如上圖,若先更新數(shù)據(jù)庫,再刪除緩存,則可能存在如下問題:
步驟5、6發(fā)生在步驟3之前或步驟3刪除緩存失敗,則線程B通過步驟5會(huì)拿到緩存數(shù)據(jù),但此時(shí)獲取到的緩存數(shù)據(jù)仍為舊數(shù)據(jù)。
3.2.1 解決思路
訂閱binlog
數(shù)據(jù)庫的每一步操作均會(huì)寫入binlog日志,可以通過監(jiān)聽binlog,實(shí)時(shí)感知數(shù)據(jù)變化情況,根據(jù)數(shù)據(jù)變化情況刪除redis并添加重試機(jī)制,直至redis刪除成功。
引入消息隊(duì)列
上圖步驟3中若Redis刪除失敗,則將Redis key放入消息隊(duì)列,消費(fèi)端監(jiān)聽消息隊(duì)列并刪除Redis直至刪除成功;
總結(jié)
需要注意的是3.1.1 和 3.2.1中描述的解決方案也只能保證最終數(shù)據(jù)一致性,無法保證強(qiáng)一致性,如上述各場景中若線程A操作異常,在通過3.1.1 和 3.2.1的方式解決問題之前,其他線程仍有可能獲取到臟數(shù)據(jù)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Redis緩存預(yù)熱的實(shí)現(xiàn)方法
緩存預(yù)熱是一種在程序啟動(dòng)或緩存失效之后,主動(dòng)將熱點(diǎn)數(shù)據(jù)加載到緩存中的策略,本文將給大家分享一下如何實(shí)現(xiàn)Redis的緩存預(yù)熱,文中有詳細(xì)的實(shí)現(xiàn)代碼,需要的朋友可以參考下2023-10-10基于redis實(shí)現(xiàn)世界杯排行榜功能項(xiàng)目實(shí)戰(zhàn)
前段時(shí)間,做了一個(gè)世界杯競猜積分排行榜。對世界杯64場球賽勝負(fù)平進(jìn)行猜測,猜對+1分,錯(cuò)誤+0分,一人一場只能猜一次。下面通過本文給大家分享基于redis實(shí)現(xiàn)世界杯排行榜功能項(xiàng)目實(shí)戰(zhàn),感興趣的朋友一起看看吧2018-10-10基于redis 7.2.3的makefile源碼解讀學(xué)習(xí)
這篇文章主要為大家介紹了基于redis 7.2.3的makefile源碼解讀學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Redis如何實(shí)現(xiàn)數(shù)據(jù)庫讀寫分離詳解
Redis的主從架構(gòu),能幫助我們實(shí)現(xiàn)讀多,寫少的情況,下面這篇文章主要給大家介紹了關(guān)于Redis如何實(shí)現(xiàn)數(shù)據(jù)庫讀寫分離的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03redis實(shí)現(xiàn)session共享的方法
本文主要介紹了redis實(shí)現(xiàn)session共享的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04Redis?Lua腳本實(shí)現(xiàn)ip限流示例
這篇文章主要介紹了Redis?Lua腳本實(shí)現(xiàn)ip限流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Redis+PHP實(shí)現(xiàn)用戶消息推送每天最多通知2次的功能
在開發(fā)應(yīng)用程序中,經(jīng)常需要向用戶推送消息通知,但是為了避免過多的打擾用戶,我們希望限制每天最多通知2次,本篇博文將介紹如何使用PHP和Redis實(shí)現(xiàn)這一功能,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-10-10