redis
redis是單線程的馅而,但是一般的作為緩存使用的話祥诽,redis足夠了,因?yàn)樗淖x寫速度太快了瓮恭。
官方的一個(gè)簡單測試:
測試完成了50個(gè)并發(fā)執(zhí)行100000個(gè)請求雄坪。
設(shè)置和獲取的值是一個(gè)256字節(jié)字符串。
結(jié)果:讀的速度是110000次/s,寫的速度是81000次/s
但對于訪問量特別大的服務(wù)來說屯蹦,還是稍有不足维哈。那么,如何提升redis的性能呢登澜?搭建集群阔挠。
redis主要提供三種集群策略:
- 主從復(fù)制
- 集群
- 哨兵
一、主從復(fù)制
在主從復(fù)制中脑蠕,數(shù)據(jù)庫分為倆類购撼,主數(shù)據(jù)庫(master)和從數(shù)據(jù)庫(slave)。
1.1 主從復(fù)制有如下特點(diǎn):
- 主數(shù)據(jù)庫可以進(jìn)行讀寫操作谴仙,當(dāng)讀寫操作導(dǎo)致數(shù)據(jù)變化時(shí)會自動將數(shù)據(jù)同步給從數(shù)據(jù)庫
- 從數(shù)據(jù)庫一般都是只讀的份招,并且接收主數(shù)據(jù)庫同步過來的數(shù)據(jù)
- 一個(gè)master可以擁有多個(gè)slave,但是一個(gè)slave只能對應(yīng)一個(gè)master
1.2 工作機(jī)制
- slave從節(jié)點(diǎn)服務(wù)啟動并連接到Master之后狞甚,它將主動發(fā)送一個(gè)SYNC命令锁摔。Master服務(wù)主節(jié)點(diǎn)收到同步命令后將啟動后臺存盤進(jìn)程,同時(shí)收集所有接收到的用于修改數(shù)據(jù)集的命令哼审,在后臺進(jìn)程執(zhí)行完畢后谐腰,Master將傳送整個(gè)數(shù)據(jù)庫文件到Slave孕豹,以完成一次完全同步。而Slave從節(jié)點(diǎn)服務(wù)在接收到數(shù)據(jù)庫文件數(shù)據(jù)之后將其存盤并加載到內(nèi)存中十气。此后励背,Master主節(jié)點(diǎn)繼續(xù)將所有已經(jīng)收集到的修改命令,和新的修改命令依次傳送給Slaves砸西,Slave將在本次執(zhí)行這些數(shù)據(jù)修改命令叶眉,從而達(dá)到最終的數(shù)據(jù)同步。
- 復(fù)制初始化后芹枷,master每次接收到的寫命令都會同步發(fā)送給slave衅疙,保證主從數(shù)據(jù)一致性。
- 如果Master和Slave之間的鏈接出現(xiàn)斷連現(xiàn)象鸳慈,Slave可以自動重連Master饱溢,但是在連接成功之后,一次完全同步將被自動執(zhí)行走芋。
1.3 主從配置
redis默認(rèn)是主數(shù)據(jù)绩郎,所以master無需配置,我們只需要修改slave的配置即可翁逞。
設(shè)置需要連接的master的ip端口:
slaveof 192.168.0.107 6379
如果master設(shè)置了密碼肋杖。需要配置:
masterauth master-password
連接成功進(jìn)入命令行后,可以通過以下命令行查看連接該數(shù)據(jù)庫的其他庫信息:
info replication
1.3 優(yōu)點(diǎn)
- 同一個(gè)Master可以同步多個(gè)Slaves挖函。
- Slave同樣可以接受其它Slaves的連接和同步請求兽愤,這樣可以有效的分載Master的同步壓力。因此我們可以將Redis的Replication架構(gòu)視為圖結(jié)構(gòu)挪圾。
- Master Server是以非阻塞的方式為Slaves提供服務(wù)浅萧。所以在Master-Slave同步期間,客戶端仍然可以提交查詢或修改請求哲思。
- Slave Server同樣是以非阻塞的方式完成數(shù)據(jù)同步洼畅。在同步期間,如果有客戶端提交查詢請求棚赔,Redis則返回同步之前的數(shù)據(jù)
- 為了分載Master的讀操作壓力帝簇,Slave服務(wù)器可以為客戶端提供只讀操作的服務(wù),寫服務(wù)仍然必須由Master來完成靠益。即便如此丧肴,系統(tǒng)的伸縮性還是得到了很大的提高。
- Master可以將數(shù)據(jù)保存操作交給Slaves完成胧后,從而避免了在Master中要有獨(dú)立的進(jìn)程來完成此操作芋浮。
- 支持主從復(fù)制,主機(jī)會自動將數(shù)據(jù)同步到從機(jī)壳快,可以進(jìn)行讀寫分離纸巷。
1.4 缺點(diǎn)
- Redis不具備自動容錯(cuò)和恢復(fù)功能镇草,主機(jī)從機(jī)的宕機(jī)都會導(dǎo)致前端部分讀寫請求失敗,需要等待機(jī)器重啟或者手動切換前端的IP才能恢復(fù)瘤旨。
- 主機(jī)宕機(jī)梯啤,宕機(jī)前有部分?jǐn)?shù)據(jù)未能及時(shí)同步到從機(jī),切換IP后還會引入數(shù)據(jù)不一致的問題存哲,降低了系統(tǒng)的可用性因宇。
- Redis的主從復(fù)制采用全量復(fù)制,復(fù)制過程中主機(jī)會fork出一個(gè)子進(jìn)程對內(nèi)存做一份快照祟偷,并將子進(jìn)程的內(nèi)存快照保存為文件發(fā)送給從機(jī)察滑,這一過程需要確保主機(jī)有足夠多的空余內(nèi)存。若快照文件較大肩袍,對集群的服務(wù)能力會產(chǎn)生較大的影響,而且復(fù)制過程是在從機(jī)新加入集群或者從機(jī)和主機(jī)網(wǎng)絡(luò)斷開重連時(shí)都會進(jìn)行婚惫,也就是網(wǎng)絡(luò)波動都會造成主機(jī)和從機(jī)間的一次全量的數(shù)據(jù)復(fù)制氛赐,這對實(shí)際的系統(tǒng)運(yùn)營造成了不小的麻煩。
- Redis較難支持在線擴(kuò)容先舷,在集群容量達(dá)到上限時(shí)在線擴(kuò)容會變得很復(fù)雜艰管。為避免這一問題,運(yùn)維人員在系統(tǒng)上線時(shí)必須確保有足夠的空間蒋川,這對資源造成了很大的浪費(fèi)牲芋。
- 其實(shí)redis的主從模式很簡單,在實(shí)際的生產(chǎn)環(huán)境中是很少使用的捺球,我也不建議在實(shí)際的生產(chǎn)環(huán)境中使用主從模式來提供系統(tǒng)的高可用性缸浦,之所以不建議使用都是由它的缺點(diǎn)造成的,在數(shù)據(jù)量非常大的情況氮兵,或者對系統(tǒng)的高可用性要求很高的情況下裂逐,主從模式也是不穩(wěn)定的。
二泣栈、哨兵
該模式是從Redis的2.6版本開始提供的卜高,但是當(dāng)時(shí)這個(gè)版本的模式是不穩(wěn)定的,直到Redis的2.8版本以后南片,這個(gè)哨兵模式才穩(wěn)定下來掺涛,無論是主從模式,還是哨兵模式疼进,這兩個(gè)模式都有一個(gè)問題薪缆,不能水平擴(kuò)容,并且這兩個(gè)模式的高可用特性都會受到Master主節(jié)點(diǎn)內(nèi)存的限制伞广。
2.1 哨兵的作用是監(jiān)控 redis系統(tǒng)的運(yùn)行狀況矮燎,功能如下
- 監(jiān)控主從數(shù)據(jù)庫是否正常運(yùn)行定血。
- master出現(xiàn)故障時(shí),自動將它的其中一個(gè)slave轉(zhuǎn)化為master诞外。
- master和slave服務(wù)器切換后澜沟,master的redis.conf、slave的redis.conf和sentinel.conf的配置文件的內(nèi)容都會發(fā)生相應(yīng)的改變峡谊,即茫虽,saster主服務(wù)器的redis.conf配置文件中會多一行slaveof的配置,sentinel.conf的監(jiān)控目標(biāo)會隨之調(diào)換既们。
- 當(dāng)被監(jiān)控的某個(gè)Redis節(jié)點(diǎn)出現(xiàn)問題時(shí), 哨兵(sentinel) 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知濒析。
- 多哨兵配置的時(shí)候,哨兵之間也會自動監(jiān)控啥纸。
- 多個(gè)哨兵可以監(jiān)控同一個(gè)redis号杏。
2.2 哨兵工作機(jī)制
- 哨兵進(jìn)程啟動時(shí)會讀取配置文件的內(nèi)容,通過
sentinel monitor master-name ip port quorum
查找到master的ip端口斯棒。一個(gè)哨兵可以監(jiān)控多個(gè)master數(shù)據(jù)庫盾致,只需要提供多個(gè)該配置項(xiàng)即可。 - 配置文件還定義了與監(jiān)控相關(guān)的參數(shù)荣暮,比如master多長時(shí)間無響應(yīng)即即判定位為下線庭惜。
- 哨兵啟動后,會與要監(jiān)控的master建立倆條連接:
3.1 一條連接用來訂閱master的_sentinel_:hello頻道穗酥,并獲取其他監(jiān)控該master的哨兵節(jié)點(diǎn)信息
3.2 另一條連接定期向master發(fā)送INFO等命令獲取master本身的信息 - 與master建立連接后护赊,哨兵會執(zhí)行三個(gè)操作,這三個(gè)操作的發(fā)送頻率都可以在配置文件中配置:
4.1 定期向master和slave發(fā)送INFO命令
4.2 定期向master和slave的_sentinel_:hello頻道發(fā)送自己的信息
4.3 定期向master砾跃、slave和其他哨兵發(fā)送PING命令
這三個(gè)操作的意義非常重大骏啰,發(fā)送INFO命令可以獲取當(dāng)前數(shù)據(jù)庫的相關(guān)信息從而實(shí)現(xiàn)新節(jié)點(diǎn)的自動發(fā)現(xiàn)。所以說哨兵只需要配置master數(shù)據(jù)庫信息就可以自動發(fā)現(xiàn)其slave信息抽高。獲取到slave信息后器一,哨兵也會與slave建立倆條連接執(zhí)行監(jiān)控。通過INFO命令厨内,哨兵可以獲取主從數(shù)據(jù)庫的最新信息祈秕,并進(jìn)行相應(yīng)的操作,比如角色變更等雏胃。 - 接下來哨兵向主從數(shù)據(jù)庫的_sentinel_:hello頻道發(fā)送信息请毛,并與同樣監(jiān)控這些數(shù)據(jù)庫的哨兵共享自己的信息,發(fā)送內(nèi)容為哨兵的ip端口瞭亮、運(yùn)行id方仿、配置版本、master名字、master的ip端口還有master的配置版本仙蚜。這些信息有以下用處:
5.1 其他哨兵可以通過該信息判斷發(fā)送者是否是新發(fā)現(xiàn)的哨兵此洲,如果是的話會創(chuàng)建一個(gè)到該哨兵的連接用于發(fā)送ping命令。
5.2 其他哨兵通過該信息可以判斷master的版本委粉,如果該版本高于直接記錄的版本呜师,將會更新 - 當(dāng)實(shí)現(xiàn)了自動發(fā)現(xiàn)slave和其他哨兵節(jié)點(diǎn)后,哨兵就可以通過定期發(fā)送ping命令定時(shí)監(jiān)控這些數(shù)據(jù)庫和節(jié)點(diǎn)有沒有停止服務(wù)贾节。發(fā)送頻率可以配置汁汗,但是最長間隔時(shí)間為1s,可以通過
sentinel down-after-milliseconds mymaster 600
設(shè)置栗涂。 - 如果被ping的數(shù)據(jù)庫或者節(jié)點(diǎn)超時(shí)未回復(fù)知牌,哨兵認(rèn)為其主觀下線。如果下線的是master斤程,哨兵會向其他哨兵點(diǎn)發(fā)送命令詢問他們是否也認(rèn)為該master主觀下線角寸。如果一個(gè)master主服務(wù)器被標(biāo)記為主觀下線(SDOWN),則正在監(jiān)視這個(gè)Master主服務(wù)器的所有 Sentinel(哨兵)進(jìn)程要以每秒一次的頻率確認(rèn)Master主服務(wù)器的確進(jìn)入了主觀下線狀態(tài)忿墅。如果達(dá)到一定數(shù)目(即配置文件中的quorum)投票扁藕,哨兵會認(rèn)為該master已經(jīng)客觀下線(ODOWN),并選舉領(lǐng)頭的哨兵節(jié)點(diǎn)對主從系統(tǒng)發(fā)起故障恢復(fù)球匕。
- 如上文所說纹磺,哨兵認(rèn)為master客觀下線后帖烘,故障恢復(fù)的操作需要由選舉的領(lǐng)頭哨兵執(zhí)行亮曹,選舉采用Raft算法:
8.1 發(fā)現(xiàn)master下線的哨兵節(jié)點(diǎn)(我們稱他為A)向每個(gè)哨兵發(fā)送命令,要求對方選自己為領(lǐng)頭哨兵
8.2 如果目標(biāo)哨兵節(jié)點(diǎn)沒有選過其他人秘症,則會同意選舉A為領(lǐng)頭哨兵
8.3 如果有超過一半的哨兵同意選舉A為領(lǐng)頭照卦,則A當(dāng)選
8.4 如果有多個(gè)哨兵節(jié)點(diǎn)同時(shí)參選領(lǐng)頭,此時(shí)有可能存在一輪投票無競選者勝出乡摹,此時(shí)每個(gè)參選的節(jié)點(diǎn)等待一個(gè)隨機(jī)時(shí)間后再次發(fā)起參選請求役耕,進(jìn)行下一輪投票精選,直至選舉出領(lǐng)頭哨兵
8.5 選出領(lǐng)頭哨兵后聪廉,領(lǐng)頭者開始對進(jìn)行故障恢復(fù)瞬痘,從出現(xiàn)故障的master的從數(shù)據(jù)庫slave中挑選一個(gè)來當(dāng)選新的master,選擇規(guī)則如下:
8.5.1 所有在線的slave中選擇優(yōu)先級最高的,優(yōu)先級可以通過slave-priority配置
8.5.2 如果有多個(gè)最高優(yōu)先級的slave板熊,則選取復(fù)制偏移量最大(即復(fù)制越完整)的當(dāng)選
8.5.3 如果以上條件都一樣框全,選取id最小的slave - 挑選出需要繼任的slaver后,領(lǐng)頭哨兵向該數(shù)據(jù)庫發(fā)送命令使其升格為master干签,然后再向其他slave發(fā)送命令接受新的master津辩,最后更新數(shù)據(jù)。將已經(jīng)停止的舊的master更新為新的master的從數(shù)據(jù)庫,使其恢復(fù)服務(wù)后以slave的身份繼續(xù)運(yùn)行喘沿。
2.3 哨兵配置
哨兵配置的配置文件為sentinel.conf闸度,設(shè)置主機(jī)名稱,地址蚜印,端口莺禁,以及選舉票數(shù)即恢復(fù)時(shí)最少需要幾個(gè)哨兵節(jié)點(diǎn)同意。只要配置需要監(jiān)控的master就可以了晒哄,哨兵會監(jiān)控連接該master的slave睁宰。
sentinel monitor mymaster 192.168.0.107 6379 1
啟動哨兵節(jié)點(diǎn):
redis-server sentinel.conf --sentinel &
出現(xiàn)以下類似信息即啟動哨兵成功
3072:X 12 Apr 22:40:02.554 # Sentinel runid is e510bd95d4deba3261de72272130322b2ba650e7
3072:X 12 Apr 22:40:02.554 # +monitor master mymaster 192.168.0.107 6379 quorum 1
3072:X 12 Apr 22:40:03.516 * +slave slave 192.168.0.108:6379 192.168.0.108 6379 @ mymaster 192.168.0.107 6379
3072:X 12 Apr 22:40:03.516 * +slave slave 192.168.0.109:6379 192.168.0.109 6379 @ mymaster 192.168.0.107 6379
可以在任何一臺服務(wù)器上查看指定哨兵節(jié)點(diǎn)信息:
bin/redis-cli -h 192.168.0.110 -p 26379 info Sentinel
控制臺輸出哨兵信息
redis-cli -h 192.168.0.110 -p 26379 info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=192.168.0.107:6379,slaves=2,sentinels=1
三、集群
3.1 特點(diǎn)
3.0版本之前的redis是不支持集群的寝凌,我們的徐子睿老師說柒傻,那個(gè)時(shí)候,我們的redis如果想要集群的話较木,就需要一個(gè)中間件红符,然后這個(gè)中間件負(fù)責(zé)將我們需要存入redis中的數(shù)據(jù)的key通過一套算法計(jì)算得出一個(gè)值。然后根據(jù)這個(gè)值找到對應(yīng)的redis節(jié)點(diǎn)伐债,將這些數(shù)據(jù)存在這個(gè)redis的節(jié)點(diǎn)中预侯。在取值的時(shí)候,同樣先將key進(jìn)行計(jì)算峰锁,得到對應(yīng)的值萎馅,然后就去找對應(yīng)的redis節(jié)點(diǎn),從對應(yīng)的節(jié)點(diǎn)中取出對應(yīng)的值虹蒋。這樣做有很多不好的地方糜芳,比如說我們的這些計(jì)算都需要在系統(tǒng)中去進(jìn)行,所以會增加系統(tǒng)的負(fù)擔(dān)魄衅。還有就是這種集群模式下峭竣,某個(gè)節(jié)點(diǎn)掛掉,其他的節(jié)點(diǎn)無法知道晃虫。而且也不容易對每個(gè)節(jié)點(diǎn)進(jìn)行負(fù)載均衡皆撩。
從redis 3.0版本開始支持redis-cluster集群,redis-cluster采用無中心結(jié)構(gòu)哲银,每一個(gè)節(jié)點(diǎn)都保存有這個(gè)集群所有主節(jié)點(diǎn)以及從節(jié)點(diǎn)的信息扛吞,及集群狀態(tài),每個(gè)節(jié)點(diǎn)都和其他節(jié)點(diǎn)連接荆责。所以redis-cluster是一種服務(wù)端分片技術(shù)滥比。
- 每個(gè)節(jié)點(diǎn)都和n-1個(gè)節(jié)點(diǎn)通信,這被稱為集群總線(cluster bus)草巡。它們使用特殊的端口號守呜,即對外服務(wù)端口號加10000型酥。所以要維護(hù)好這個(gè)集群的每個(gè)節(jié)點(diǎn)信息,不然會導(dǎo)致整個(gè)集群不可用查乒,其內(nèi)部采用特殊的二進(jìn)制協(xié)議優(yōu)化傳輸速度和帶寬弥喉。
- redis-cluster把所有的物理節(jié)點(diǎn)映射到[0,16383]slot(槽)上,cluster負(fù)責(zé)維護(hù)node--slot--value玛迄。
- 集群預(yù)先給所有節(jié)點(diǎn)分好16384個(gè)桶由境,每個(gè)節(jié)點(diǎn)得到部分桶,當(dāng)需要在redis集群中插入數(shù)據(jù)時(shí)蓖议,根據(jù)CRC16(KEY) mod 16384的值虏杰,決定將一個(gè)key放到哪個(gè)桶中。
- 客戶端與redis節(jié)點(diǎn)直連勒虾,不需要連接集群所有的節(jié)點(diǎn)纺阔,連接集群中任何一個(gè)可用節(jié)點(diǎn)即可。整個(gè)cluster被看做是一個(gè)整體修然,客戶端可連接任意一個(gè)節(jié)點(diǎn)進(jìn)行操作笛钝,當(dāng)客戶端操作的key沒有分配在該節(jié)點(diǎn)上時(shí),redis會返回轉(zhuǎn)向指令愕宋,指向正確的節(jié)點(diǎn)玻靡。
- redis-trib.rb腳本(rub語言)為集群的管理工具,比如自動添加節(jié)點(diǎn)中贝,規(guī)劃槽位囤捻,遷移數(shù)據(jù)等一系列操作。
- 節(jié)點(diǎn)的fail是通過集群中超過半數(shù)的節(jié)點(diǎn)檢測失效時(shí)才生效邻寿。集群節(jié)點(diǎn)之間通過互相的ping-pong判斷是否可以連接上蝎土。如果有一半以上的節(jié)點(diǎn)去ping一個(gè)節(jié)點(diǎn)的時(shí)候沒有回應(yīng),集群就認(rèn)為這個(gè)節(jié)點(diǎn)宕機(jī)了老厌,然后去連接它的備用節(jié)點(diǎn)瘟则。如果某個(gè)節(jié)點(diǎn)和所有從節(jié)點(diǎn)全部掛掉黎炉,集群就進(jìn)入fail狀態(tài)枝秤,也可以理解成集群的slot映射[0-16383]不完整時(shí)進(jìn)入fail狀態(tài)。如果有一半以上的主節(jié)點(diǎn)宕機(jī)慷嗜,那么無論這些節(jié)點(diǎn)有沒有從節(jié)點(diǎn)淀弹,集群同樣進(jìn)入fail狀態(tài)。這就是redis的投票機(jī)制庆械。
- 為了增加集群的可訪問性薇溃,官方推薦的方案是將node配置成主從結(jié)構(gòu),即一個(gè)master主節(jié)點(diǎn)缭乘,掛n個(gè)slave從節(jié)點(diǎn)沐序。如果主節(jié)點(diǎn)失效,redis cluster會根據(jù)選舉算法從slave節(jié)點(diǎn)中選擇一個(gè)上升為master節(jié)點(diǎn),整個(gè)集群繼續(xù)對外提供服務(wù)策幼。
3.2 配置
- redis集群依賴ruby邑时,需安裝ruby環(huán)境,ruby版本需高于2.2
yum install ruby
yum install rubygems
gem install redis
- 修改配置文件
bind 192.168.0.107
# 配置端口
port 6380
# 配置快照保存路徑特姐,6個(gè)節(jié)點(diǎn)配置不同路徑
dir /usr/local/redis-cluster/6380/
# 開啟集群
cluster-enabled yes
# 為節(jié)點(diǎn)設(shè)置不同的工作目錄晶丘,6個(gè)節(jié)點(diǎn)配置不同目錄
cluster-config-file nodes-6380.conf
# 集群失效時(shí)間
cluster-node-timeout 15000
- 開啟集群中的所有節(jié)點(diǎn)
redis-service …/6380/redis.conf
redis-service …/6381/redis.conf
redis-service …/6382/redis.conf
redis-service …/6383/redis.conf
redis-service …/6384/redis.conf
redis-service …/6385/redis.conf
- 將節(jié)點(diǎn)加入集群中,中途需要輸入yes確定創(chuàng)建集群
redis-trib.rb create --replicas 1 192.168.0.107:6380 192.168.0.107:6381 192.168.0.107:6382 192.168.0.107:6383 192.168.0.107:6384 192.168.0.107:6385
- 進(jìn)入集群中任何一個(gè)節(jié)點(diǎn)
redis-cli -c -h 192.168.0.107 -p 6381
- 查看集群中的節(jié)點(diǎn)
cluster nodes
[root@buke107 src]# redis-cli -c -h 192.168.0.107 -p 6381
192.168.0.107:6381> cluster nodes
868456121fa4e6c8e7abe235a88b51d354a944b5 192.168.0.107:6382 master - 0 1523609792598 3 connected 10923-16383
d6d01fd8f1e5b9f8fc0c748e08248a358da3638d 192.168.0.107:6385 slave 868456121fa4e6c8e7abe235a88b51d354a944b5 0 1523609795616 6 connected
5cd3ed3a84ead41a765abd3781b98950d452c958 192.168.0.107:6380 master - 0 1523609794610 1 connected 0-5460
b8e047aeacb9398c3f58f96d0602efbbea2078e2 192.168.0.107:6383 slave 5cd3ed3a84ead41a765abd3781b98950d452c958 0 1523609797629 1 connected
68cf66359318b26df16ebf95ba0c00d9f6b2c63e 192.168.0.107:6384 slave 90b4b326d579f9b5e181e3df95578bceba29b204 0 1523609796622 5 connected
90b4b326d579f9b5e181e3df95578bceba29b204 192.168.0.107:6381 myself,master - 0 0 2 connected 5461-10922
如上所示唐含,三主三從節(jié)點(diǎn)已創(chuàng)建成功
- 增加集群節(jié)點(diǎn)
cluster meet ip port
其他集群實(shí)現(xiàn)方式
中間件
一浅浮、twemproxy
- twemproxy又稱nutcracker,起源于推特系統(tǒng)中redis捷枯、memcached集群的輕量級代理滚秩。
- Redis代理中間件twemproxy是一種利用中間件做分片的技術(shù)。twemproxy處于客戶端和服務(wù)器的中間淮捆,將客戶端發(fā)來的請求叔遂,進(jìn)行一定的處理后(sharding),再轉(zhuǎn)發(fā)給后端真正的redis服務(wù)器争剿。也就是說已艰,客戶端不直接訪問redis服務(wù)器,而是通過twemproxy代理中間件間接訪問蚕苇。降低了客戶端直連后端服務(wù)器的連接數(shù)量哩掺,并且支持服務(wù)器集群水平擴(kuò)展。
- twemproxy中間件的內(nèi)部處理是無狀態(tài)的涩笤,它本身可以很輕松地集群嚼吞,這樣可以避免單點(diǎn)壓力或故障。
- 從下面架構(gòu)圖看到twemproxy是一個(gè)單點(diǎn)蹬碧,很容易對其造成很大的壓力舱禽,所以通常會結(jié)合keepalived來實(shí)現(xiàn)twemproy的高可用。這時(shí)恩沽,通常只有一臺twemproxy在工作誊稚,另外一臺處于備機(jī),當(dāng)一臺掛掉以后罗心,vip自動漂移里伯,備機(jī)接替工作。關(guān)于keepalived的用法可自行網(wǎng)上查閱資料渤闷。
二疾瓮、codis
codis是一個(gè)分布式的Redis解決方案,由豌豆莢開源飒箭,對于上層的應(yīng)用來說狼电,連接codis proxy和連接原生的redis server沒什么明顯的區(qū)別蜒灰,上層應(yīng)用可以像使用單機(jī)的redis一樣使用,codis底層會處理請求的轉(zhuǎn)發(fā)肩碟,不停機(jī)的數(shù)據(jù)遷移等工作卷员,所有后邊的事情,對于前面的客戶端來說是透明的腾务,可以簡單的認(rèn)為后邊連接的是一個(gè)內(nèi)存無限大的redis服務(wù)毕骡。
客戶端分片
分區(qū)的邏輯在客戶端實(shí)現(xiàn),由客戶端自己選擇請求到哪個(gè)節(jié)點(diǎn)岩瘦。方案可參考一致性哈希未巫,這種方案通常適用于用戶對客戶端的行為有完全控制能力的場景。
一启昧、Jedis sharding集群
Redis Sharding可以說是在Redis cluster出來之前業(yè)界普遍的采用方式叙凡,其主要思想是采用hash算法將存儲數(shù)據(jù)的key進(jìn)行hash散列,這樣特定的key會被定為到特定的節(jié)點(diǎn)上密末。
慶幸的是握爷,Java Redis客戶端驅(qū)動Jedis已支持Redis Sharding功能,即ShardedJedis以及結(jié)合緩存池的ShardedJedisPool
Jedis的Redis Sharding實(shí)現(xiàn)具有如下特點(diǎn):
- 采用一致性哈希算法严里,將key和節(jié)點(diǎn)name同時(shí)hashing新啼,然后進(jìn)行映射匹配,采用的算法是MURMUR_HASH刹碾。采用一致性哈希而不是采用簡單類似哈希求模映射的主要原因是當(dāng)增加或減少節(jié)點(diǎn)時(shí)燥撞,不會產(chǎn)生由于重新匹配造成的rehashing。一致性哈希只影響相鄰節(jié)點(diǎn)key分配迷帜,影響量小物舒。
- 為了避免一致性哈希只影響相鄰節(jié)點(diǎn)造成節(jié)點(diǎn)分配壓力,ShardedJedis會對每個(gè)Redis節(jié)點(diǎn)根據(jù)名字(沒有戏锹,Jedis會賦予缺省名字)會虛擬化出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)移動再分配更均勻伞插,而不是只有相鄰節(jié)點(diǎn)受影響割粮。
- ShardedJedis支持keyTagPattern模式盾碗,即抽取key的一部分keyTag做sharding媚污,這樣通過合理命名key,可以將一組相關(guān)聯(lián)的key放入同一個(gè)Redis節(jié)點(diǎn)廷雅,這在避免跨節(jié)點(diǎn)訪問相關(guān)數(shù)據(jù)時(shí)很重要耗美。
- 當(dāng)然京髓,Redis Sharding這種輕量靈活方式必然在集群其它能力方面做出妥協(xié)。比如擴(kuò)容商架,當(dāng)想要增加Redis節(jié)點(diǎn)時(shí)堰怨,盡管采用一致性哈希,畢竟還是會有key匹配不到而丟失蛇摸,這時(shí)需要鍵值遷移备图。
- 作為輕量級客戶端sharding,處理Redis鍵值遷移是不現(xiàn)實(shí)的赶袄,這就要求應(yīng)用層面允許Redis中數(shù)據(jù)丟失或從后端數(shù)據(jù)庫重新加載數(shù)據(jù)揽涮。但有些時(shí)候,擊穿緩存層饿肺,直接訪問數(shù)據(jù)庫層蒋困,會對系統(tǒng)訪問造成很大壓力。