本篇文章給大家帶來了關于redis的相關知識,其中主要介紹了關于主從復制、哨兵和集群這三種模式的相關問題,還有分布式鎖以及系統優化等等,希望對大家有幫助。
推薦學習:redis
一、主從復制
1. 主從同步的用處
??通過持久化功能,redis 保證了即使在服務器重啟的情況下也不會丟失數據,因為持久化會把內存中的數據保存到硬盤上,重啟會從硬盤上加載數據,但是由于數據是存儲在一臺服務器上的,如果這臺服務器出現硬盤故障等問題,也會導致數據丟失。為了避免單點故障,通常的做法是將數據庫復制多個副本以部署在不同的服務器上,這樣即使有一臺服務器出現故障,其他服務器依然可以繼續提供服務。為此,redis 提供了復制 replication 功能,可以實現當一臺數據庫中的數據更新后,自動將更新的數據同步到其他數據庫上。
??在復制的概念中,數據庫分為兩類,一類是主數據庫 master,另一類是從數據庫 slave。主數據庫可以進行讀寫操作,當寫操做導致數據變化時自動將數據同步給從數據庫,而從數據庫一般是只讀的,并接收主數據庫同步過來的數據。一個主數據庫可以擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫。
2. 主從同步原理
2.1 原理詳解
-
若啟動一個 Slave 機器進程,則它會向 Master 機器發送一個 sync_command 命令,請求同步連接。
-
無論是第一次連接還是重新連接,Master 機器都會啟動一個后臺進程,將數據快照(RDB)保存到數據文件中(.rdb文件),同時 Master 還會記錄修改數據的所有命令并緩存在數據文件中。
-
后臺進程完成緩存操作之后,Master 機器就會向 Slave 機器發送數據文件,Slave 端機器將數據文件保存到硬盤上,然后將其加載到內存中,接著 Master 機器就會將修改數據的所有操作一并發送給 Slave 端機器。若 Slave 出現故障導致宕機,則恢復正常后會自動重新連接。
-
Master 機器收到 Slave 端機器的連接后,將其完整的數據文件發送給 Slave 端機器,如果 Master 同時收到多個 Slave發來的同步請求則 Master 會在后臺啟動一個進程以保存數據文件,然后將其發送給所有的 Slave 端機器,確保所有的 Slave 端機器都正常。
RDB 做全量同步,AOF 做增量同步
2.2 理論精簡
slave -> master 發送 sync command 申請同步 master 主進程 -> 調用 fork() 函數 派生 RDB 子進程進行持久化 -> 生成 RDB 文件 將 RDB 文件推送給 slaves(完成全量同步)#增量同步:使用到了 AOF 持久化(機制:將緩存數據保存到緩沖中),所以主從節點均需要開啟 AOF增量同步是通過 AOF 功能將緩存中的數據 append(追加)到緩沖中來進行 master 緩沖 -> slave 緩沖的同步 在持續性的運行過程中,也是增量持續同步的過程
2.3 最終精簡版
slave -> master 發送 syncmaster 使用 RDB 生成 .rdb 文件(全量同步)發送給 slaves master 使用 AOF 將緩沖區數據同步給 slaves 緩沖區數據(增量)
二、哨兵模式
1. 哨兵的作用
哨兵的出現主要是解決了主從復制出現故障時需要人為干預的問題
哨兵模式主要功能:
集群監控:負責監控 redismaster 和 slave 進程是否正常工作 消息通知:如果某個 redis 實例有故障,那么哨兵負責發送消息作為報警通知給管理員 故障轉移:如果 master node 掛掉了,會自動轉移到 slave node 上 配置中心:如果故障轉移發生了,通知 client 客戶端新的 master 地址
??使用一個或者多個哨兵 sentinel 實例組成的系統,對 redis 節點進行監控,在主節點出現故障的情況下,能將從節點中的一個升級為主節點,進行故障轉移,保證系統的可用性。
2. 哨兵原理
2.1 原理詳解
-
首先主節點的信息是配置在哨兵 sentinel 的配置文件中。
-
哨兵節點會和配置的主節點建立起兩條連接命令連接和訂閱連接
PS:redis 發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消 息,訂閱者 (sub)接收消息。 -
哨兵會通過命令連接每 10s 發送一次 INFO 命令,通過 INFO 命令,主節點會返回自己的 run_id 和自己的從節點信息。
-
哨兵會對這些從節點也建立兩條連接命令連接和訂閱連接。
-
哨兵通過命令連接向從節點發送 INFO 命令,獲取到他的一些信息:
run id(redis 服務器 id) role(職能) 從服務器的復制偏移量 offset 其他
-
通過命令連接向服務器的 sentinel:hello 頻道發送一條消息,內容包括自己的 IP、端口、run id、配置(后續投票的時候會用到)等。
-
通過訂閱連接對服務器的 sentinel:hello 頻道做了監聽,所有向該頻道發送的哨兵的消息都能被接受到。
-
解析監聽到的消息,進行分析提取,就可以知道還有那些別的哨兵服務節點也在監聽這些主從節點了,更新結構體將這些哨兵節點記錄下來。
-
向觀察到的其他的哨兵節點建立命令連接(此時沒有訂閱連接)。
2.2 原理精簡
3 個哨兵 3 個 redis
- 三個哨兵之間建立命令連接,周期檢測 “隊友” 狀態
- 哨兵會向 master 節點(己在配置文件中指定)發送兩條連接,分別是命令連接和訂閱連接(為了周期性獲取 master 節點的數據)
- 哨兵向 master 周期性發送 info 命令,master(活著的情況下)會返回 redis-cli info replication master 節點的信息 + 從節點位置
- 哨兵通過 master 返回的信息,再向 slaves 節點發送 info 命令,slaves 返回數據,從而哨兵集群就可以獲取到 redis 所有集群信息
- 哨兵會向服務器發送命令連接,建立自己的 hello 頻道,哨兵會向這個 hello 頻道建立訂閱,用于哨兵之間的消息共享
2.3 思路
- 3 個哨兵互相監聽,使用 ping 互相檢測存活
- 3 個哨兵分別向數據節點 master 發送命令連接和訂閱連接(info 命令)獲取數據節點信息(包含主從節點)3 個哨兵再向其他從節點發送 info ,用于獲取從節點詳細信息
- 3 個哨兵之間通過 hello 頻道進行消息共享
3. 哨兵模式下的故障遷移
-
① 主觀下線
哨兵節點會每秒一次的頻率向建立了命令連接的實例發送 PING 命令,如果在 down-after-milliseconds 毫秒內沒有做出有效響應包括 PONG/LOADING/MASTERDOWN 以外的響應,哨兵就會將該實例在本結構體中的狀態標記為 SRI_S_DOWN 主觀下線。 -
② 客觀下線
當一個哨兵節點發現主節點處于主觀下線狀態是,會向其他的哨兵節點發出詢問,該節點是不是已經主觀下線了。如果超過配置參數 quorum 個節點認為是主觀下線時,該哨兵節點就會將自己維護的結構體中該主節點標記為 SRIO DOWN 客觀下線詢問命令 SENTINEL is-master-down-by-addr。 -
③ master 選舉
在認為主節點客觀下線的情況下,哨兵節點節點間會發起一次選舉,命令為 SENTINEL is-master-down-by-addr ,只是 runid 這次會將自己的 runid 帶進去,希望接受者將自己設置為主節點。如果超過半數以上的節點返回將該節點標記為 leader 的情況下,會有該 leader 對故障進行遷移。 -
④ 故障轉移
####在從節點中挑選出新的主節點通訊正常 優先級排序 優先級相同時選擇 offset 最大的###將該節點設置成新的主節點SLAVEOF no one,并確保在后續的INGO命令時 該節點返回狀態為master ###將其他的從節點設置成從新的主節點復制,SLAVEOF命令###將舊的主節點變成新的主節點的從節點PS:優缺點#優點:高可用,哨兵模式是基于主從模式的,所有主從模式的優點,哨兵模式都具有有;主從可以自動切換,系統更健壯,可用性更高#缺點:redis 比較難支持在線擴容,在群集容量達到上限時在線擴容會變得很復雜
三、集群
1. redis 集群的含義
主節點負責讀寫請求和集群信息的維護,從節點只進行主節點數據和狀態信息的復制
??redis 的哨兵模式基本已經可以實現高可用、讀寫分離,但是在這種模式每臺 redis 服務器都存儲相同的數據,很浪費內存資源,所以在 redis3.0 上加入了 Cluster 群集模式,實現了 redis 的分布式存儲,也就是說每臺 redis 節點存儲著不同的內容。根據官方推薦,集群部署至少要 3 臺以上的 master 節點,最好使用 3 主 3 從六個節點的模式。
??Cluster 群集由多個 redis 服務器組成的分布式網絡服務群集,群集之中有多個 master 主節點,每一個主節點都可讀可寫,節點之間會相互通信,兩兩相連,redis 群集無中心節點。
2. redis 集群的特點
- 在 redis-Cluster 群集中,可以給每個一個主節點添加從節點,主節點和從節點直接尊循主從模型的特性,當用戶需要處理更多讀請求的時候,添加從節點可以擴展系統的讀性能
- redis-cluster 的故障轉移:redis 群集的主機節點內置了類似 redis sentinel 的節點故障檢測和自動故障轉移功能,當群集中的某個主節點下線時,群集中的其他在線主節點會注意到這一點,并且對已經下線的主節點進行故障轉移
- 集群進行故障轉移的方法和 redis sentinel 進行故障轉移的方法基本一樣,不同的是,在集群里面,故障轉移是由集群中其他在線的主節點負責進行的,所以群集不必另外使用 redis sentinel
四、分布式鎖
https://www.zhihu.com/question/300767410/answer/1749442787
??如果在一個分布式系統中,我們從數據庫中讀取一個數據,然后修改保存,這種情況很容易遇到并發問題。因為讀取和更新保存不是一個原子操作,在并發時就會導致數據的不正確。這種場景其實并不少見,比如電商秒殺活動,庫存數量的更新就會遇到。如果是單機應用,直接使用本地鎖就可以避免。如果是分布式應用,本地鎖派不上用場,這時就需要引入分布式鎖來解決。由此可見分布式鎖的目的其實很簡單,就是為了保證多臺服務器在執行某一段代碼時保證只有一臺服務器執行。
簡單來說: ??現在的業務應用通常都是微服務架構,這也意味著一個應用會部署多個進程,那么多個進程如果需要修改數據庫中的同一行記錄時,為了避免操作亂序導致數據錯誤,此時就需要引入分布式鎖解決問題。
為了保證分布式鎖的可用性,至少要確保鎖的實現要同時滿足以下幾點:
- 互斥性。在任何時刻,保證只有一個客戶端持有鎖。
- 不能出現死鎖。如果在一個客戶端持有鎖的期間,這個客戶端崩潰了,也要保證后續的其他客戶端可以上鎖。
- 保證上鎖和解鎖都是同一個客戶端。
一般來說,實現分布式鎖的方式有以下幾種:
對 redis 來說注意三點,對 key 的加鎖,如果請求未完成對快要過期的 key 的續期,請求完成后 key 的解鎖。防止并發環境下被讀取的一個 key 可能被多個請求修改,造成無效操作,資源浪費的情況。
五、redis 總結
-
redis 可以做為 mysql 的前置緩存數據庫,redis 與 mysql 對接的方式需要配置線程池,需要定義后端 mysql 的位置( IP + port +sock 文件的位置)
-
redis 基礎功能:用于內存/緩存的快速存儲(讀?。?/p>
-
實現的方式:
默認將數據存儲在內存/緩存中 具有豐富的數據類型:string list hash set && order set 等 重要數據持久化的功能,持久化的方式:AOF RDB
單線程模式 -> 速度快的原因之一:Epoll + I/O 復用(cluster 中的 slots 哈希槽可以充當數據讀、取的索引)
- redis 中的算法:
LRU:淘汰策略1) 緩存中的數據進行隨機淘汰2) 緩存中被設置了過期時間的數據進行隨機淘汰3) 緩存中被設置了過期時間的數據,進行惰性刪除(僅當訪問到的數據過期了,才會刪除)4) 當數據持續存儲過程中內存將滿,會在設置了過期時間的數據中進行近期淘汰 令牌桶 + 漏桶算法:限流 Raft:選舉機制,用于選舉新的主節點
- redis 緩存高熱數據的機制
高熱數據:命中次數高的數據 指定提高緩存內數據的命中數,最直接的可以刷腳本,訪問這些數據
六、系統優化
1. 單例服務器,服務器本身優化
硬件資源選擇(系統五大資源)
- 磁盤 固態盤 SCSI(硬件磁盤陣列)
- 服務器內存條選擇(本地服務器和云服務器)
- CPU 核數選擇
- 網絡網卡(本地服務器和云服務器),需要考慮負載壓力下的網絡流量 QPS
- 服務器選型(麒麟、曉龍、浪潮英信、華為、華三、戴爾(類型:刀片、塔式、機柜))
以上需要計算費用成本,還需要考慮到該服務器上的服務在運行時消耗的性能比例(需要預留給系統一部分資源)
服務本身環境的選擇
-
操作系統選擇 linux 發行版:centos ubuntu redhat server debian alphon mac SUSE(PS:虛擬化 KVM XEN FUFE)
-
基于操作系統,依賴環境。選擇最小化安裝還是指定操作系統版本的安裝 + 指定內核版本。軟件是否有依賴(例如:tomcat 需要 JDK,編譯需要 gcc gcc-c++ pcre …)
-
軟件資源優化 五大負載+內核優化(TCP協議相關、隊列相關、路由轉發、重定向、端口、文件打開數、系統的軟硬限制等)
2. 單例服務器應用服務本身優化
以 redis 為例
首先從啟動讀取的恢復文件來看,基于AOF需要開啟 AOF功能(RDB 默認)
- RDB 中 save M N 觸發周期的選擇判定,這會影響到磁盤資源的使用
- AOF 中選擇合適的 syncwrite 同步寫入磁盤的策略 everysecond
使用過程中,需要考慮到的是內存的使用量( OOM )
- 內存淘汰策略:惰性淘汰+定期刪除,禁止淘汰+定期刪除。根據情況選擇合適的淘汰策略(配置文件中定義)。
持久化方向
持久化的功能在保證數據完整性的同時,依然會持續性的對磁盤產生存儲壓力(壓力來源于 AOF 和 RDB 生成的數據文件,AOF 和 RDB 的日志文件)。
- 數據/日志文件的定期歸檔
- 日志文件的分割(保存在日志中心)
- 共享存儲 NFS GFS fastDFS
redis主進程
- 可以使用兩個 redis 主進程配合實現備份冗余,提高抗高并發的能力
推薦學習:redis