Redis集群方案

Redis集群方案

通常,為了提高網(wǎng)站響應(yīng)速度牵素,總是把熱點(diǎn)數(shù)據(jù)保存在內(nèi)存中而不是直接從后端數(shù)據(jù)庫中讀取粮揉。Redis是一個(gè)很好的Cache工具巡李。大型網(wǎng)站應(yīng)用,熱點(diǎn)數(shù)據(jù)量往往巨大扶认,幾十G上百G是很正常的事兒侨拦,在這種情況下,如何正確架構(gòu)Redis呢蝠引?

首先阳谍,無論我們是使用自己的物理主機(jī),還是使用云服務(wù)主機(jī)螃概,內(nèi)存資源往往是有限制的,scale up不是一個(gè)好辦法鸽疾,我們需要scale out橫向可伸縮擴(kuò)展吊洼,這需要由多臺(tái)主機(jī)協(xié)同提供服務(wù),即分布式多個(gè)Redis實(shí)例協(xié)同運(yùn)行制肮。

其次冒窍,目前硬件資源成本降低,多核CPU豺鼻,幾十G內(nèi)存的主機(jī)很普遍综液,對(duì)于主進(jìn)程是單線程工作的Redis,只運(yùn)行一個(gè)實(shí)例就顯得有些浪費(fèi)儒飒。同時(shí)谬莹,管理一個(gè)巨大內(nèi)存不如管理相對(duì)較小的內(nèi)存高效。因此桩了,實(shí)際使用中附帽,通常一臺(tái)機(jī)器上同時(shí)跑多個(gè)Redis實(shí)例。

1.Redis官方集群方案 Redis Cluster

Redis Cluster是一種服務(wù)器Sharding技術(shù)井誉,3.0版本開始正式提供蕉扮。

Redis Cluster中,Sharding采用slot(槽)的概念颗圣,一共分成16384個(gè)槽喳钟,這有點(diǎn)兒類pre sharding思路。對(duì)于每個(gè)進(jìn)入Redis的鍵值對(duì)在岂,根據(jù)key進(jìn)行散列奔则,分配到這16384個(gè)slot中的某一個(gè)中。使用的hash算法也比較簡單洁段,就是CRC16后16384取模应狱。

Redis集群中的每個(gè)node(節(jié)點(diǎn))負(fù)責(zé)分?jǐn)傔@16384個(gè)slot中的一部分,也就是說祠丝,每個(gè)slot都對(duì)應(yīng)一個(gè)node負(fù)責(zé)處理疾呻。當(dāng)動(dòng)態(tài)添加或減少node節(jié)點(diǎn)時(shí)除嘹,需要將16384個(gè)槽做個(gè)再分配,槽中的鍵值也要遷移岸蜗。當(dāng)然尉咕,這一過程,在目前實(shí)現(xiàn)中璃岳,還處于半自動(dòng)狀態(tài)年缎,需要人工介入。

Redis集群铃慷,要保證16384個(gè)槽對(duì)應(yīng)的node都正常工作单芜,如果某個(gè)node發(fā)生故障,那它負(fù)責(zé)的slots也就失效犁柜,整個(gè)集群將不能工作洲鸠。

為了增加集群的可訪問性,官方推薦的方案是將node配置成主從結(jié)構(gòu)馋缅,即一個(gè)master主節(jié)點(diǎn)扒腕,掛n個(gè)slave從節(jié)點(diǎn)。這時(shí)萤悴,如果主節(jié)點(diǎn)失效瘾腰,Redis Cluster會(huì)根據(jù)選舉算法從slave節(jié)點(diǎn)中選擇一個(gè)上升為主節(jié)點(diǎn),整個(gè)集群繼續(xù)對(duì)外提供服務(wù)覆履。這非常類似前篇文章提到的Redis Sharding場(chǎng)景下服務(wù)器節(jié)點(diǎn)通過Sentinel監(jiān)控架構(gòu)成主從結(jié)構(gòu)蹋盆,只是Redis Cluster本身提供了故障轉(zhuǎn)移容錯(cuò)的能力。

