Redis一致性方案

2021-10-25 06:13:49 字數 1248 閱讀 2954

儘管到目前為止,我在專案中很少遇到快取不一致問題,僅有一次是因為**原因。就是那次讓我考慮快取不一致的解決方案,網上有很方案,例如加鎖,訊息佇列,或延遲刪除,還有監控binlog日誌,以及用lua實現樂觀鎖,但我以為這些方案都不是太理想,要麼增加了系統的複雜度,要麼不能做到實時一致性。一天我漫步在乙個江南水鄉的小鎮上。突發奇想:很多方案都是利用序列化的方式實現快取一致性。那我為什麼不能利用資料庫的特性去實現呢?於是有了以下方案:

首先關聯式資料庫中對同一記錄寫與寫之是互斥的,這表示乙個寫事條沒有提交,另乙個寫事務將阻塞在**。那麼這兩個操作就是乙個序列化操作了:

/**

**/@transactial()

//定義整個方法體為事務邊界

public

void

update

(entity e)

以上**很輕鬆地解決了寫與寫之前的併發問題。那麼寫與讀呢?

讀資料流程通常是這樣的:

public entity get

(int id)

return e;

}

oracle資料預設隔離級別為:readcommit,在這種級別下,對同一條記錄讀與寫可以並行執行。那麼可能存在以下問題,在執get方法時,讀到update方法中事務提交之前的資料,當update執行完畢後,get方法中put資料。這時候redis就會存在一條髒資料。mysql是repeatable read隔離級別,應該不會出現髒讀問題吧(我沒做過實驗)。

對於讀和寫並行的問題我想是否可以讓讀操作中,對快取只新增不修修改。redis提供的原子操作可以輕鬆實現這點:

public entity get

(int id)

return e;

}

最後乙個問題,那就是刪除,刪除與讀之間操作可能存在問題,如下圖

如上圖,可見在刪與讀之間可能髒資料問題。解決方案可以如下,刪除時,不執行redis中的刪除操作,而是執行put操作,將乙個代表刪除的物件put到redis中,並設制ttl時間為半分種。

public

void

delete

(int id)

以上是我自己琢磨出來的一套方案,但未付之行動。或許以有機會,我會去做一些實驗。

最終一致性方案

訊息傳送一致性 微服務架構下,需要通過網路進行通訊,就自然引入了資料傳輸的不確定性,也就是cap原理中的p 分割槽容錯,而這裡的訊息傳送一致性是可靠訊息的保證。生成訊息的業務動作與訊息傳送的一致 e.g 如果業務操作成功,那麼由這個業務操作所產生的訊息一定會成功投遞出去,否則就丟失訊息 如上圖,保證...

強一致性 弱一致性 最終一致性

這種方式在es等分布式系統中也有體現,可以設定主shard提交即返回成功,或者需要replica shard提交成功再返回。提到分布式架構就一定繞不開 一致性 問題,而 一致性 其實又包含了資料一致性和事務一致性兩種情況,本文主要討論資料一致性 事務一致性指acid 複製是導致出現資料一致性問題的唯...

Redis快取一致性

用過redis的應該都清楚,redis作為記憶體快取,只是他查詢快的一大優勢,關係型資料庫只能用作儲存重要資料,或者備份快取的資料,這個時候,不可避免,我們會遇到快取中的資料與關係型資料庫中的資料不一致的情況。出現不一致的現象很常見,如果你是單個使用者肯定不會出現這種情況,如果在多執行緒併發的情況下...