NoSQL 開發中或多或少都會用到,也是面試必問知識點,最近這幾天的面試每一場都問到了,但是感徑訓答的并不好,還有很多需要梳理的知識點,這里通過幾篇 Redis 筆記整個梳理一遍,后面再加上面試題,
Redis 系列:
- Redis系列(一)Redis入門
- Redis系列(二)Redis的8種資料型別
- Redis系列(三)Redis的事務和Spring Boot整合
- Redis系列(四)Redis組態檔和持久化
- Redis系列(五)發布訂閱模式、主從復制和哨兵模式
- Redis系列(六)Redis 的快取穿透、快取擊穿和快取雪崩
- Redis系列(七)Redis面試題
- 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 的快取穿透、快取擊穿和快取雪崩,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/3173.html
標籤:NoSQL
