Redis系列(五)發布訂閱模式、主從復制和哨兵模式


NoSQL 開發中或多或少都會用到,也是面試必問知識點。最近這幾天的面試每一場都問到了。但是感覺回答的並不好,還有很多需要梳理的知識點。這里通過幾篇 Redis 筆記整個梳理一遍,后面再加上面試題。

Redis 系列:

  1. Redis系列(一)Redis入門
  2. Redis系列(二)Redis的8種數據類型
  3. Redis系列(三)Redis的事務和Spring Boot整合
  4. Redis系列(四)Redis配置文件和持久化
  5. Redis系列(五)發布訂閱模式、主從復制和哨兵模式
  6. Redis系列(六)Redis 的緩存穿透、緩存擊穿和緩存雪崩
  7. Redis系列(七)Redis面試題
  8. Redis命令參考

1、Redis 訂閱發布

Redis 發布訂閱(pub/sub)是一種消息通信模式:發送者發(pub)送消息,訂閱者(sub)接收消息。

Redis 客戶端可以訂閱任意數量的頻道。

訂閱 / 發布消息圖:

下圖展示了頻道 channel1,已經訂閱這個頻道的三個客戶端。

當有新消息通過 publish 命令發送給頻道 channel1 時,這個消息就會被發送給訂閱它的三個客戶端。

命令

這些命令被廣泛應用於構建即時通訊應用、比如網絡聊天室和實時廣播、實時提醒等。

序號 命令及描述
1 [PSUBSCRIBE pattern pattern ...] 訂閱一個或多個符合給定模式的頻道。
2 [PUBSUB subcommand argument [argument ...]] 查看訂閱與發布系統狀態。
3 PUBLISH channel message 將信息發送到指定的頻道。
4 [PUNSUBSCRIBE pattern [pattern ...]] 退訂所有給定模式的頻道。
5 [SUBSCRIBE channel channel ...] 訂閱給定的一個或多個頻道的信息。
6 [UNSUBSCRIBE channel [channel ...]] 指退訂給定的頻道。

測試

以下實例演示了發布訂閱是如何工作的。在我們實例中我們創建了訂閱頻道名為 redisChat:

redis 127.0.0.1:6379> SUBSCRIBE redisChat

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

現在,我們先重新開啟個 redis 客戶端,然后在同一個頻道 redisChat 發布兩次消息,訂閱者就能接收到消息。

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"

(integer) 1

redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"

(integer) 1

# 訂閱者的客戶端會顯示如下消息
1) "message"
2) "redisChat"
3) "Redis is a great caching technique"
1) "message"
2) "redisChat"
3) "Learn redis by runoob.com"

原理

Redis 是使用 C 實現的,通過分析 Redis 源碼里的 public.c 文件,了解發布和訂閱機制的底層實現,借此加深對 Redis 的理解。Redis 通過 public 、subscribe 和 psubscribe 等命令實現發布和訂閱功能。

微信:

通過 subscribe 命令訂閱某頻道后,redis=server 里面維護了一個字典,字典的鍵就是一個個頻道!而字典的值則是一個鏈表,鏈表保存了所有訂閱這個 channel 的客戶端。subscribe 命令的關鍵,就是講客戶端添加到給定 channel 的訂閱鏈中。

通過 publish 命令向訂閱者發送消息,redis-server 會使用給定的頻道作為鍵,在它所維護的channel 字典中查找記錄了訂閱這個頻道的所有客戶端的鏈表,遍歷這個鏈表,將消息發布給所有的訂閱者。

使用場景:

1、實時消息系統

2、實時聊天

3、訂閱、關注系統都可以

稍微復雜的場景更多的使用消息中間件 MQ。


2、主從復制

1、概念

主從復制,是指將一台 Redis 服務器的數據,復制到其他的 Redis 服務器。前者稱之為主節點(master/leader),后者稱之為從節點(slave/flower);數據的復制都是單向的,只能從主節點到從節點。Master 以寫為主,Slave 以讀為主。

默認情況下,每台 Redis 服務器都是主節點。且一個主節點可以有多個從節點或者沒有從節點,但是一個從節點只能有一個主節點。

2、主從復制的作用

1、數據冗余:主從復制實現了數據的熱備份,是持久化的之外的一種數據冗余方式。

2、故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復。實際也是一種服務的冗余。

3、負載均衡:在主從復制的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫 Redis 數據時應用連接主節點,讀 Redis 的時候應用連接從節點),分擔服務器負載;尤其是在寫少讀多的場景下,通過多個節點分擔讀負載,可以大大提高 Redis 服務器的並發量。