Redis Cluster的新節(jié)點(diǎn)識(shí)別能力内狗、故障判斷及故障轉(zhuǎn)移能力是通過集群中的每個(gè)node都在和其它nodes進(jìn)行通信怪嫌,這被稱為集群總線(cluster bus)。它們使用特殊的端口號(hào)柳沙,即對(duì)外服務(wù)端口號(hào)加10000岩灭。例如如果某個(gè)node的端口號(hào)是6379,那么它與其它nodes通信的端口號(hào)是16379赂鲤。nodes之間的通信采用特殊的二進(jìn)制協(xié)議噪径。

對(duì)客戶端來說,整個(gè)cluster被看做是一個(gè)整體数初,客戶端可以連接任意一個(gè)node進(jìn)行操作找爱,就像操作單一Redis實(shí)例一樣,當(dāng)客戶端操作的key沒有分配到該node上時(shí)泡孩,Redis會(huì)返回轉(zhuǎn)向指令车摄,指向正確的node,這有點(diǎn)兒像瀏覽器頁面的302 redirect跳轉(zhuǎn)。

Redis Cluster是Redis 3.0以后才正式推出吮播,時(shí)間較晚变屁,目前能證明在大規(guī)模生產(chǎn)環(huán)境下成功的案例還不是很多,需要時(shí)間檢驗(yàn)意狠。

2.Redis Sharding集群

多Redis實(shí)例服務(wù)粟关,比單Redis實(shí)例要復(fù)雜的多,這涉及到定位环戈、協(xié)同闷板、容錯(cuò)、擴(kuò)容等技術(shù)難題院塞。這里遮晚,我們介紹一種輕量級(jí)的客戶端Redis Sharding技術(shù)。

Redis Sharding可以說是Redis Cluster出來之前迫悠,業(yè)界普遍使用的多Redis實(shí)例集群方法鹏漆。其主要思想是采用哈希算法將Redis數(shù)據(jù)的key進(jìn)行散列,通過hash函數(shù)创泄,特定的key會(huì)映射到特定的Redis節(jié)點(diǎn)上。這樣括蝠,客戶端就知道該向哪個(gè)Redis節(jié)點(diǎn)操作數(shù)據(jù)鞠抑。

慶幸的是,java redis客戶端驅(qū)動(dòng)jedis忌警,已支持Redis Sharding功能搁拙,即ShardedJedis以及結(jié)合緩存池的ShardedJedisPool。

Jedis的Redis Sharding實(shí)現(xiàn)具有如下特點(diǎn):

  1. 采用一致性哈希算法(consistent hashing)法绵,將key和節(jié)點(diǎn)name同時(shí)hashing箕速,然后進(jìn)行映射匹配,采用的算法是MURMUR_HASH朋譬。采用一致性哈希而不是采用簡單類似哈希求模映射的主要原因是當(dāng)增加或減少節(jié)點(diǎn)時(shí)盐茎,不會(huì)產(chǎn)生由于重新匹配造成的rehashing。一致性哈希只影響相鄰節(jié)點(diǎn)key分配徙赢,影響量小字柠。

  2. 為了避免一致性哈希只影響相鄰節(jié)點(diǎn)造成節(jié)點(diǎn)分配壓力,ShardedJedis會(huì)對(duì)每個(gè)Redis節(jié)點(diǎn)根據(jù)名字(沒有狡赐,Jedis會(huì)賦予缺省名字)會(huì)虛擬化出160個(gè)虛擬節(jié)點(diǎn)進(jìn)行散列窑业。根據(jù)權(quán)重weight,也可虛擬化出160倍數(shù)的虛擬節(jié)點(diǎn)枕屉。用虛擬節(jié)點(diǎn)做映射匹配常柄,可以在增加或減少Redis節(jié)點(diǎn)時(shí),key在各Redis節(jié)點(diǎn)移動(dòng)再分配更均勻,而不是只有相鄰節(jié)點(diǎn)受影響西潘。

  3. ShardedJedis支持keyTagPattern模式卷玉,即抽取key的一部分keyTag做sharding,這樣通過合理命名key秸架,可以將一組相關(guān)聯(lián)的key放入同一個(gè)Redis節(jié)點(diǎn)揍庄,這在避免跨節(jié)點(diǎn)訪問相關(guān)數(shù)據(jù)時(shí)很重要。

