單個redis實例無論是存儲容量還是請求處理能力最后都會受限于單機的性能,隨著數(shù)據(jù)量和請求量的增長柒昏,必然要尋求redis集群的解決方案凳宙。在redis推出早期,redis自身并沒有集群的方案职祷,但是業(yè)界在使用redis的時候有不少集群方案氏涩。到了redis 3.0,redis內(nèi)建了集群方案有梆,稱之為redis cluster是尖。集群設(shè)計核心是將眾多的key分散存放到多個不同的實例上去,另外要考慮的問題就是高可用以及可擴展泥耀。
為了實現(xiàn)集群的功能饺汹,從服務(wù)端、客戶端的角度來看痰催,可以分為以下三類:
- 客戶端實現(xiàn): 典型的是支持一致性哈希的客戶端
- 代理層實現(xiàn): 典型代表twemproxy兜辞、codis
- redis服務(wù)端實現(xiàn): redis cluster
客戶端實現(xiàn)redis集群
在客戶端實現(xiàn)redis集群,通常的使用場景是把redis單純當作簡單的緩存來使用夸溶,就像使用memcache那樣使用redis逸吵。一般的策略是使用一致性哈希。實際應(yīng)用中缝裁,在客戶端實現(xiàn)redis集群功能并不是一個好方案扫皱,它存在維護管理困難的問題,當需要這么做時請考慮在代理層做捷绑。
代理層實現(xiàn)redis集群
在redis 3.0推出redis cluster之前啸罢,代理層實現(xiàn)redis集群是首選方案,twemproxy和codis是最常見的兩個代理胎食。
twemproxy實現(xiàn)redis集群
twemproxy實現(xiàn)redis集群的方案主要通過twemproxy配置里的distribution來控制的扰才,不同的distribution可以適用于不同的場景,比較如下:
項目 | ketama | modula | random |
---|---|---|---|
KEY分布 | 一致性哈希方式將key分布到不同的redis實例上 | 通過對key的哈希值求模分布到相應(yīng)的redis實例上 | 隨機分布key |
高可用 | 可以通過開啟自動屏蔽失效節(jié)點來自動更新一致性哈希環(huán)厕怜,從而實現(xiàn)依賴一致性哈希的高可用 | 內(nèi)建沒有對高可用的支持衩匣,可以通過外部控制在有節(jié)點失效時更新配置并重啟 | 開啟自動屏蔽失效節(jié)點功能,或同modula |
可擴展 | 直接添加redis節(jié)點重啟代理即可 | 只能雙倍擴容粥航,數(shù)據(jù)同步過程中需要重啟twemproxy琅捏,重啟過程中可能丟失一點最新的數(shù)據(jù),擴容后各redis實例里會殘留垃圾數(shù)據(jù)递雀,如果未設(shè)置超時時間的話需要手工清理 | 直接添加redis節(jié)點重啟代理即可 |
適用場景 | 緩存使用 | 緩存或存儲使用 | 隊列使用柄延,較少使用 |
問題 | 一致性哈希雖然既可以實現(xiàn)高可用也可以實現(xiàn)可擴展,但實際上這兩點做的都不夠好,在一致性哈希環(huán)改變的時候會造成短期的緩存命中率下降搜吧,在大量請求的情況下這可能是不可接受的市俊,有可能瞬間把后端數(shù)據(jù)庫擊垮;在網(wǎng)絡(luò)抖動情況下,哈希環(huán)可能持續(xù)多次改變滤奈,這可能會帶來臟數(shù)據(jù)的問題;在有多個代理的時候摆昧,還可能因為種種原因?qū)е赂鞔砩瞎-h(huán)不一致的問題。 | 高可用需要額外依賴其它組件來實現(xiàn)蜒程,可擴展問題上面已提出 | 較少使用 |
codis實現(xiàn)redis集群
與twemproxy不一樣绅你,codis不單純是一款代理軟件,它包括了好幾個組件昭躺,不過在這里我們不細講忌锯,只介紹其實現(xiàn)redis集群的基本原理。兩個主要的組件是codis-server(redis修改版本)和codis-proxy领炫,codis在邏輯上劃分出1024個slot偶垮,每個codis-server實例可以擁有多個slot,而key則通過計算哈希值來求模分布到這1024個slot中驹吮,codis-proxy知道每個slot位于哪個codis-server里针史。對高可用的支持codis依賴redis-sentinel晶伦,而對可擴展的支持是通過遷移slot到新的codis-server實例上來實現(xiàn)的碟狞。
redis cluster
redis cluster原理上和codis差不多,同樣是引入了slot的概念婚陪,不過redis cluster有16384個slot族沃。redis cluster自身集成了高可用的功能,可擴展也是通過遷移slot來實現(xiàn)的泌参。但是對客戶端來說脆淹,redis cluster和單個redis實例相比它在請求響應(yīng)上帶來了MOVE/ASK語義,也就意味著之前的redis客戶端無法直接獲得全部集群功能沽一,需要增加對MOVE/ASK響應(yīng)的支持才可以訪問整個集群盖溺。
為了讓客戶端透明的訪問redis cluster,可以在中間加一層代理铣缠,predixy是一個不錯的選擇
方案選擇
基于客戶端的方案任何時候都要慎重考慮烘嘱,在此我們不予推薦。
基于twemproxy的方案雖然看起來功能挺全面蝗蛙,但是實際使用中存在的問題同樣很多蝇庭,具體見上述,目前也不推薦再用twemproxy的方案捡硅。
codis在redis cluster出來之前應(yīng)該是最理想的一種redis集群解決方案哮内,但是codis需要采用其自身修改版的redis,因此這和redis社區(qū)版本會有差異壮韭,因此無法及時跟進redis社區(qū)版本更新北发,而對于那些自己對redis有所改動的用戶來講纹因,那更不便使用codis。同時codis-proxy是go語言編寫鲫竞,在性能方面辐怕,尤其是耗時表現(xiàn)損耗較多。
redis cluster自redis 3.0推出以來从绘,目前已經(jīng)在很多生產(chǎn)環(huán)境上得到了應(yīng)用寄疏,目前來講,構(gòu)建redis集群僵井,推薦采用redis cluster搭配一款支持redis cluster的代理方案陕截。