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