Redis集群方式共有三種:主從模式,哨兵模式,集群(cluster)模式
* 主從模式
主從模式是三種集群方式里最簡單的。它主要是基于Redis的主從復制特性架構的。通常我們會設置一個主節點,N個從節點;默認情況下,主節點負責處理使用者的IO操作,而從節點則會對主節點的數據進行備份,并且也會對外提供讀操作的處理。
主要的特點如下:
1. 主從模式下,當某一節點損壞時,因為其會將數據備份到其它Redis實例上,這樣做在很大程度上可以恢復丟失的數據。
2. 主從模式下,可以保證負載均衡.
3. 主從模式下,主節點和從節點是讀寫分離的。使用者不僅可以從主節點上讀取數據,還可以很方便的從從節點上讀取到數據,這在一定程度上緩解了主機的壓力。
從節點也是能夠支持寫入數據的,只不過從從節點寫入的數據不會同步到主節點以及其它的從節點下。
從以上,我們不難看出Redis在主從模式下,必須保證主節點不會宕機——一旦主節點宕機,其它節點不會競爭稱為主節點,此時,Redis將喪失寫的能力。這點在生產環境中,是致命的。
* 哨兵模式
哨兵模式是基于主從模式做的一定變化,它能夠為Redis提供了高可用性。
在實際生產中,服務器難免不會遇到一些突發狀況:服務器宕機,停電,硬件損壞等。這些情況一旦發生,其后果往往是不可估量的。
而哨兵模式在一定程度上能夠幫我們規避掉這些意外導致的災難性后果。其實,哨兵模式的核心還是主從復制。
只不過相對于主從模式在主節點宕機導致不可寫的情況下,多了一個競選機制——從所有的從節點競選出新的主節點。競選機制的實現,是依賴于在系統中啟動一個sentinel進程。
sentinel特點:
* 監控:它會監聽主服務器和從服務器之間是否在正常工作。
* 通知:它能夠通過API告訴系統管理員或者程序,集群中某個實例出了問題。
* 故障轉移:它在主節點出了問題的情況下,會在所有的從節點中競選出一個節點,并將其作為新的主節點。
* 提供主服務器地址:它還能夠向使用者提供當前主節點的地址。這在故障轉移后,使用者不用做任何修改就可以知道當前主節點地址。
sentinel,也可以集群,部署多個哨兵,sentinel可以通過發布與訂閱來自動發現Redis集群上的其它sentinel。sentinel在發現其它sentinel進程后,會將其放入一個列表中,這個列表存儲了所有已被發現的sentinel。
集群中的所有sentinel不會并發著去對同一個主節點進行故障轉移。故障轉移只會從第一個sentinel開始,當第一個故障轉移失敗后,才會嘗試下一個。
當選擇一個從節點作為新的主節點后,故障轉移即成功了(而不會等到所有的從節點配置了新的主節點后)。這過程中,如果重啟了舊的主節點,那么就會出現無主節點的情況,這種情況下,只能重啟集群。
當競選出新的主節點后,被選為新的主節點的從節點的配置信息會被sentinel改寫為舊的主節點的配置信息。完成改寫后,再將新主節點的配置廣播給所有的從節點。
* 集群模式
Redis 集群是一個提供在多個Redis間節點間共享數據的程序集, 其中Redis集群分為主節點和從節點。主節點用于處理槽,而從節點用于復制某個主節點,并在被復制的主節點下線時,代替下線的主節點繼續處理命令請求。
Redis集群并不支持處理多個keys的命令,因為這需要在不同的節點間移動數據,從而達不到像Redis那樣的性能,在高負載的情況下可能會導致不可預料的錯誤.
Redis 集群通過分區來提供一定程度的可用性,在實際環境中當某個節點宕機或者不可達的情況下繼續處理命令. Redis 集群的優勢:
自動分割數據到不同的節點上。
整個集群的部分節點失敗或者不可達的情況下能夠繼續處理命令。
Redis集群的數據分片 Redis 集群沒有使用一致性hash, 而是引入了哈希槽的概念.
Redis 集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽.集群的每個節點負責一部分hash槽.
例如,當前集群有3個節點,那么:
* 節點 A 包含 0 到 5500號哈希槽.
* 節點 B 包含5501 到 11000 號哈希槽.
* 節點 C 包含11001 到 16384號哈希槽.
這種結構很容易添加或者刪除節點. 比如如果我想新添加個節點D, 我需要從節點 A, B, C中得部分槽到D上.
如果我想移除節點A,需要將A中的槽移到B和C節點上,然后將沒有任何槽的A節點從集群中移除即可.
由于從一個節點將哈希槽移動到另一個節點并不會停止服務,所以無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集群不可用的狀態.
Redis 集群的主從復制模型 為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有N-1個復制品.
- Golang基礎
- Go中new與make的區別
- Golang中除了加Mutex鎖以外還有哪些方式安全讀寫共享變量
- 無緩沖Chan的發送和接收是否同步
- Golang并發機制以及它所使用的CSP并發模型.
- Golang中常用的并發模型
- Go中對nil的Slice和空Slice的處理是一致的嗎
- 協程和線程和進程的區別
- Golang的內存模型中為什么小對象多了會造成GC壓力
- Go中數據競爭問題怎么解決
- 什么是channel,為什么它可以做到線程安全
- Golang垃圾回收算法
- GC的觸發條件
- Go的GPM如何調度
- 并發編程概念是什么
- Go語言的棧空間管理是怎么樣的
- Goroutine和Channel的作用分別是什么
- 怎么查看Goroutine的數量
- Go中的鎖有哪些
- 怎么限制Goroutine的數量
- Channel是同步的還是異步的
- Goroutine和線程的區別
- Go的Struct能不能比較
- Go的defer原理是什么
- Go的select可以用于什么
- Context包的用途是什么
- Go主協程如何等其余協程完再操作
- Go的Slice如何擴容
- Go中的map如何實現順序讀取
- Go中CAS是怎么回事
- Go中的逃逸分析是什么
- Go值接收者和指針接收者的區別
- Go的對象在內存中是怎樣分配的
- 棧的內存是怎么分配的
- 堆內存管理怎么分配的
- 在Go函數中為什么會發生內存泄露
- G0的作用
- Go中的鎖如何實現
- Go中的channel的實現
- 棧的內存是怎么分配的2
- 堆內存管理怎么分配的2
- Go中的map的實現
- Go中的http包的實現原理
- Goroutine發生了泄漏如何檢測
- Go函數返回局部變量的指針是否安全
- Go中兩個Nil可能不相等嗎
- Goroutine和KernelThread之間是什么關系
- 為何GPM調度要有P
- 如何在goroutine執行一半就退出協程
- Mysql基礎
- Mysql索引用的是什么算法
- Mysql事務的基本要素
- Mysql的存儲引擎
- Mysql事務隔離級別
- Mysql高可用方案有哪些
- Mysql中utf8和utf8mb4區別
- Mysql中樂觀鎖和悲觀鎖區別
- Mysql索引主要是哪些
- Mysql聯合索引最左匹配原則
- 聚簇索引和非聚簇索引區別
- 如何查詢一個字段是否命中了索引
- Mysql中查詢數據什么情況下不會命中索引
- Mysql中的MVCC是什么
- Mvcc和Redolog和Undolog以及Binlog有什么不同
- Mysql讀寫分離以及主從同步
- InnoDB的關鍵特性
- Mysql如何保證一致性和持久性
- 為什么選擇B+樹作為索引結構
- InnoDB的行鎖模式
- 哈希(hash)比樹(tree)更快,索引結構為什么要設計成樹型
- 為什么索引的key長度不能太長
- Mysql的數據如何恢復到任意時間點
- Mysql為什么加了索引可以加快查詢
- Explain命令有什么用
- Redis基礎
- Redis的數據結構及使用場景
- Redis持久化的幾種方式
- Redis的LRU具體實現
- 單線程的Redis為什么快
- Redis的數據過期策略
- 如何解決Redis緩存雪崩問題
- 如何解決Redis緩存穿透問題
- Redis并發競爭key如何解決
- Redis的主從模式和哨兵模式和集群模式區別
- Redis有序集合zset底層怎么實現的
- 跳表的查詢過程是怎么樣的,查詢和插入的時間復雜度
- 網絡協議基礎
- TCP和UDP有什么區別
- TCP中三次握手和四次揮手
- TCP的LISTEN狀態是什么
- 常見的HTTP狀態碼有哪些
- 301和302有什么區別
- 504和500有什么區別
- HTTPS和HTTP有什么區別
- Quic有什么優點相比Http2
- Grpc的優缺點
- Get和Post區別
- Unicode和ASCII以及Utf8的區別
- Cookie與Session異同
- Client如何實現長連接
- Http1和Http2和Grpc之間的區別是什么
- Tcp中的拆包和粘包是怎么回事
- TFO的原理是什么
- TIME_WAIT的作用
- 網絡的性能指標有哪些