4、高可用(集群)的基石:除了上述作用以外,主從復制還是哨兵模式和集群能夠實施的基礎,因此說主從復制是 Redis 高可用的基礎。

一般來說,要將Redis 運用於工程項目中,只使用一台 Redis 是萬萬不能的(可能會宕機),原因如下:

1、從結構上,單個 Redis 服務器會發生單點故障,並且一台服務器需要處理所有的請求負載,壓力很大;

2、從容量上,單個 Redis 服務器內存容量有限,就算一台 Redis 服務器內存容量為 265G, 也不能將所有的內存用作 Redis 存儲內存,一般來說,單台 Redis最大使用內存不應該超過 20G

電商網站上的商品,一般都是一次上傳,無數次瀏覽的,說專業點就是“多讀少寫”。

對於這種場景,我們可以使用如下這種架構:

主從復制,讀寫分離!80% 的情況下,都是在進行讀操作。這種架構可以減少服務器壓力,經常使用實際生產環境中,最少是“一主二從”的配置。真實環境中不可能使用單機 Redis。

3、環境配置

只配置從庫,不用配置主庫。

[root@itzhouc bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> info replication			# 查看當前庫的信息
# Replication
role:master									# 角色
connected_slaves:0							# 當前沒有從庫
master_replid:2467dd9bd1c252ce80df280c925187b3417055ad
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> 

復制 3 個配置文件,然后修改對應的信息

1、端口

2、pid 名稱

3、log 文件名稱

4、dump.rdb 名稱

port 6381
pidfile /var/run/redis_6381.pid
logfile "6381.log"
dbfilename dump6381.rdb

修改完畢后,啟動我們的 3 個 redis 服務器,可以通過進程信息查詢。

[root@itzhouc ~]# ps -ef|grep redis
root       426     1  0 16:53 ?        00:00:00 redis-server *:6379
root       446     1  0 16:54 ?        00:00:00 redis-server *:6380
root       457     1  0 16:54 ?        00:00:00 redis-server *:6381
root       464   304  0 16:54 pts/3    00:00:00 grep --color=auto redis

4、一主二從

默認情況下,每台 Redis 服務器都是主節點,我們一般情況下,只用配置從機就好了。

主機:6379, 從機:6380 和 6381

配置的方式有兩種:一種是直接使用命令配置,這種方式當 Redis 重啟后配置會失效。另一種方式是使用配置文件。這里使用命令演示一下。

下面將80 和 81 兩個配置為在從機。

127.0.0.1:6380> SLAVEOF 127.0.0.1 6379		# SLAVEOF host  port
OK
127.0.0.1:6380> info replication
# Replication
role:slave			# 角色已經是從機了
master_host:127.0.0.1	# 主節點地址
master_port:6379			# 主節點端口
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:907bcdf00c69d361ede43f4f6181004e2148efb7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0
127.0.0.1:6380> 

配置好了之后,看主機:

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2		# 主節點下有兩個從節點
slave0:ip=127.0.0.1,port=6380,state=online,offset=420,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=420,lag=1
master_replid:907bcdf00c69d361ede43f4f6181004e2148efb7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:420
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:420
127.0.0.1:6379> 

真實的主從配置應該是在配置文件中配置,這樣才是永久的。這里使用命令是暫時的。

配置文件 redis.conf

################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.
#
# replicaof <masterip> <masterport>			# 這里配置

# If the master is password protected (using the "requirepass" configuration
# directive below) it is possible to tell the replica to authenticate before
# starting the replication synchronization process, otherwise the master will
# refuse the replica request.
#
# masterauth <master-password>

配置方式也是一樣的。

5、幾個問題

1、主機可以寫,從機不能寫只能讀。主機中的所有信息和數據都會保存在從機中。如果從機嘗試進行寫操作就會報錯。

127.0.0.1:6381> get k1			# k1的值是在主機中寫入的,從機中可以讀取到。
"v1"
127.0.0.1:6381> set k2 v2			# 從機嘗試寫操作,報錯了
(error) READONLY You can't write against a read only replica.
127.0.0.1:6381> 

2、如果主機斷開了,從機依然鏈接到主機,可以進行讀操作,但是還是沒有寫操作。這個時候,主機如果恢復了,從機依然可以直接從主機同步信息。

3、使用命令行配置的主從機,如果從機重啟了,就會變回主機。如果再通過命令變回從機的話,立馬就可以從主機中獲取值。這是復制原理決定的。

6、復制原理

Slave 啟動成功連接到 Master 后會發送一個 sync 同步命令。

Master 接收到命令后,啟動后台的存盤進程,同時收集所有接收到的用於修改數據集的命令,在后台進程執行完畢后,master 將傳送整個數據文件到 slave ,並完成一次完全同步。

全量復制:Slave 服務在接收到數據庫文件后,將其存盤並加載到內存中。

增量復制: Master 繼續將新的所有收集到的修改命令一次傳給 slave,完成同步。

但是只要重新連接 master ,一次完全同步(全量復制)將被自動執行。我們的數據一定可以在從機中看到。

這種模式的原理圖:

第二種模式

這種模式的話,將 6381 的主節點配置為 6380 。主節點 6379 只有一個從機。

如果現在 6379 節點宕機了, 6380 和 6381 節點都是從節點,只能進行讀操作,都不會自動變為主節點。需要手動將其中一個變為主節點,使用如下命令:

SLAVEOF no one

3、哨兵模式

1、概述

主從切換技術的方式是:當主機服務器宕機之后,需要手動將一台服務器切換為主服務器,這需要人工干預,費時費力,還會造成一段時間內的服務不可用。這不是一種推薦的方式,更多的時候我們優先考慮的的是哨兵模式。Redis 從 2.8 開始正式提供了 Sentinel(哨兵)架構來解決這個問題。

哨兵模式能夠后台監控主機是否故障,如果故障了根據投票數自動將從庫轉換為主庫。

哨兵模式是一種特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一個獨立的進程,作為進程,它獨立運行。其原理是哨兵通過發送命令,等待 Redis 服務器響應,從而監控運行的多個 Redis 實例

這里的哨兵有兩個作用

  • 通過發送命令,讓 Redis 服務器返回監控其運行狀態,包括主服務器和從服務器
  • 當哨兵檢測到 master 宕機,會自動將 slave 切換為 master,然后通過發布訂閱模式通知其他的從放服務器,修改配置文件,讓他們切換主機。

然而一個哨兵進程對 Redis 服務器進行監控,可能會出現問題,為此,我們可以使用多個哨兵進行監控。各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。

假設主服務器宕機了,哨兵1先檢測到這個結果,系統並不會馬上進行 failover 過程,僅僅是哨兵 1 主觀認為主服務器不可用,這個現象稱之為主觀下線。當后面的哨兵也檢測到主服務器不可用,並且數量達到一定值時,那么哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行 failover 【故障轉移】。切換成功后,就會通過發布訂閱模式,讓各個哨兵把自己監控的從服務器實現切換主機,這個過程稱之為客觀下線

2、配置一個一主二從的哨兵模式

1、配置哨兵模式配置文件,新建文件 /usr/local/bin/kconfig/sentinel.conf

# sentinel monitor 被監控的名字(隨便寫) host 1
sentinel monitor myredis 127.0.0.1 1

后面的數字1代表主機宕機后,slave投票決定誰成為新的主機,票數最多成為主機。

2、啟動哨兵

[root@itzhouc bin]# ls
6379.log  6381.log      dump6380.rdb  dump.rdb  redis-benchmark  redis-check-rdb  redis-sentinel
6380.log  dump6379.rdb  dump6381.rdb  kconfig   redis-check-aof  redis-cli        redis-server
[root@itzhouc bin]# redis-sentinel kconfig/sentinel.conf 
2421:X 15 May 2020 20:24:06.847 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2421:X 15 May 2020 20:24:06.847 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=2421, just started
2421:X 15 May 2020 20:24:06.847 # Configuration loaded
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.5 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 2421
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

2421:X 15 May 2020 20:24:06.848 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
2421:X 15 May 2020 20:24:06.851 # Sentinel ID is 100430af0018d23bd1ae2fe57e71e0d45f64d9a5
2421:X 15 May 2020 20:24:06.851 # +monitor master myredis 127.0.0.1 6379 quorum 1
2421:X 15 May 2020 20:24:06.852 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379

啟動成功~!

如果現在 Master 節點宕機了,這個時候會從從機中根據投票算法選擇一個作為主機。

如果原來的主機恢復運行了,只能歸到新的主機下,作為從機, 這就是哨兵模式的規則。

哨兵模式的優點

1、哨兵集群,基於主從復制模式,所有的主從配置優點,它全有

2、主從可以切換,故障可以轉移,系統的可用性就會更好

3、哨兵模式就是主從模式的升級,手動到自動,更加健壯。

哨兵模式的缺點

1、Redis 不方便在線擴容,集群達到一定的上限,在線擴容就會十分麻煩;

2、實現哨兵模式的配置其實也很麻煩,里面有甚多的配置項。

下一篇筆記將介紹 Redis 的緩存穿透、緩存擊穿和緩存雪崩。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM