使用特定的數據,如redis的鍵或用戶ID,再根據節點數量N使用公式:hash(key)%N計算出hash值,用來決定數據映射到哪壹個節點上.
這種方案的問題是:
當節點數量變化時,需要重新計算hash,會導致數據的重新遷移.
2.壹致性hash算法
壹致性hash算法實現思路是為系統中每壹個節點分配壹個token,範圍在0~2^32,這些token構成壹個hash環.數據的讀寫執行節點查找操作時,先根據key計算hash值,然後順時針找到第壹個大於等於該hash的token節點.
好處:
這種方式最大的好處就是,在加入或刪除節點時,只影響hash環中相鄰的兩個節點,對其他節點無影響.
問題:
3.虛擬槽算法
使用分散度較好的hash函數,將所有的數據映射到 比如0~16383(2^14)範圍的槽中(slot).這個槽的數量壹般遠遠大於實例的數量.
槽是集群數據管理和遷移的基本單位.采用大範圍槽的主要目的是為了方便數據拆分和集群擴展.
每壹個實例會映射壹部分範圍的槽.
特點:
1.解耦數據和節點之間的關系,簡化擴容和鎖容的難度
2.節點自身維護槽的映射關系,不需要客戶端或代理服務維護槽分區的元數據.
3.支持節點,槽,鍵之間的映射查詢,用於數據路由,在線伸縮燈場景.
HashTags(面試)
Mset k1 v1 k2 v2 k3 v3
通過分片手段,可以將數據合理的劃分到不同的節點上,這本來是壹件好事。但是有的時候,我們希望對相關聯的業務以原子性方式進行操作。舉個簡單的例子
我們在單節點上執行MSET (m表示多個,壹次向redis設置多個key和值), 它是壹個原子性的操作,我們要求所有給定的key要在同壹時間內被設置,不能出現某些指定的key被更新另壹些指定的key沒有被更新的情況。但是在集群環境下,我們仍然可以執行MSET命令,但它的操作不在是原子操作,會存在某些指定的key被更新,而另外壹些指定的key沒有改變,原因是多個key可能會被分配到不同的機器上。
所以,這裏就會存在壹個矛盾點,及要求key盡可能的分散在不同機器,又要求某些相關聯的key分配到相同機器。
這個也是在面試的時候會容易被問到的內容。怎麽解決呢?
從前面的分析中我們了解到,分片其實就是壹個hash的過程,對key做hash取模然後劃分到不同的機器上。所以為了解決這個問題,我們需要考慮如何讓相關聯的key得到的hash值都相同呢?如果key全部相同是不現實的,所以怎麽解決呢?在redis中引入了HashTag的概念,可以使得數據分布算法可以根據key的某壹個部分進行計算,然後讓相關的key落到同壹個數據分片;
舉個簡單的例子,假如對於用戶的信息進行存儲,
redis:store:1001、redis:store:1002
那麽通過hashtag的方式,
redis:{store}:1001、redis:{store}:1002; 表示
當壹個key包含 {} 的時候,就不對整個key做hash,而僅對 {} 包括的字符串做hash。