一、Redis單機(jī)模式

特點(diǎn):簡(jiǎn)單
問題:
1、內(nèi)存容量有限 2、處理能力有限 3、無法高可用。
二、Redis的主從模式

Redis 的主從同步復(fù)制(replication)功能,保證一個(gè) matser主節(jié)點(diǎn)服務(wù)器可以創(chuàng)建任意多個(gè)slaver從服務(wù)器實(shí)現(xiàn)數(shù)據(jù)從主節(jié)點(diǎn)傳遞到從節(jié)點(diǎn)。
主從復(fù)制流程如果所示:

Redis的主從模式特點(diǎn):
1、master/slave 角色
2、master/slave 數(shù)據(jù)相同
3、降低 master 并發(fā)讀壓力在轉(zhuǎn)交從庫
問題:
1、無法保證高可用,master節(jié)點(diǎn)宕機(jī)導(dǎo)致整個(gè)服務(wù)不可用
2、沒有解決 master 高并發(fā)寫的壓力
3、可能主從同步有數(shù)據(jù)延遲,對(duì)于即寫即讀的場(chǎng)景,必須強(qiáng)制使用主庫進(jìn)行數(shù)據(jù)讀寫
三、Redis哨兵模式

Sentinel(哨兵)是用于監(jiān)控Redis集群中Master狀態(tài)的工具,是Redis高可用解決方案,哨兵可以監(jiān)視一個(gè)或者多個(gè)redis master服務(wù),以及這些master服務(wù)的所有從服務(wù)。 某個(gè)master服務(wù)宕機(jī)后,會(huì)把這個(gè)master下的某個(gè)從服務(wù)升級(jí)為master來替代已宕機(jī)的master繼續(xù)工作。
(順帶提一句,即使后來之前的master重啟服務(wù),也不會(huì)變回master了,而是作為slave從服務(wù))
Redis sentinel 是一個(gè)分布式系統(tǒng)中監(jiān)控 redis 主從服務(wù)器,并在主服務(wù)器下線時(shí)自動(dòng)進(jìn)行故障轉(zhuǎn)移
其中三個(gè)特性:
1、監(jiān)控(Monitoring): Sentinel 會(huì)不斷地檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
2、提醒(Notification): 當(dāng)被監(jiān)控的某個(gè) Redis 服務(wù)器出現(xiàn)問題時(shí), Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
3、自動(dòng)故障遷移(Automatic failover): 當(dāng)一個(gè)主服務(wù)器不能正常工作時(shí), Sentinel 會(huì)開始一次自動(dòng)故障遷移操作
特點(diǎn):
1、保證高可用
2、監(jiān)控各個(gè)節(jié)點(diǎn)
3、自動(dòng)故障遷移
缺點(diǎn):主從模式,切換需要時(shí)間丟數(shù)據(jù)
沒有解決 master 寫的壓力
四、Redis Cluster分片集群架構(gòu)模式
但隨著Redis的版本迭代,Redis官方的Cluster也越來越穩(wěn)定,更多人開始采用官方的集群化方案。也正是因?yàn)樗枪俜酵瞥龅?,所以它的持續(xù)維護(hù)性可以得到保障,這就比那些第三方的開源方案更有優(yōu)勢(shì)。
Redis Cluster沒有了中間的Proxy代理層,那么是如何進(jìn)行請(qǐng)求的轉(zhuǎn)發(fā)呢?
Redis把請(qǐng)求轉(zhuǎn)發(fā)的邏輯放在了Smart Client中,要想使用Redis Cluster,必須升級(jí)Client SDK,這個(gè)SDK中內(nèi)置了請(qǐng)求轉(zhuǎn)發(fā)的邏輯,所以業(yè)務(wù)開發(fā)人員同樣不需要自己編寫轉(zhuǎn)發(fā)規(guī)則,Redis Cluster采用16384個(gè)槽位進(jìn)行路由規(guī)則的轉(zhuǎn)發(fā)。也有第三方代理方案:請(qǐng)參考Redis代理集群




