Redis实战(六):Redis的集群:AKF,主从复制的概念引入,CAP,Sentinel 哨兵
單擊、單節點、單實例存在的問題
- 單點故障(物理機掛了,要等很久才能可用)
- 容量有限
- 壓力過大
解決方式
AKF
有XYZ三個軸,可以只發生一個,可以多個維度一起發生
X軸:Redis示例的副本,數據庫的副本…讀寫分離,增加備用性,解決單點故障的問題,全量鏡像,不能解決容量有限的問題
Y軸:對要存的數據按照不同的功能業務拆分,不同類別的數據分開存儲,客戶端實現指定查詢哪個庫,解決容量有限的問題
Z軸:在按照業務拆分的前提下,如果又存不下了,可以基于一定的規則,將一個業務將數據再拆分,存儲到不同的庫里。
數據量足夠小,更容易發揮單擊性能;
單機單點問題得到了解決;
新的問題
通過AKF實現一邊多,產生數據一致性的問題:
方案1:所有節點阻塞,直到數據全部一致 - 強一致性,成本極高,并且難以達到。如果有一個節點因為網絡問題掛了,整體就寫失敗了,對外表現出的是整個服務不可用。強一致性會破壞可用性。而我們將單redis拆分成多redis,本來就是要解決可用性的問題。
方案2:容忍數據丟失一部分,主redis直接返回ok,通過異步方式讓兩個從庫同步。存在的問題是,如果兩個從庫都寫失敗,別人在查詢的時候,會發現丟失了這個數據。
方案3:使用足夠可靠的kafka,達到數據的最終一致性。如果客戶端要取數據的話,有多種可能:在達到最終一致性之前,可能會取到不一致的數據
問題2:
主備:客戶端不參與業務,只作備用機
主從:主從復制,可以在從庫取數據
這里面一定會有主的概念,主自己又是一個單點。如果主掛掉了,又導致整個服務不可用了。
因此我們一般對主做HA(高可用),如果主掛了,可以選擇讓一個備機頂上去。這件事情可以人工去做,也可以自動的故障轉移。如何自動?要用一個程序實現。一個程序又會有單點故障的問題,因此監控程序自身應該也是一個一變多的集群。
多臺監控程序:多臺盯著一個主,如果redis掛了,可能有監控發現它掛了,有監控沒發現它掛,因為有網絡延時的存在。一個redis是好是壞,應該由多少臺監控程序決定?這時不能使用強一致性,因為可能有的監控由于網絡延遲卡住了。因此只要一部分給出ok,就立刻確定redis掛了。那么,一部分應該是幾個?這時候我們推導一下:
假設我們有3個監控,有1個說redis掛了,就立刻把他踢掉,但可能是由于這個監控的連接有問題,這就誤傷了。并且一個監控說話就能算數的話,三個監控之間會產生不同的結果,產生競爭。會產生一個問題:網絡分區(腦裂),不同的客戶端拿到的是不同的數據,對外表現為數據的不一致。
分區容忍性:有時候我們可能不需要全量數據的一致,比如一共有50臺tomcat注冊到注冊中心,注冊中心是一個集群,注冊中心有的注冊到了50臺,有的注冊到了40臺,這時候不管注冊了多少臺,只要能用就行,不一致這個問題會被我們包容。這就是分區容忍性。
如果2個監控說redis掛了,1個監控說redis還活著,這2個監控的勢力為2。勢力為1的監控就沒有決策權了。這時對外表現出的就不是一種模棱兩可的狀態了。
因此,當勢力達到n/2+1,也就是過半的時候,就可以解決腦力問題。所以集群一般使用奇數臺。
為什么是奇數臺?
我們用3臺和4臺比較,它們都只允許掛一臺。但4臺比3臺更容易掛一臺,而且4臺的價格更高。所以第4臺是沒有必要的。
Redis是怎么實現集群的?
Redis沒有使用強一致性。
實驗:(受限于設備個數,我們同一臺機器上用三個redis服務,是偽分布式)
實現三臺redis的主從復制,三臺機器端口號分別是6379(主),6380(從),6381(從)
1、在三臺redis的配置文件中,關閉aof。啟動三臺redis,在6380(從),6381(從)的client端執行REPLICAOF 127.0.0.1 6379
我們查看6379(主)的部分日志,可以看到6380連接進來了。(6381的連接日志在后面,沒截圖)
這時候我們假設6381(從)掛掉了,那么在使用redis-server ./6381.conf --replicaof 127.0.0.1 6379重啟之后,仍然會將掛掉這段時間的增量同步過來。
兩種不同的主從同步的方式:
配置文件中的repl-backlog-size 1mb 是增量復制的設置。
如果這個隊列設置的太小了,假設 從redis 就掛了3秒鐘,結果 主redis 1秒鐘就把隊列寫滿了,數據會擠出,這時候就要觸發全量的RDB了。所以要根據業務,調整合適的隊列大小。
下圖左邊是主,右邊是從
Sentinel 哨兵
主從復制需要人工維護單點故障的問題,因此我們引入哨兵機制
Redis 的 Sentinel 中文文檔
- 監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。
- 提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。
- 自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主服務器的其中一個從服務器升級為新的主服務器, 并讓失效主服務器的其他從服務器改為復制新的主服務器; 當客戶端試圖連接失效的主服務器時, 集群也會向客戶端返回新主服務器的地址, 使得集群可以使用新主服務器代替失效服務器。
Redis Sentinel 是一個分布式系統, 你可以在一個架構中運行多個 Sentinel 進程(progress), 這些進程使用流言協議(gossip protocols)來接收關于主服務器是否下線的信息, 并使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從服務器作為新的主服務器。
雖然 Redis Sentinel 釋出為一個單獨的可執行文件 redis-sentinel , 但實際上它只是一個運行在特殊模式下的 Redis 服務器, 你可以在啟動一個普通 Redis 服務器時通過給定 –sentinel 選項來啟動 Redis Sentinel 。
總結
以上是生活随笔為你收集整理的Redis实战(六):Redis的集群:AKF,主从复制的概念引入,CAP,Sentinel 哨兵的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多线程与高并发(七):详解线程池 - 自
- 下一篇: MySQL调优(六):分区设计,分区优化