Sharding

  • redis服務(wù)器節(jié)點(diǎn)劃分:將每臺(tái)服務(wù)器節(jié)點(diǎn)采用hash算法劃分為160個(gè)虛擬節(jié)點(diǎn)(可以配置劃分權(quán)重)
  • 將劃分虛擬節(jié)點(diǎn)采用TreeMap存儲(chǔ)
  • 對(duì)每個(gè)redis服務(wù)器的物理連接采用LinkedHashMap存儲(chǔ)
  • 對(duì)Key or KeyTag 采用同樣的hash算法东抹,然后從TreeMap獲取大于等于鍵hash值得節(jié)點(diǎn)蚂子,取最鄰近節(jié)點(diǎn)存儲(chǔ);當(dāng)key的hash值大于虛擬節(jié)點(diǎn)hash值得最大值時(shí)缭黔,存入第一個(gè)虛擬節(jié)點(diǎn)
  • sharded采用的hash算法:MD5 和 MurmurHash兩種食茎;默認(rèn)采用64位的MurmurHash算法

擴(kuò)容問題

當(dāng)想要增加Redis節(jié)點(diǎn)時(shí),盡管采用一致性哈希馏谨,畢竟還是會(huì)有key匹配不到而丟失别渔,這時(shí)需要鍵值遷移。

作為輕量級(jí)客戶端sharding惧互,處理Redis鍵值遷移是不現(xiàn)實(shí)的哎媚,這就要求應(yīng)用層面允許Redis中數(shù)據(jù)丟失或從后端數(shù)據(jù)庫重新加載數(shù)據(jù)。

但有些時(shí)候喊儡,擊穿緩存層拨与,直接訪問數(shù)據(jù)庫層,會(huì)對(duì)系統(tǒng)訪問造成很大壓力艾猜。有沒有其它手段改善這種情況买喧?

preshardin方案:預(yù)先分配好足夠的分片,擴(kuò)容時(shí)只是將屬于某一分片的原Redis實(shí)例替換成新的容量更大的Redis實(shí)例匆赃。

即預(yù)先根據(jù)系統(tǒng)規(guī)模盡量部署好多個(gè)Redis實(shí)例淤毛,這些實(shí)例占用系統(tǒng)資源很小,一臺(tái)物理機(jī)可部署多個(gè)算柳,讓他們都參與sharding低淡,當(dāng)需要擴(kuò)容時(shí),選中一個(gè)實(shí)例作為主節(jié)點(diǎn)埠居,新加入的Redis節(jié)點(diǎn)作為從節(jié)點(diǎn)進(jìn)行數(shù)據(jù)復(fù)制查牌。數(shù)據(jù)同步后,修改sharding配置滥壕,讓指向原實(shí)例的Shard指向新機(jī)器上擴(kuò)容后的Redis節(jié)點(diǎn)纸颜,同時(shí)調(diào)整新Redis節(jié)點(diǎn)為主節(jié)點(diǎn),原實(shí)例可不再使用绎橘。

presharding是預(yù)先分配好足夠的分片胁孙,擴(kuò)容時(shí)只是將屬于某一分片的原Redis實(shí)例替換成新的容量更大的Redis實(shí)例唠倦。參與sharding的分片沒有改變,所以也就不存在key值從一個(gè)區(qū)轉(zhuǎn)移到另一個(gè)分片區(qū)的現(xiàn)象涮较,只是將屬于同分片區(qū)的鍵值從原Redis實(shí)例同步到新Redis實(shí)例稠鼻。