圖中定義的規(guī)則是平均分配槽位:
①節(jié)點(diǎn)1的槽位區(qū)間范圍為0-5460
②節(jié)點(diǎn)2的槽位區(qū)間范圍為5461-10922
③節(jié)點(diǎn)3的槽位區(qū)間范圍為10923-16383
Redis虛擬槽的特點(diǎn)
解耦數(shù)據(jù)和節(jié)點(diǎn)之間的關(guān)系,簡(jiǎn)化了節(jié)點(diǎn)擴(kuò)容和收縮難度。
節(jié)點(diǎn)自身維護(hù)槽的映射關(guān)系,不需要客戶端或者代理服務(wù)維護(hù)槽分區(qū)元數(shù)據(jù)。
支持節(jié)點(diǎn)、槽和鍵之間的映射查詢,用于數(shù)據(jù)路由,在線集群伸縮等場(chǎng)景。
Redis集群架構(gòu)伸縮
Redis 集群提供了靈活的節(jié)點(diǎn)擴(kuò)容和收縮方案。
在不影響集群對(duì)外服務(wù)的情況下,可以為集群添加節(jié)點(diǎn)進(jìn)行擴(kuò)容也可以下線部分節(jié)點(diǎn)進(jìn)行縮容。
可以說,槽是 Redis 集群管理數(shù)據(jù)的基本單位,集群伸縮就是槽和數(shù)據(jù)在節(jié)點(diǎn)之間的移動(dòng)
(1)假設(shè)主節(jié)點(diǎn)的數(shù)量為3,將16384個(gè)槽位按照用戶自己的規(guī)則手動(dòng)去分配這3個(gè)節(jié)點(diǎn),16384除以3,那么每個(gè)節(jié)點(diǎn)大約得到5460個(gè)槽。
(用戶自定義分配的原因在于有些機(jī)器的配置高,有些機(jī)器的配置低,配置高的可以分配多一點(diǎn)槽位,配置低的可以分配少一點(diǎn)槽位)
(2)存儲(chǔ)數(shù)據(jù)時(shí),對(duì)要存儲(chǔ)的鍵進(jìn)行crc16哈希運(yùn)算,得到一個(gè)值,并取模16384,判斷這個(gè)值在哪個(gè)節(jié)點(diǎn)的范圍區(qū)間。
假設(shè)crc16(“test_key”)%16384=3345
因?yàn)?345在區(qū)間0-5460之間,
所以test_key數(shù)據(jù)寫入到節(jié)點(diǎn)1里面。
(3)查詢數(shù)據(jù)時(shí),對(duì)要查詢的鍵進(jìn)行crc16哈希運(yùn)算,得到一個(gè)值,并取模16384,判斷這個(gè)值在哪個(gè)節(jié)點(diǎn)的范圍區(qū)間。
假設(shè)crc16(“test_key”)%16384=3345,
因?yàn)?345在區(qū)間0-5460之間,
所以test_key數(shù)據(jù)應(yīng)該從節(jié)點(diǎn)1里面獲取。
以上就是redis集群采用的虛擬哈希槽的原理和計(jì)算規(guī)則說明
這種結(jié)構(gòu)很容易添加或者刪除節(jié)點(diǎn),并且無論是添加刪除或者修改某一個(gè)節(jié)點(diǎn),都不會(huì)造成集群不可用的狀態(tài)。使用哈希槽的好處就在于可以方便的添加或移除節(jié)點(diǎn)。
當(dāng)需要增加節(jié)點(diǎn)時(shí),只需要把其他節(jié)點(diǎn)的某些哈希槽挪到新節(jié)點(diǎn)就可以了
當(dāng)需要移除節(jié)點(diǎn)時(shí),只需要把移除節(jié)點(diǎn)上的哈希槽挪到其他節(jié)點(diǎn)就可以了。
Redis Cluster也提供了在線數(shù)據(jù)遷移、節(jié)點(diǎn)擴(kuò)容縮容等功能,內(nèi)部還內(nèi)置了哨兵完成故障自動(dòng)恢復(fù)功能,可見它是一個(gè)集成所有功能于一體的Cluster。因此它在部署時(shí)非常簡(jiǎn)單,不需要部署過多的組件,對(duì)于運(yùn)維極其友好。
Redis Cluster在節(jié)點(diǎn)數(shù)據(jù)遷移、擴(kuò)容縮容時(shí),對(duì)于客戶端的請(qǐng)求處理也做了相應(yīng)的處理。當(dāng)客戶端訪問的數(shù)據(jù)正好在遷移過程中時(shí),服務(wù)端與客戶端制定了一些協(xié)議,來告知客戶端去正確的節(jié)點(diǎn)上訪問,幫助客戶端訂正自己的路由規(guī)則。
雖然Redis Cluster提供了在線數(shù)據(jù)遷移的功能,但它的遷移性能并不高,遷移過程中遇到大key時(shí)還有可能長時(shí)間阻塞遷移的兩個(gè)節(jié)點(diǎn)
現(xiàn)在越來越多的公司開始采用Redis Cluster,有能力的公司還在它的基礎(chǔ)上進(jìn)行了二次開發(fā)和定制,來解決Redis Cluster存在的一些問題,我們期待Redis Cluster未來有更好的發(fā)展。
特點(diǎn):
1、無中心架構(gòu)(不存在哪個(gè)節(jié)點(diǎn)影響性能瓶頸),少了 proxy 層。
2、數(shù)據(jù)按照 slot 存儲(chǔ)分布在多個(gè)節(jié)點(diǎn),節(jié)點(diǎn)間數(shù)據(jù)共享,可動(dòng)態(tài)調(diào)整數(shù)據(jù)分布。
3、可擴(kuò)展性,可線性擴(kuò)展到 1000 個(gè)節(jié)點(diǎn),節(jié)點(diǎn)可動(dòng)態(tài)添加或刪除。
4、高可用性,部分節(jié)點(diǎn)不可用時(shí),集群仍可用。通過增加 Slave 做備份數(shù)據(jù)副本
5、實(shí)現(xiàn)故障自動(dòng) failover,節(jié)點(diǎn)之間通過 gossip 協(xié)議交換狀態(tài)信息,用投票機(jī)制完成 Slave到 Master 的角色提升。
缺點(diǎn):
1、資源隔離性較差,容易出現(xiàn)相互影響的情況。
2、數(shù)據(jù)通過異步復(fù)制,不保證數(shù)據(jù)的強(qiáng)一致性集群的必要性
所謂的集群,就是通過添加服務(wù)器的數(shù)量,提供相同的服務(wù),從而讓服務(wù)器達(dá)到一個(gè)穩(wěn)定、高效的狀態(tài)。
- 使用 redis 集群的必要性
問題:我們已經(jīng)部署好了redis,并且能啟動(dòng)一個(gè)redis,實(shí)現(xiàn)數(shù)據(jù)的讀寫,為什么還要學(xué)習(xí)redis集群?
答:
(1)單個(gè)redis存在不穩(wěn)定性。當(dāng)redis服務(wù)宕機(jī)了,就沒有可用的服務(wù)了。
(2)單個(gè)redis的讀寫能力是有限的。
總結(jié):redis集群是為了強(qiáng)化redis的讀寫能力。
五、Redis集群擴(kuò)容機(jī)制

操作指南
1.redis擴(kuò)容的話,首先創(chuàng)建redis-cluster節(jié)點(diǎn)(具體配置和其他節(jié)點(diǎn)一樣),然后再把他們加入到redis集群中
redis-cli --cluster add-node new_host_ip:port exsitint_host_ip:port ##這個(gè)是將新節(jié)點(diǎn)加入到集群中
redis-cli --cluster add-node new_host_ip:port exsitint_host_ip:port --cluster-slave ##這個(gè)將新節(jié)點(diǎn)加入集群中作為后面一個(gè)節(jié)點(diǎn)的從節(jié)點(diǎn)
2.遷移槽,遷移槽時(shí)要計(jì)算原節(jié)點(diǎn)遷移多個(gè)槽到新節(jié)點(diǎn)中
redis-cli --cluster reshard <host>:<port> --cluster-from <node-id> --cluster-to <node-id> --cluster-slots <number of slots>
--cluster-yes
<host>:<port>:可以指定任意一個(gè)在集群中的節(jié)點(diǎn)
--cluster-from:這個(gè)指的是原節(jié)點(diǎn)
--cluter-to:這個(gè)指的是目標(biāo)節(jié)點(diǎn)
--cluter-slots:這個(gè)是要遷移的槽的數(shù)量
3.遷移完了之后,最后可以rebalance一下
4.縮容的話(感覺這種操作可能很少),首先也需要用2中的命令將槽給遷移到其他節(jié)點(diǎn)上,然后再用redis-cli --cluter del-node run_id 進(jìn)行刪除

redis cluster增加節(jié)點(diǎn)進(jìn)行擴(kuò)容步驟:
1.在新的服務(wù)器上部署redis cluster
2.使用工具將新部署的節(jié)點(diǎn)加到集群中
3.使用工具將集群槽位重新分配
4.將主從復(fù)制關(guān)系調(diào)整成交叉模式
擴(kuò)容原理: 原來的節(jié)點(diǎn)算好要拿出多少的槽位給新加的節(jié)點(diǎn),新加的節(jié)點(diǎn)準(zhǔn)備導(dǎo)入的槽位,準(zhǔn)備的前提條件就是加入集群,一切準(zhǔn)備就緒后,主節(jié)點(diǎn)將劃分出來的槽位分配給新節(jié)點(diǎn),然后將相關(guān)槽位的數(shù)據(jù)遷移到新的節(jié)點(diǎn)
為什么Redis Cluster會(huì)設(shè)計(jì)成16384個(gè)槽呢?
為什么Redis Cluster會(huì)設(shè)計(jì)成16384個(gè)槽呢?
理論上crc16算法可以得到2^16個(gè)數(shù)值,其數(shù)值范圍在0-65535之間,
取模運(yùn)算key的時(shí)候,應(yīng)該是crc16(key)%655351.如果槽位為65536,發(fā)送心跳信息的消息頭達(dá)8k,發(fā)送的心跳包過于龐大。
2.Redis的集群主節(jié)點(diǎn)數(shù)量基本不可能超過1000個(gè)。
3.槽位越小,節(jié)點(diǎn)少的情況下,壓縮率高1.redis cluster 分片為什么沒有使用一致性hash算法,而是使用了哈希槽預(yù)分片?
緩存熱點(diǎn)問題:
一致性哈希算法在節(jié)點(diǎn)太少時(shí),容易因?yàn)閿?shù)據(jù)分布不均勻而造成緩存熱點(diǎn)的問題。
一致性哈希算法可能集中在某個(gè)hash區(qū)間內(nèi)的值特別多,會(huì)導(dǎo)致大量的數(shù)據(jù)涌入同一個(gè)節(jié)點(diǎn)
造成master的熱點(diǎn)問題(如同一時(shí)間20W的請(qǐng)求都在某個(gè)hash區(qū)間內(nèi))