在電商服務中, 熱點商品信息存儲在Redis緩存中。數據量小的場景下,使用單個節點存儲。隨着數據量的增長,一般採用多節點集羣模式管理。算法
將請求均勻分配到各個服務器節點。假設有4個Redis服務節點,能夠取商品對象hash值,經過算法 hash(object)/(4)均勻映射到每一個服務節點數據庫
當Redis服務器從4個擴容到5個,咱們發現只有4個對象能夠命中緩存(圖中綠色的點),致使其餘大量的請求穿透緩存,壓力所有到數據庫,後果不可預料。緩存
咱們發現hash分佈的結果是關鍵,能夠將Redis服務器從4個擴容到8個這樣成倍的擴容。已經經過哈希分派到了相應的緩存,原有的映射纔不會改變。服務器
成倍的擴容彷佛解決了擴容問題,可是成倍擴容會致使資源的浪費,並且集羣的收縮性不是很好。更重要的是,Redis服務器故障移除時,一樣致使上述的穿透緩存問題。爲了解決緩存服務器數量發生變化致使的問題,咱們引入了一致性哈希算法分佈式
一致性哈希算法仍然是取模的算法。一致性Hash算法將整個哈希值空間組織成一個虛擬的圓環,一般哈希函數值空間爲0-2^32-1.函數
假設咱們有4臺服務器,Redis-1(10.0.1.156),Redis-1(10.1.2.145),Redis-1(10.2.3.112),Redis-1(10.6.4.231)
咱們使用一個簡單的hash函數:hash(Redis-1) = 1001156,將服務器映射到哈希環。
能夠看到,4個節點將哈希環分爲4個部分. 假設有個商品A的Hash值爲2157132,找到在hash環上的範圍1064231~1001156,而後順時針查找第一個服務器節點Redis-1,就是咱們的緩存節點。以此類推圖中4個商品存儲在哪一個緩存節點上。spa
一致性哈希算法是否解決了緩存服務器數量發生變化致使的問題?
咱們假設節點Redis-1故障了,商品A的Hash值爲2157132,找到在hash環上的位置,而後順時針查找第一個服務器節點Redis-2.Hash值落在其餘區間的對象和服務器的映射關係沒有收到影響。設計
咱們新增節點Redis-5(1072132),商品A的Hash值爲2157132,找到在hash環上的範圍1064231~1072132,而後順時針查找第一個服務器節點Redis-5. Hash值落在其餘區間的對象和服務器的映射關係沒有收到影響。3d
當服務器節點發生變動,只有部分緩存失效,不會出現大範圍緩存失效的問題。對象
上文講到節點Redis-1故障時,全部緩存在節點Redis-1的數據都會緩存到節點Redis-2上,這樣就會致使一個緩存分佈不均衡的問題,大量緩存集中在某幾個節點上。
從另外一個角度來講,是hash環沒有被平均的切分致使的散列不均衡。那麼咱們多建立幾個節點就能解決這個問題。由於實際上物理服務器是固定的,那麼咱們建立虛擬節點作分佈。
爲每一個Redis節點建立3個虛擬節點,虛擬節點自身關聯到物理節點。
因爲多個節點,整個hash環被分紅9個區間,Redis-1 負責映射到區間2,4,6的對象,總體來看每一個Redis服務器承擔的區間壓力更加均勻。
一致性哈希算法設計是爲了解決分佈式Cache中提出的,設計目標是爲了解決在分佈式服務節點變動,使用簡單哈希算法帶來的問題。在實際使用中,如何保證分佈式服務的穩定性,是服務設計首先要考慮的問題。