并不是只有增刪Redis節(jié)點(diǎn)引起鍵值丟失問題,更大的障礙來自Redis節(jié)點(diǎn)突然宕機(jī)狂票。在《Redis持久化》一文中已提到候齿,為不影響Redis性能,盡量不開啟AOF和RDB文件保存功能闺属,可架構(gòu)Redis主備模式慌盯,主Redis宕機(jī),數(shù)據(jù)不會(huì)丟失掂器,備Redis留有備份亚皂。

這樣,我們的架構(gòu)模式變成一個(gè)Redis節(jié)點(diǎn)切片包含一個(gè)主Redis和一個(gè)備Redis国瓮。在主Redis宕機(jī)時(shí)灭必,備Redis接管過來,上升為主Redis乃摹,繼續(xù)提供服務(wù)禁漓。主備共同組成一個(gè)Redis節(jié)點(diǎn),通過自動(dòng)故障轉(zhuǎn)移孵睬,保證了節(jié)點(diǎn)的高可用性璃饱。則Sharding架構(gòu)演變成:

Redis Sentinel提供了主備模式下Redis監(jiān)控、故障轉(zhuǎn)移功能達(dá)到系統(tǒng)的高可用性肪康。

高訪問量下,即使采用Sharding分片撩穿,一個(gè)單獨(dú)節(jié)點(diǎn)還是承擔(dān)了很大的訪問壓力磷支,這時(shí)我們還需要進(jìn)一步分解。通常情況下食寡,應(yīng)用訪問Redis讀操作量和寫操作量差異很大雾狈,讀常常是寫的數(shù)倍,這時(shí)我們可以將讀寫分離抵皱,而且讀提供更多的實(shí)例數(shù)善榛。

可以利用主從模式實(shí)現(xiàn)讀寫分離,主負(fù)責(zé)寫呻畸,從負(fù)責(zé)只讀移盆,同時(shí)一主掛多個(gè)從。在Sentinel監(jiān)控下伤为,還可以保障節(jié)點(diǎn)故障的自動(dòng)監(jiān)測(cè)咒循。

3.利用代理中間件實(shí)現(xiàn)大規(guī)模Redis集群

上面分別介紹了多Redis服務(wù)器集群的兩種方式,它們是基于客戶端sharding的Redis Sharding和基于服務(wù)端sharding的Redis Cluster。
客戶端sharding技術(shù)其優(yōu)勢(shì)在于服務(wù)端的Redis實(shí)例彼此獨(dú)立叙甸,相互無關(guān)聯(lián)颖医,每個(gè)Redis實(shí)例像單服務(wù)器一樣運(yùn)行,非常容易線性擴(kuò)展裆蒸,系統(tǒng)的靈活性很強(qiáng)熔萧。其不足之處在于:
由于sharding處理放到客戶端,規(guī)模進(jìn)步擴(kuò)大時(shí)給運(yùn)維帶來挑戰(zhàn)僚祷。
服務(wù)端Redis實(shí)例群拓?fù)浣Y(jié)構(gòu)有變化時(shí)佛致,每個(gè)客戶端都需要更新調(diào)整。
連接不能共享久妆,當(dāng)應(yīng)用規(guī)模增大時(shí)晌杰,資源浪費(fèi)制約優(yōu)化。

服務(wù)端sharding的Redis Cluster其優(yōu)勢(shì)在于服務(wù)端Redis集群拓?fù)浣Y(jié)構(gòu)變化時(shí)筷弦,客戶端不需要感知肋演,客戶端像使用單Redis服務(wù)器一樣使用Redis集群,運(yùn)維管理也比較方便烂琴。
不過Redis Cluster正式版推出時(shí)間不長爹殊,系統(tǒng)穩(wěn)定性、性能等都需要時(shí)間檢驗(yàn)奸绷,尤其在大規(guī)模使用場(chǎng)合梗夸。

