分布式快取和本地快取的一致性在專案中的解決方案

2021-10-10 03:37:10 字數 1858 閱讀 4669

先不談題目中的一致性問題,我們先看下基本業務流程

1.放入快取

a專案修改或者建立採集模型時,後台通過http介面呼叫b專案。

b專案將資訊放入redis,同時放入本地map快取:快取的key為模型的token,value為模型的所有採集字段。

為什麼需要在本地快取中放乙份?是為了當請求過來時可以查詢本地快取,而不與redis互動。這在後面會介紹。

**如下

private concurrenthashmap

> tokenandcolumns =

newconcurrenthashmap()

<

>;.

....

....

...public

static result operatorcollectmodel

(collectmodel collectmodel)

elseif(

"delete"

.equals

(collectmodel.

getoperator()

))return

newresult

<

>

(true);

}

2.查詢快取

需要說明的是,b專案存在多個節點。

b專案中某段業務邏輯是,根據請求帶過來的token引數查詢本地快取,如果本地有則無需再查詢redis;如果本地沒有,即map中不存在這個key,則查詢redis快取,並將查詢結果放入本地快取。

在第1步說過http呼叫b專案時,b專案會往本地本地快取存乙份,那這裡為什麼還會出現本地沒有的情況?因為b專案存在多個節點,http呼叫到的只是乙個節點,其它節點的本地快取沒有。

因此,當第一次請求將redis資料放入本地map後,後續同乙個節點的請求過來時,直接查詢本地快取。

**如下

//先查詢本地

mapcolumns = tokenandcolumns.

get(accesstoken);if

(collectionutils.

isempty

(columns)

)}

之後業務流程是對請求裡的採集字段進行判斷,判斷是否在快取資料中。

通過日誌發現,b專案在查詢本地快取時,查詢到的採集欄位與採集模型裡的字段不一致,但實際上redis中的採集欄位與採集模型的字段是一致的。

1.a專案第一次建立採集模型時呼叫http,b專案將資訊放入了redis和本地快取

2.之後a專案修改模型,新增了新的採集字段,由於b專案有多個節點,呼叫http時通過nginx**到了b1專案,於是b1專案將資訊放入了redis和b1的本地快取

3.此時,b專案本地快取的key雖然存在,但是value代表的採集字段不是最新的,導致b查詢到的快取資料有誤。

通過分析可知,根本原因是本地快取與redis快取不一致,解決方法如下:

新寫乙個定時任務,定時同步redis資料到本地快取。

這樣的話,假如後期修改了模型字段,在定時任務觸發前,雖然短期內redis和本地快取資料不一致,但最終肯定是一致的。

@scheduled

(cron =

"0 */1 * * * ?"

)public

void

syncredistolocal()

);}

後來b專案的redis切換了位址但沒有同步資料,在重啟後本地快取資料也丟失了。而a專案又沒有通過http呼叫b專案,於是b專案從redis和本地快取中都查不出資料。

雖然切換redis位址並不是頻繁的事,但是為了以防萬一,解決方法是b專案啟動時查詢a專案的採集模型資訊,並將資料放入redis。

分布式快取的一致性Hash演算法

具體過程 1 先構造乙個長度為0 2 32的整數環,根據節點名稱的hash值,將快取伺服器節點放置在這個hash環上。2 根據需要快取的資料的key值計算得到其hash值,然後在hash環上順時針查詢距離這個key值的hash值最近的快取伺服器節點,完成key到伺服器的hash對映查詢。補充 這個一...

分布式快取的一致性 Hash 演算法

簡單的路由演算法可以使用餘數 hash 用伺服器資料除快取資料 key 的 hash 值,餘數為伺服器列表下標編碼。這種演算法可以滿足大多數的快取路由需求。但是,當分布式快取集群需要擴容的時候,事情就變得棘手了。舉個例子 很容易可以計算出,3臺快取伺服器擴容至4臺伺服器,大約有 75 3 4 被快取...

分布式一致性

分布式一致性是指在分布式環境中對某個副本資料進行更新操作時,必須確保其他副本也會更新,避免不同副本資料不一致。分布式系統乙個重要的問題時解決資料複製,一是為了增加系統的可用性防止單點故障,二是提高系統可用性,通過負載聚恆,使分布在不同位置的資料副本能夠提供服務。理想狀態下,當然希望分布式系統能夠實現...