-
當(dāng)前位置:首頁 > 創(chuàng)意學(xué)院 > 技術(shù) > 專題列表 > 正文
redis一致性hash算法
大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于redis一致性hash算法的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。
開始之前先推薦一個非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計劃、工作報告、論文、代碼、作文、做題和對話答疑等等
只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁版、PC客戶端
官網(wǎng):https://ai.de1919.com。
創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務(wù)客戶遍布全球各地,如需了解SEO相關(guān)業(yè)務(wù)請撥打電話175-8598-2043,或添加微信:1454722008
本文目錄:
一、Redis技巧:分片技術(shù)和Hash Tag
twitter的 twemproxy 是一個Redis的代理服務(wù)程序,能夠?qū)崿F(xiàn)key的分片。分片能使key均勻地分布到集群的機(jī)器上去,能保證數(shù)據(jù)的一致性,有著眾多的優(yōu)點。
但從Redis單實例切換到twemproxy集群時,還是有些需要注意的地方:
不支持的方法:
KEYS,MIGRATE,SCAN等
支持但需特殊處理的方法:
MSET,SINTERSTORE,SUNIONSTORE,ZINTERSTORE,ZUNIONSTORE等
全部請查看 Redis命令列表 .
對于不支持的方法,在使用時需要尋找替代方案。本文主要解決一下需特殊處理的方法。
單實例上的MSET是一個原子性(atomic)操作,所有給定 key 都會在同一時間內(nèi)被設(shè)置,某些給定 key 被更新而另一些給定 key 沒有改變的情況,不可能發(fā)生。
而集群上雖然也支持同時設(shè)置多個key,但不再是原子性操作。會存在某些給定 key 被更新而另外一些給定 key 沒有改變的情況。其原因是需要設(shè)置的多個key可能分配到不同的機(jī)器上。
這四個命令屬于同一類型。它們的共同之處是都需要對一組key進(jìn)行運算或操作,但要求這些key都被分配到相同機(jī)器上。
這就是分片技術(shù)的矛盾之處:
即要求key盡可能地分散到不同機(jī)器,又要求某些相關(guān)聯(lián)的key分配到相同機(jī)器。
解鈴還需系鈴人。解決方法還是從分片技術(shù)的原理上找。
分片,就是一個hash的過程:對key做md5,sha1等hash算法,根據(jù)hash值分配到不同的機(jī)器上。
為了實現(xiàn)將key分到相同機(jī)器,就需要相同的hash值,即相同的key(改變hash算法也行,但不簡單)。
但key相同是不現(xiàn)實的,因為key都有不同的用途。例如user:user1:ids保存用戶的tweets ID,user:user1:tweets保存tweet的具體內(nèi)容,兩個key不可能同名。
仔細(xì)觀察user:user1:ids和user:user1:tweets,兩個key其實有相同的地方,即user1。能不能拿這一部分去計算hash呢?
這就是 Hash Tag 。允許用key的部分字符串來計算hash。
當(dāng)一個key包含 {} 的時候,就不對整個key做hash,而僅對 {} 包括的字符串做hash。
假設(shè)hash算法為sha1。對user:{user1}:ids和user:{user1}:tweets,其hash值都等同于sha1(user1)。
Hash Tag是用于hash的部分字符串開始和結(jié)束的標(biāo)記,例如"{}"、"$$"等。
配置時,只需更改hash_tag字段即可
博客鏈接: http://spetacular.github.io/2015/09/20/redis-hash-tag.html
二、Redis集群方案應(yīng)該怎么做
使用方法和普通redis無任何區(qū)別,設(shè)置好它下屬的多個redis實例后,使用時在本需要連接redis的地方改為連接twemproxy,它會以一個代理的身份接收請求并使用一致性hash算法,將請求轉(zhuǎn)接到具體redis,將結(jié)果再返回twemproxy。
三、「干貨」redis面試題
Redis 的全稱是:Remote Dictionary.Server,本質(zhì)上是一個 Key-Value 類型的內(nèi)存數(shù)據(jù)庫,很像
memcached,整個數(shù)據(jù)庫統(tǒng)統(tǒng)加載在內(nèi)存當(dāng)中進(jìn)行操作,定期通過異步操作把數(shù)據(jù)庫數(shù)據(jù) flush 到硬盤
上進(jìn)行保存。
因為是純內(nèi)存操作,Redis 的性能非常出色,每秒可以處理超過 10 萬次讀寫操作,是已知性能最快的
Key-Value DB。
Redis 的出色之處不僅僅是性能,Redis 最大的魅力是支持保存多種數(shù)據(jù)結(jié)構(gòu),此外單個 value 的最大限
制是 1GB,不像 memcached 只能保存 1MB 的數(shù)據(jù),因此 Redis 可以用來實現(xiàn)很多有用的功能。
比方說用他的 List 來做 FIFO 雙向鏈表,實現(xiàn)一個輕量級的高性 能消息隊列服務(wù),用他的 Set 可以做高
性能的 tag 系統(tǒng)等等。
另外 Redis 也可以對存入的 Key-Value 設(shè)置 expire 時間,因此也可以被當(dāng)作一 個功能加強(qiáng)版的
memcached 來用。 Redis 的主要缺點是數(shù)據(jù)庫容量受到物理內(nèi)存的限制,不能用作海量數(shù)據(jù)的高性能
讀寫,因此 Redis 適合的場景主要局限在較小數(shù)據(jù)量的高性能操作和運算上。
1.memcached 所有的值均是簡單的字符串,redis 作為其替代者,支持更為豐富的數(shù)據(jù)類型
2.redis 的速度比 memcached 快很多 redis 的速度比 memcached 快很多
3.redis 可以持久化其數(shù)據(jù) redis 可以持久化其數(shù)據(jù)
String、List、Set、Sorted Set、hashes
內(nèi)存。
1.noeviction:返回錯誤當(dāng)內(nèi)存限制達(dá)到,并且客戶端嘗試執(zhí)行會讓更多內(nèi)存被使用的命令。
2.allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新添加的數(shù)據(jù)有空間存放。
3.volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限于在過期集合的鍵,使得新添加的數(shù)據(jù)有空間存
放。
4.allkeys-random: 回收隨機(jī)的鍵使得新添加的數(shù)據(jù)有空間存放。
5.volatile-random: 回收隨機(jī)的鍵使得新添加的數(shù)據(jù)有空間存放,但僅限于在過期集合的鍵。
6.volatile-ttl: 回收在過期集合的鍵,并且優(yōu)先回收存活時間(TTL)較短的鍵,使得新添加的數(shù)據(jù)有空間
存放。
因為目前 Linux 版本已經(jīng)相當(dāng)穩(wěn)定,而且用戶量很大,無需開發(fā) windows 版本,反而會帶來兼容性等問
題。
512M
Redis 為了達(dá)到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中,并通過異步的方式將數(shù)據(jù)寫入磁盤。
所以 redis 具有快速和數(shù)據(jù)持久化的特征,如果不將數(shù)據(jù)放在內(nèi)存中,磁盤 I/O 速度為嚴(yán)重影響 redis 的
性能。
在內(nèi)存越來越便宜的今天,redis 將會越來越受歡迎, 如果設(shè)置了最大使用的內(nèi)存,則數(shù)據(jù)已有記錄數(shù)達(dá)
到內(nèi)存限值后不能繼續(xù)插入新值。
1.codis 2.目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在節(jié)點數(shù)量改變情況下,舊節(jié)點
數(shù)據(jù)可恢復(fù)到新 hash 節(jié)點。
redis cluster3.0 自帶的集群,特點在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自
身支持節(jié)點設(shè)置從節(jié)點。具體看官方文檔介紹。
3.在業(yè)務(wù)代碼層實現(xiàn),起幾個毫無關(guān)聯(lián)的 redis 實例,在代碼層,對 key 進(jìn)行 hash 計算,然后去對應(yīng)的
redis 實例操作數(shù)據(jù)。這種方式對 hash 層代碼要求比較高,考慮部分包括,節(jié)點失效后的替代算法方
案,數(shù)據(jù)震蕩后的自動腳本恢復(fù),實例的監(jiān)控,等等。
有 A,B,C 三個節(jié)點的集群,在沒有復(fù)制模型的情況下,如果節(jié)點 B 失敗了,那么整個集群就會以為缺少
5501-11000 這個范圍的槽而不可用。
redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時候,就會施行數(shù)據(jù)淘汰策略。
(1)會話緩存(Session Cache)
最常用的一種使用 Redis 的情景是會話緩存(sessioncache),用 Redis 緩存會話比其他存儲(如
Memcached)的優(yōu)勢在于:Redis 提供持久化。當(dāng)維護(hù)一個不是嚴(yán)格要求一致性的緩存時,如果用戶的
購物車信息全部丟失,大部分人都會不高興的,現(xiàn)在,他們還會這樣嗎?
幸運的是,隨著 Redis 這些年的改進(jìn),很容易找到怎么恰當(dāng)?shù)氖褂?Redis 來緩存會話的文檔。甚至廣為
人知的商業(yè)平臺 Magento 也提供 Redis 的插件。
(2)全頁緩存(FPC)
除基本的會話 token 之外,Redis 還提供很簡便的 FPC 平臺?;氐揭恢滦詥栴},即使重啟了 Redis 實
例,因為有磁盤的持久化,用戶也不會看到頁面加載速度的下降,這是一個極大改進(jìn),類似 PHP 本地
FPC。
再次以 Magento 為例,Magento 提供一個插件來使用 Redis 作為全頁緩存后端。
此外,對 WordPress 的用戶來說,Pantheon 有一個非常好的插件 wp-redis,這個插件能幫助你以最快
速度加載你曾瀏覽過的頁面。
(3)隊列
Reids 在內(nèi)存存儲引擎領(lǐng)域的一大優(yōu)點是提供 list 和 set 操作,這使得 Redis 能作為一個很好的消息隊列
平臺來使用。Redis 作為隊列使用的操作,就類似于本地程序語言(如 Python)對 list 的 push/pop
操作。
如果你快速的在 Google 中搜索“Redis queues”,你馬上就能找到大量的開源項目,這些項目的目的
就是利用 Redis 創(chuàng)建非常好的后端工具,以滿足各種隊列需求。例如,Celery 有一個后臺就是使用
Redis 作為 broker,你可以從這里去查看。
(4)排行榜/計數(shù)器 Redis 在內(nèi)存中對數(shù)字進(jìn)行遞增或遞減的操作實現(xiàn)的非常好。集合(Set)和有序集合(SortedSet)也使
得我們在執(zhí)行這些操作的時候變的非常簡單,Redis 只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu)。
所以,我們要從排序集合中獲取到排名最靠前的 10 個用戶–我們稱之為“user_scores”,我們只需要像
下面一樣執(zhí)行即可:
當(dāng)然,這是假定你是根據(jù)你用戶的分?jǐn)?shù)做遞增的排序。如果你想返回用戶及用戶的分?jǐn)?shù),你需要這樣執(zhí)
行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games 就是一個很好的例子,用 Ruby 實現(xiàn)的,它的排行榜就是使用 Redis 來存儲數(shù)據(jù)的,你可
以在這里看到。
立聊天系統(tǒng)!
Redisson、Jedis、lettuce 等等,官方推薦使用 Redisson。
Redisson 是一個高級的分布式協(xié)調(diào) Redis 客服端,能幫助用戶在分布式環(huán)境中輕松實現(xiàn)一些 Java 的對
象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap,
List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock,
ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。
Jedis 是 Redis 的 Java 實現(xiàn)的客戶端,其 API 提供了比較全面的 Redis 命令的支持;
Redisson 實現(xiàn)了分布式和可擴(kuò)展的 Java 數(shù)據(jù)結(jié)構(gòu),和 Jedis 相比,功能較為簡單,不支持字符串操作,
Redis 集群沒有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 個哈希槽,每個 key 通
過 CRC16 校驗后對 16384 取模來決定放置哪個槽,集群的每個節(jié)點負(fù)責(zé)一部分 hash 槽。
為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,
每個節(jié)點都會有 N-1 個復(fù)制品.
Redis 并不能保證數(shù)據(jù)的強(qiáng)一致性,這意味這在實際中集群在特定的條件下可能會丟失寫操作。
異步復(fù)制
16384 個
Redis 集群目前無法做數(shù)據(jù)庫選擇,默認(rèn)在 0 數(shù)據(jù)庫。
一次請求/響應(yīng)服務(wù)器能實現(xiàn)處理新的請求即使舊的請求還未被響應(yīng),這樣就可以將多個命令發(fā)送到服務(wù)
器,而不用等待回復(fù),最后在一個步驟中讀取該答復(fù)。
這就是管道(pipelining),是一種幾十年來廣泛使用的技術(shù)。例如許多 POP3 協(xié)議已經(jīng)實現(xiàn)支持這個功
能,大大加快了從服務(wù)器下載新郵件的過程。
事務(wù)是一個單獨的隔離操作:事務(wù)中的所有命令都會序列化、按順序地執(zhí)行,事務(wù)在執(zhí)行的過程中,不會被其他客戶端發(fā)送來的命令請求所打斷。
事務(wù)是一個原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行。
MULTI、EXEC、DISCARD、WATCH
EXPIRE 和 PERSIST 命令
盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個散列表里面。
比如你的 web 系統(tǒng)中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設(shè)置單獨的 key,而是應(yīng)該把這個用戶的所有信息存儲到一張散列表里面。
一個客戶端運行了新的命令,添加了新的數(shù)據(jù)。Redi 檢查內(nèi)存使用情況,如果大于 maxmemory 的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。一個新的命令被執(zhí)行,等等。
所以我們不斷地穿越內(nèi)存限制的邊界,通過不斷達(dá)到邊界然后不斷地回收回到邊界以下。
如果一個命令的結(jié)果導(dǎo)致大量內(nèi)存被使用(例如很大的集合的交集保存到一個新的鍵),不用多久內(nèi)存限制就會被這個內(nèi)存使用量超越。
咱們來看上面那張圖,現(xiàn)在某個客戶端要加鎖。如果該客戶端面對的是一個 redis cluster 集 群,他首先會根據(jù) hash 節(jié)點選擇一臺機(jī)器。這里注意,僅僅只是選擇一臺機(jī)器!這點很關(guān) 鍵!緊接著,就會發(fā)送一段 lua 腳本到 redis 上,那段 lua 腳本如下所示:
為啥要用 lua 腳本呢?因為一大坨復(fù)雜的業(yè)務(wù)邏輯,可以通過封裝在 lua 腳本中發(fā)送給 redis, 保證這段復(fù)雜業(yè)務(wù)邏輯執(zhí)行的原子性。
那么,這段 lua 腳本是什么意思呢?這里 KEYS[1]代表的是你加鎖的那個 key,比如說:RLoc
k lock = redisson.getLock("myLock");這里你自己設(shè)置了加鎖的那個鎖 key 就是“myLock”。
ARGV[1]代表的就是鎖 key 的默認(rèn)生存時間,默認(rèn) 30 秒。ARGV[2]代表的是加鎖的客戶端的 I D,類似于下面這樣:8743c9c0-0795-4907-87fd-6c719a6b4586:1
給大家解釋一下,第一段 if 判斷語句,就是用“exists myLock”命令判斷一下,如果你要加鎖 的那個鎖 key 不存在的話,你就進(jìn)行加鎖。如何加鎖呢?很簡單,用下面的命令:hset myLoc k 8743c9c0-0795-4907-87fd-6c719a6b4586:1 1,通過這個命令設(shè)置一個 hash 數(shù)據(jù)結(jié)構(gòu),這行 命令執(zhí)行后,會出現(xiàn)一個類似下面的數(shù)據(jù)結(jié)構(gòu):
上述就代表“8743c9c0-0795-4907-87fd-6c719a6b4586:1”這個客戶端對“myLock”這個鎖 key 完 成了加鎖。接著會執(zhí)行“pexpire myLock 30000”命令,設(shè)置 myLock 這個鎖 key 的生存時間 是 30 秒。好了,到此為止,ok,加鎖完成了。
那么在這個時候,如果客戶端 2 來嘗試加鎖,執(zhí)行了同樣的一段 lua 腳本,會咋樣呢?很簡 單,第一個 if 判斷會執(zhí)行“exists myLock”,發(fā)現(xiàn) myLock 這個鎖 key 已經(jīng)存在了。接著第二 個 if 判斷,判斷一下,myLock 鎖 key 的 hash 數(shù)據(jù)結(jié)構(gòu)中,是否包含客戶端 2 的 ID,但是明 顯不是的,因為那里包含的是客戶端 1 的 ID。
所以,客戶端 2 會獲取到 pttl myLock 返回的一個數(shù)字,這個數(shù)字代表了 myLock 這個鎖 key 的剩余生存時間。比如還剩 15000 毫秒的生存時間。此時客戶端 2 會進(jìn)入一個 while 循環(huán),不 停的嘗試加鎖。
客戶端 1 加鎖的鎖 key 默認(rèn)生存時間才 30 秒,如果超過了 30 秒,客戶端 1 還想一直持有這把 鎖,怎么辦呢?
簡單!只要客戶端 1 一旦加鎖成功,就會啟動一個 watch dog 看門狗,他是一個后臺線程,會 每隔 10 秒檢查一下,如果客戶端 1 還持有鎖 key,那么就會不斷的延長鎖 key 的生存時間。
31.可重入加鎖機(jī)制
那如果客戶端 1 都已經(jīng)持有了這把鎖了,結(jié)果可重入的加鎖會怎么樣呢?比如下面這種代碼:
這時我們來分析一下上面那段 lua 腳本。第一個 if 判斷肯定不成立,“exists myLock”會顯示鎖 key 已經(jīng)存在了。第二個 if 判斷會成立,因為 myLock 的 hash 數(shù)據(jù)結(jié)構(gòu)中包含的那個 ID,就 是客戶端 1 的那個 ID,也就是“8743c9c0-0795-4907-87fd-6c719a6b4586:1” 此時就會執(zhí)行可重入加鎖的邏輯,他會用:
incrby myLock 8743c9c0-0795-4907-87fd-6c71a6b4586:1 1 ,通過這個命令,對客戶端 1 的加鎖次數(shù),累加 1。此時 myLock 數(shù)據(jù)結(jié)構(gòu)變?yōu)橄旅孢@樣:
大家看到了吧,那個 myLock 的 hash 數(shù)據(jù)結(jié)構(gòu)中的那個客戶端 ID,就對應(yīng)著加鎖的次數(shù)
如果執(zhí)行 lock.unlock(),就可以釋放分布式鎖,此時的業(yè)務(wù)邏輯也是非常簡單的。其實說白 了,就是每次都對 myLock 數(shù)據(jù)結(jié)構(gòu)中的那個加鎖次數(shù)減 1。如果發(fā)現(xiàn)加鎖次數(shù)是 0 了,說明 這個客戶端已經(jīng)不再持有鎖了,此時就會用:“del myLock”命令,從 redis 里刪除這個 key。 然后呢,另外的客戶端 2 就可以嘗試完成加鎖了。這就是所謂的分布式鎖的開源 Redisson 框 架的實現(xiàn)機(jī)制。
一般我們在生產(chǎn)系統(tǒng)中,可以用 Redisson 框架提供的這個類庫來基于 redis 進(jìn)行分布式鎖的加 鎖與釋放鎖。
其實上面那種方案最大的問題,就是如果你對某個 redis master 實例,寫入了 myLock 這種鎖 key 的 value,此時會異步復(fù)制給對應(yīng)的 master slave 實例。但是這個過程中一旦發(fā)生 redis m aster 宕機(jī),主備切換,redis slave 變?yōu)榱?redis master。
接著就會導(dǎo)致,客戶端 2 來嘗試加鎖的時候,在新的 redis master 上完成了加鎖,而客戶端 1 也以為自己成功加了鎖。此時就會導(dǎo)致多個客戶端對一個分布式鎖完成了加鎖。這時系統(tǒng)在業(yè) 務(wù)語義上一定會出現(xiàn)問題,導(dǎo)致各種臟數(shù)據(jù)的產(chǎn)生。
所以這個就是 redis cluster,或者是 redis master-slave 架構(gòu)的主從異步復(fù)制導(dǎo)致的 redis 分布 式鎖的最大缺陷:在 redis master 實例宕機(jī)的時候,可能導(dǎo)致多個客戶端同時完成加鎖。
先拿 setnx 來爭搶鎖,搶到之后,再用 expire 給鎖加一個過期時間防止鎖忘記了釋放。
如果在 setnx 之后執(zhí)行 expire 之前進(jìn)程意外 crash 或者要重啟維護(hù)了,那會怎么樣?
set 指令有非常復(fù)雜的參數(shù),這個應(yīng)該是可以同時把 setnx 和 expire 合成一條指令來用的!
緩存穿透
一般的緩存系統(tǒng),都是按照 key 去緩存查詢,如果不存在對應(yīng)的 value,就應(yīng)該去后端系統(tǒng)查找(比如DB)。一些惡意的請求會故意查詢不存在的 key,請求量很大,就會對后端系統(tǒng)造成很大的壓力。這就叫做緩存穿透。
如何避免?
1:對查詢結(jié)果為空的情況也進(jìn)行緩存,緩存時間設(shè)置短一點,或者該 key 對應(yīng)的數(shù)據(jù) insert 了之后清理緩存。
2:對一定不存在的 key 進(jìn)行過濾。可以把所有的可能存在的 key 放到一個大的 Bitmap 中,查詢時通過該 bitmap 過濾。
緩存雪崩
當(dāng)緩存服務(wù)器重啟或者大量緩存集中在某一個時間段失效,這樣在失效的時候,會給后端系統(tǒng)帶來很大壓力。導(dǎo)致系統(tǒng)崩潰。
如何避免?
1:在緩存失效后,通過加鎖或者隊列來控制讀數(shù)據(jù)庫寫緩存的線程數(shù)量。比如對某個 key 只允許一個線程查詢數(shù)據(jù)和寫緩存,其他線程等待。
2:做二級緩存,A1 為原始緩存,A2 為拷貝緩存,A1 失效時,可以訪問 A2,A1 緩存失效時間設(shè)置為短期,A2 設(shè)置為長期
3:不同的 key,設(shè)置不同的過期時間,讓緩存失效的時間點盡量均勻
四、Spring Data Redis - Redis Repositories使用技巧
使用 Redis Repositories 可以方便的在redis中用Redis Hash的方式存儲各種對象類型。
使用方法 非常簡單,僅需定義接口和在需要存儲的對象上增加注解:
在使用redis的集群模式后,redis會對數(shù)據(jù)進(jìn)行分片,分片能使key均勻地分布到集群的機(jī)器上去,能保證數(shù)據(jù)的一致性,有著眾多的優(yōu)點。但是在某些業(yè)務(wù)場景,又要求某些相關(guān)聯(lián)的key分配到相同機(jī)器。這就是分片技術(shù)的矛盾之處。
解決方法還是從分片技術(shù)的原理上找:分片,就是一個hash的過程:對key做md5,sha1等hash算法,根據(jù)hash值分配到不同的機(jī)器上。為了實現(xiàn)將key分到相同機(jī)器,就需要相同的hash值,即相同的key(改變hash算法也行,但不簡單)。但key相同是不現(xiàn)實的,因為key都有不同的用途。
例如user:user1:ids保存用戶的tweets ID,user:user1:tweets保存tweet的具體內(nèi)容,兩個key不可能同名。仔細(xì)觀察user:user1:ids和user:user1:tweets,兩個key其實有相同的地方,即user1。能不能拿這一部分去計算hash呢?
這就是Hash Tag,允許用key的部分字符串來計算hash。 當(dāng)一個key包含 {} 的時候,就不對整個key做hash,而僅對 {} 包括的字符串做hash。 假設(shè)hash算法為sha1。對user:{user1}:ids和user:{user1}:tweets,其hash值都等同于sha1(user1)。
Spring Data Redis的官方文檔 也建議在使用Cluster模式的時候使用Hash Tag,這樣可以讓對象的屬性位于同一個分片,方便查找和計算。
參考文獻(xiàn):
以上就是關(guān)于redis一致性hash算法相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。
推薦閱讀:
觸覺景觀設(shè)計手法(觸覺景觀設(shè)計手法是什么)
海外餐飲品牌設(shè)計(海外餐飲品牌設(shè)計論文)