能不能結(jié)合二者優(yōu)勢(shì)?即能使服務(wù)端各實(shí)例彼此獨(dú)立号醉,支持線性可伸縮反症,同時(shí)sharding又能集中處理,方便統(tǒng)一管理畔派?

本篇介紹的Redis代理中間件twemproxy就是這樣一種利用中間件做sharding的技術(shù)铅碍。類似的還有codis。

twemproxy處于客戶端和服務(wù)器的中間线椰,將客戶端發(fā)來的請(qǐng)求胞谈,進(jìn)行一定的處理后(如sharding),再轉(zhuǎn)發(fā)給后端真正的Redis服務(wù)器憨愉。也就是說烦绳,客戶端不直接訪問Redis服務(wù)器,而是通過twemproxy代理中間件間接訪問配紫。
參照Redis Sharding架構(gòu)径密,增加代理中間件的Redis集群架構(gòu)如下:
twemproxy中間件的內(nèi)部處理是無狀態(tài)的,它本身可以很輕松地集群笨蚁,這樣可避免單點(diǎn)壓力或故障睹晒。
twemproxy又叫nutcracker趟庄,起源于twitter系統(tǒng)中redis/memcached集群開發(fā)實(shí)踐,運(yùn)行效果良好伪很,后代碼奉獻(xiàn)給開源社區(qū)戚啥。其輕量高效,采用C語言開發(fā)锉试,工程網(wǎng)址是:GitHub - twitter/twemproxy: A fast, light-weight proxy for memcached and redis**
twemproxy后端不僅支持redis猫十,同時(shí)也支持memcached,這是twitter系統(tǒng)具體環(huán)境造成的呆盖。
由于使用了中間件拖云,twemproxy可以通過共享與后端系統(tǒng)的連接,降低客戶端直接連接后端服務(wù)器的連接數(shù)量应又。同時(shí)宙项,它也提供sharding功能,支持后端服務(wù)器集群水平擴(kuò)展株扛。統(tǒng)一運(yùn)維管理也帶來了方便尤筐。
當(dāng)然,也是由于使用了中間件代理洞就,相比客戶端直連服務(wù)器方式盆繁,性能上會(huì)有所損耗,實(shí)測(cè)結(jié)果大約降低了20%左右旬蟋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末油昂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子倾贰,更是在濱河造成了極大的恐慌冕碟,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匆浙,死亡現(xiàn)場(chǎng)離奇詭異鸣哀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吞彤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叹放,“玉大人饰恕,你說我怎么就攤上這事【觯” “怎么了埋嵌?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長俱恶。 經(jīng)常有香客問我雹嗦,道長范舀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任了罪,我火速辦了婚禮锭环,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泊藕。我一直安慰自己辅辩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布娃圆。 她就那樣靜靜地躺著玫锋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪讼呢。 梳的紋絲不亂的頭發(fā)上撩鹿,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音悦屏,去河邊找鬼节沦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛窜管,可吹牛的內(nèi)容都是我干的散劫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼幕帆,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼获搏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起失乾,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤常熙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后碱茁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裸卫,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年纽竣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了墓贿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜓氨,死狀恐怖聋袋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情穴吹,我是刑警寧澤幽勒,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站港令,受9級(jí)特大地震影響啥容,放射性物質(zhì)發(fā)生泄漏锈颗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一咪惠、第九天 我趴在偏房一處隱蔽的房頂上張望击吱。 院中可真熱鬧,春花似錦硝逢、人聲如沸姨拥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叫乌。三九已至,卻和暖如春徽缚,著一層夾襖步出監(jiān)牢的瞬間憨奸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工凿试, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留排宰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓那婉,卻偏偏與公主長得像板甘,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子详炬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容