redis與Mysql的資料一致性

2021-09-30 13:41:48 字數 1262 閱讀 4684

為了減少db的讀壓力,加快讀速度,系統使用cache做快取,會引起cache一致性問題。因為db會有事務性導致回滾,而cache無法回滾,會導致髒資料。

一般情況下,我們會在儲存資料時,先穿透儲存到db中,再同步資料到redis中。

為了保證儲存層對外層透明,我們會把db與redis操作封裝,對上層呼叫來說完全透明,不關心資料具體如何儲存。

例如在我們的實際業務中有如下場景:a表插入一條資料,同步到redis中,b表插入一條資料,同步到redis中。如果b表插入資料失敗,事務回滾,a表中資料可以回滾,但是redis無法回滾。會導致redis中有髒資料。

facebook的一篇**給出如下設計:

查詢:先查詢cache,miss時查詢db,寫入cache

寫:寫db成功後,失效cache

重點說下寫:如果寫db成功後,寫cache,會有事務性和併發性兩方面問題。

1.事務性問題:乙個事務包含多個db操作,操作一些db成功,寫cache成功,操作二寫db失敗,事務回滾,db資料回滾,cache無法回滾,導致髒資料。

2.併發性問題:兩個更新操作併發,如更新名字,並且cache中key以名字為關鍵字,更新一寫db成功,寫快取***x_name1成功。更新二寫db成功,寫快取***x_name2成功。導致cache髒資料。

這裡再說一下一般更新操作順序是失效cache,寫db,寫cache。會有併發問題。

兩個併發操作,更新和讀,左邊寫執行緒,右邊為讀執行緒

①更新操作刪除cache

②讀操作讀cache,miss

③讀db,此時是舊資料

④寫db,寫cache

⑤寫cache

導致cache中髒資料。

雖然寫db成功後,失效cache也會有併發問題:更新和讀併發

①查詢cache

②寫db,失效cache

③寫chache

導致cache中髒資料,但是概率極低,並且一般db中寫時間長於讀時間,並且寫會鎖表,讀需要在寫前進入,並且要晚於寫操作更新快取,所以發生概率極低。

解決方法是 2pc或是paxos協議,代價較大。

所以我們採用的方式是:

寫資料只寫db

更新資料先更新db,再失效cache

讀資料,先讀cache,未命中讀db,寫入cache

redis與mysql資料同步

應用redis實現資料的讀寫,同時利用佇列處理器定時將資料寫入mysql,此種情況存在的問題主要是如何保證mysql與redis的資料同步,二者資料同步的關鍵在於mysql資料庫中主鍵,方案是在redis啟動時去mysql讀取所有表鍵值存入redis中,往redis寫資料時,對redis主鍵自增並進...

redis與mysql資料同步

應用redis實現資料的讀寫,同時利用佇列處理器定時將資料寫入mysql,此種情況存在的問題主要是如何保證mysql與redis的資料同步,二者資料同步的關鍵在於mysql資料庫中主鍵,方案是在redis啟動時去mysql讀取所有表鍵值存入redis中,往redis寫資料時,對redis主鍵自增並進...

redis與Mysql資料庫的同步

應用redis實現資料的讀寫,同時利用佇列處理器定時將資料寫入mysql,此種情況存在的問題主要是如何保證mysql與redis的資料同步,二者資料同步的關鍵在於mysql資料庫中主鍵,方案是在redis啟動時去mysql讀取所有表鍵值存入redis中,往redis寫資料時,對redis主鍵自增並進...