1- 水平分區(qū) VS 垂直分區(qū)
分區(qū)是分割數(shù)據(jù)到多個(gè)Redis實(shí)例的處理過程,因此每個(gè)實(shí)例只保存key的一個(gè)子集。有兩種分區(qū)方式:水平分區(qū)、垂直分區(qū)癞己。
1.1 分區(qū)的優(yōu)勢(shì)與不足
- 優(yōu)勢(shì)
通過利用多臺(tái)計(jì)算機(jī)內(nèi)存的和值,允許我們構(gòu)造更大的數(shù)據(jù)庫瑞凑。
通過多核和多臺(tái)計(jì)算機(jī)末秃,允許我們擴(kuò)展計(jì)算能力;通過多臺(tái)計(jì)算機(jī)和網(wǎng)絡(luò)適配器籽御,允許我們擴(kuò)展網(wǎng)絡(luò)帶寬
- 不足
涉及多個(gè)key的操作通常是不被支持的:
- 當(dāng)兩個(gè)set映射到不同的redis實(shí)例上時(shí)练慕,你就不能對(duì)這兩個(gè)set執(zhí)行交集操作。
- 涉及多個(gè)key的redis事務(wù)不能使用技掏。
- 當(dāng)使用分區(qū)時(shí)铃将,數(shù)據(jù)處理較為復(fù)雜,比如你需要處理多個(gè)rdb/aof文件哑梳,并且從多個(gè)實(shí)例和主機(jī)備份持久化文件劲阎。
- 增加或刪除容量也比較復(fù)雜。redis集群大多數(shù)支持在運(yùn)行時(shí)增加鸠真、刪除節(jié)點(diǎn)的透明數(shù)據(jù)平衡的能力悯仙,但是類似于客戶端分區(qū)、代理等其他系統(tǒng)則不支持這項(xiàng)特性吠卷。
1.2 水平分區(qū)
水平分區(qū)是根據(jù)一些規(guī)則把同一業(yè)務(wù)單元的Key拆分到不同的Redis實(shí)例上锡垄。
- 按Range水平分區(qū)
最簡(jiǎn)單的分區(qū)方式是按范圍分區(qū),就是映射一定范圍的對(duì)象到特定的Redis實(shí)例
比如祭隔,ID從0到10000的用戶會(huì)保存到實(shí)例R0货岭,ID從10001到 20000的用戶會(huì)保存到R1,以此類推疾渴。這種方式是可行的千贯,并且在實(shí)際中使用,不足就是要有一個(gè)區(qū)間范圍到實(shí)例的映射表搞坝。這個(gè)表要被管理搔谴,同時(shí)還需要各種對(duì)象的映射表,通常對(duì)Redis來說并非是好的方法桩撮。優(yōu)點(diǎn):規(guī)則簡(jiǎn)單己沛、數(shù)據(jù)均衡性較好慌核、比較容易擴(kuò)展;缺點(diǎn):請(qǐng)求的負(fù)載不一定均衡申尼,一般來說,新注冊(cè)的用戶會(huì)比老用戶更活躍垫桂,大range的服務(wù)請(qǐng)求壓力會(huì)更大师幕。
- 對(duì)Key哈希水平切分
按照Key進(jìn)行Hash,支持任意類型的Key诬滩,然后對(duì)得到的Hash值進(jìn)行取模運(yùn)算霹粥,分配到不同Redis實(shí)例上。優(yōu)點(diǎn):規(guī)則簡(jiǎn)單疼鸟、數(shù)據(jù)均衡性較好后控、請(qǐng)求均勻性較好;缺點(diǎn)是:不容易擴(kuò)展空镜,擴(kuò)展一個(gè)數(shù)據(jù)服務(wù)浩淘,hash方法改變時(shí)候,可能需要進(jìn)行數(shù)據(jù)遷移吴攒。
1.3 垂直分區(qū)
垂直分區(qū)就是把一個(gè)Redis實(shí)例上的不同業(yè)務(wù)單元的Key拆分到不同的Redis實(shí)例上张抄。
2- 持久化
Redis持久化方案主要有RDB和AOF,兩者毫無關(guān)系洼怔,完全獨(dú)立運(yùn)行署惯。
2.1 RDB文件
RDB是整個(gè)內(nèi)存數(shù)據(jù)的壓縮過的某一時(shí)刻的Snapshot快照,可以配置復(fù)合的觸發(fā)RDB寫的條件镣隶,默認(rèn)是1分鐘內(nèi)改了1萬次极谊,或5分鐘內(nèi)改了10次,或15分鐘內(nèi)改了1次安岂。
RDB寫入時(shí)轻猖,會(huì)連內(nèi)存一起Fork出一個(gè)新進(jìn)程,遍歷新進(jìn)程內(nèi)存中的數(shù)據(jù)寫文件嗜闻,這樣就解決了些Snapshot過程中又有新的寫入請(qǐng)求進(jìn)來的問題蜕依。
RDB會(huì)先寫到臨時(shí)文件,完了再Rename琉雳,這樣外部程序?qū)DB文件的備份和傳輸過程是安全的样眠。而且即使寫新快照的過程中Server被強(qiáng)制關(guān)掉了,舊的RDB文件還在翠肘。
可配置是否進(jìn)行壓縮檐束,壓縮方法是字符串的LZF算法,以及將string形式的數(shù)字變回int形式存儲(chǔ)束倍。
停止RDB保存規(guī)則的方法:redis-cli config set save “”
2.2 AOF文件
操作日志被丧,記錄所有有效的寫操作盟戏,等于mysql的binlog,格式就是明文的Redis協(xié)議的純文本文件甥桂。
一般配置成每秒調(diào)用一次fdatasync將kernel的文件緩存刷到磁盤柿究。當(dāng)操作系統(tǒng)非正常關(guān)機(jī)時(shí),文件可能會(huì)丟失不超過2秒的數(shù)據(jù)黄选。 如果設(shè)為fsync always蝇摸,性能很低,只剩幾百TPS办陷。如果設(shè)為no貌夕,靠操作系統(tǒng)自己的sync同步,Linux系統(tǒng)一般30秒一次民镜。
AOF文件持續(xù)增長(zhǎng)而過大時(shí)啡专,會(huì)fork出一條新進(jìn)程來將文件重寫(也是先寫臨時(shí)文件,最后再rename)制圈, 遍歷新進(jìn)程的內(nèi)存中數(shù)據(jù)们童,每條記錄的Set語句。默認(rèn)配置是當(dāng)AOF文件大小是上次rewrite后大小的一倍离唐,且文件大于64M時(shí)觸發(fā)病附。
Redis協(xié)議,如set mykey hello亥鬓, 將持久化成*3 $3 set $5 mykey $5 hello完沪, 第一個(gè)數(shù)字代表這條語句有多少元,其他的數(shù)字代表后面字符串的長(zhǎng)度嵌戈。這樣的設(shè)計(jì)覆积,使得即使在寫文件過程中突然關(guān)機(jī)導(dǎo)致文件不完整,也能自我修復(fù)熟呛,執(zhí)行redis-check-aof即可宽档。
2.3 RDB vs AOF
綜上:
RDB的數(shù)據(jù)不實(shí)時(shí),同時(shí)使用兩者時(shí)服務(wù)器重啟也只會(huì)找AOF文件庵朝。那要不要只使用AOF呢吗冤?作者建議不要,因?yàn)镽DB更適合用于備份數(shù)據(jù)庫(AOF在不斷變化不好備份)九府,快速重啟椎瘟,而且不會(huì)有AOF可能潛在的bug,留著作為一個(gè)萬一的手段侄旬。
因?yàn)镽DB文件只用作后備用途肺蔚,建議只在Slave上持久化RDB文件,而且只要15分鐘備份一次就夠了儡羔,只保留save 900 1這條規(guī)則宣羊。
如果Enalbe AOF璧诵,好處是在最惡劣情況下也只會(huì)丟失不超過兩秒數(shù)據(jù),啟動(dòng)腳本簡(jiǎn)單load自己的AOF文件就可以了仇冯。代價(jià)一是帶來了持續(xù)的IO之宿,二是AOF rewrite的最后將rewrite過程中產(chǎn)生的新數(shù)據(jù)寫到新文件造成的阻塞幾乎是不可避免的。只要硬盤許可赞枕,應(yīng)該盡量減少AOF rewrite的頻率澈缺,AOF重寫的基礎(chǔ)大小默認(rèn)值64M太小了,可以設(shè)到5G以上炕婶。
如果不Enable AOF ,僅靠Master-Slave Replication 實(shí)現(xiàn)高可用性也可以莱预。能省掉一大筆IO也減少了rewrite時(shí)帶來的系統(tǒng)波動(dòng)柠掂。代價(jià)是如果Master/Slave同時(shí)倒掉依沮,會(huì)丟失十幾分鐘的數(shù)據(jù),啟動(dòng)腳本也要比較兩個(gè)Master/Slave中的RDB文件危喉,載入較新的那個(gè)。
3- 高可用與故障切換
Master-Slave復(fù)制與Fail-Over來實(shí)現(xiàn)真正的高可用
3.1 Master-Slave復(fù)制
slave可以在配置文件辜限、啟動(dòng)命令行參數(shù)、以及redis-cli執(zhí)行SlaveOf指令來設(shè)置自己是奴隸薄嫡,設(shè)置 Slaveof no one,slave會(huì)立馬變身master毫深;Slave只可以接收客戶端的讀請(qǐng)求吩坝,兼有負(fù)載均衡的功能钉寝。
復(fù)制速度:測(cè)試表明同步延時(shí)非常小,Master指令一旦執(zhí)行完畢就會(huì)立刻寫AOF文件和向Slave轉(zhuǎn)發(fā)闸迷,除非Slave自己被阻塞住了嵌纲。
復(fù)制過程:先執(zhí)行一次Master快照RDB的全同步 — slave請(qǐng)求Master的一個(gè)RDB Snapshot文件,slave接收完畢后稿黍,清除掉自己的舊數(shù)據(jù)疹瘦,然后將RDB載入內(nèi)存。**再進(jìn)行增量同步 **— master作為一個(gè)普通的client連入slave巡球,將所有寫操作轉(zhuǎn)發(fā)給slave言沐,沒有特殊的同步協(xié)議
詳細(xì)步驟:
1) 在Slave啟動(dòng)并連接到Master之后邓嘹,它將主動(dòng)發(fā)送一個(gè)SYNC命令。
2)此后Master將啟動(dòng)后臺(tái)存盤進(jìn)程险胰,同時(shí)收集所有接收到的用于修改數(shù)據(jù)集的命令汹押,在后臺(tái)進(jìn)程執(zhí)行完畢后,Master將傳送整個(gè)數(shù)據(jù)庫文件到Slave起便,以完成一次完全同步棚贾。
3) 而Slave服務(wù)器在接收到數(shù)據(jù)庫文件數(shù)據(jù)之后將其存盤并加載到內(nèi)存中。
4)此后榆综,Master繼續(xù)將所有已經(jīng)收集到的修改命令妙痹,和新的修改命令依次傳送給Slaves,Slave將在依次執(zhí)行這些數(shù)據(jù)修改命令鼻疮,從而達(dá)到最終的數(shù)據(jù)同步怯伊。
5)如果Master和Slave之間的鏈接出現(xiàn)斷連現(xiàn)象,Slave可以自動(dòng)重連Master判沟,但是在連接成功之后耿芹,一次完全同步將被自動(dòng)執(zhí)行。
- 特點(diǎn)
- 同一個(gè)Master可以同步多個(gè)Slaves挪哄。
- Slave同樣可以接受其它Slaves的連接和同步請(qǐng)求吧秕,這樣可以有效的分載Master的同步壓力。因此我們可以將Redis的Replication架構(gòu)視為圖結(jié)構(gòu)迹炼。
- Master Server是以非阻塞的方式為Slaves提供服務(wù)砸彬。所以在Master-Slave同步期間,客戶端仍然可以提交查詢或修改請(qǐng)求疗涉。
- SlaveServer同樣是以非阻塞的方式完成數(shù)據(jù)同步拿霉。在同步期間,如果有客戶端提交查詢請(qǐng)求咱扣,Redis則返回同步之前的數(shù)據(jù)绽淘。
- 為了分載Master的讀操作壓力,Slave服務(wù)器可以為客戶端提供只讀操作的服務(wù)闹伪,寫服務(wù)仍然必須由Master來完成。即便如此偏瓤,系統(tǒng)的伸縮性還是得到了很大的提高。
- Master可以將數(shù)據(jù)保存操作交給Slaves完成赔退,從而避免了在Master中要有獨(dú)立的進(jìn)程來完成此操作硕旗。
- 潛在的問題
Slave從庫在連接Master主庫時(shí),Master會(huì)進(jìn)行內(nèi)存存盤生成快照创译,然后把整個(gè)快照文件發(fā)給Slave软族,也就是沒有象MySQL那樣有復(fù)制位置的概念残制,即無增量復(fù)制,這會(huì)給整個(gè)集群搭建帶來非常多的問題仰禽。比如Slave由于網(wǎng)絡(luò)或者其它原因與Master斷開了連接,那么當(dāng) Slave進(jìn)行重新連接時(shí)规揪,需要重新獲取整個(gè)Master的內(nèi)存快照猛铅,Slave所有數(shù)據(jù)跟著全部清除,然后重新建立整個(gè)內(nèi)存表堕伪,一方面Slave恢復(fù)的時(shí)間會(huì)非常慢欠雌,另一方面也會(huì)給主庫帶來壓力疙筹。
3.2 Fail-Ove(sentinel)
Redis-sentinel是2.6版開始加入的另一組獨(dú)立運(yùn)行的節(jié)點(diǎn)而咆,提供自動(dòng)Fail Over的支持
3.2.1 發(fā)現(xiàn) master/slave及其他sentinel
- master地址在sentinel.conf里, sentinel會(huì)每10秒一次向master發(fā)送INFO,知道m(xù)aster的slave有哪些悠瞬。
- 如果master已經(jīng)變?yōu)閟lave浅妆,sentinel會(huì)分析INFO的應(yīng)答指向新的master狂打。
- 另外,sentinel會(huì)在master上建一個(gè)pub/sub channel对省,名為”sentinel:hello”蒿涎,通告各種信息惦辛,sentinel們也是通過接收pub/sub channel上的sentinel的信息發(fā)現(xiàn)彼此胖齐,因?yàn)槊颗_(tái)sentinel每5秒會(huì)發(fā)送一次自己的host信息,宣告自己的存在补履。
3.2.2 監(jiān)測(cè)與切換過程:
- Sentinel每秒鐘對(duì)所有master箫锤,slave和其他sentinel執(zhí)行Ping雨女,redis-server節(jié)點(diǎn)要應(yīng)答。
- 如果某一臺(tái)Sentinel沒有在30秒內(nèi)(可配置得短一些哦)收到上述正確應(yīng)答馏臭,它就會(huì)認(rèn)為master處于sdown狀態(tài)(主觀Down)位喂,它向其他sentinel詢問是否也認(rèn)為該master倒了(SENTINEL is-master-down-by-addr );
- 如果quonum臺(tái)(默認(rèn)是2)sentinel在5秒鐘內(nèi)都這樣認(rèn)為塑崖,就會(huì)認(rèn)為master真是odown了(客觀Down)痛倚。
- 此時(shí)會(huì)選出一臺(tái)sentinel作為L(zhǎng)eader執(zhí)行fail-over, Leader會(huì)從slave中選出一個(gè)提升為master(執(zhí)行slaveof no one),然后讓其他slave指向它(執(zhí)行slaveof new master)掘鄙。
3.3 Redis高可用與故障轉(zhuǎn)移架構(gòu)設(shè)計(jì)
基于Sentinel + master/slave
上面雖然在server端完成了故障轉(zhuǎn)移操漠,但是對(duì)于客戶端程序來說饿这,Master切換后client并不知道新Master的IP地址长捧,一種辦法是client在訪問Server之前都要詢問一下Sentinel,獲取Master的最新IP哑子。但是明顯獲取一次數(shù)據(jù)需要訪問兩次卧蜓,網(wǎng)絡(luò)資源還是比較寶貴的把敞,有一種對(duì)client無感更經(jīng)濟(jì)實(shí)惠的切換方法:VIP漂移。
基于Sentinel + master/slave + VIP漂移
VIP方案是,redis系統(tǒng)對(duì)外始終是同一ip地址伸蚯,當(dāng)redis進(jìn)行故障轉(zhuǎn)移時(shí)简烤,需要做的是將VIP從之前的redis服務(wù)器漂移到現(xiàn)在新的主redis服務(wù)器上横侦。
當(dāng)前redis系統(tǒng)中主redis的ip地址是192.168.56.101枉侧,那么VIP(192.168.56.250)指向192.168.56.101,客戶端程序用VIP(192.168.56.250)地址連接redis憨栽,實(shí)際上連接的就是當(dāng)前主redis屑柔,這樣就避免了向sentinel發(fā)送請(qǐng)求。
當(dāng)主redis宕機(jī)死陆,進(jìn)行故障轉(zhuǎn)移時(shí)措译,192.168.56.102這臺(tái)服務(wù)器上的redis提升為主瞳遍,這時(shí)VIP(192.168.56.250)指向192.168.56.102菌羽,這樣客戶端程序不需要修改任何代碼,連接的是192.168.56.102這臺(tái)主redis猾蒂。
如何實(shí)現(xiàn)VIP漂移肚菠?
- 以使用redis sentinel的一個(gè)參數(shù)client-reconfig-script罩缴,這個(gè)參數(shù)配置執(zhí)行腳本箫章,sentinel在做failover的時(shí)候會(huì)執(zhí)行這個(gè)腳本。
- 漂移VIP也可以使用keepalived軟件來實(shí)現(xiàn)终抽。