哨兵模式
自動選取主機的模式。
概述
主從切換技術的方法是:當主服務器宕機后,需要手動把一臺從服務器切換為主服務器,這就需要人工干預,費事費力,還會造成段時間內服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。Redis從2.8開始正式提供了Sentinel(哨兵)架構來解決這個問題。
謀朝篡位的自動版,能夠后臺監控主機是否故障,如果故障了根據投票數自動將從庫轉換為主庫。
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的進程,作為進程,它會獨立運行。其原理是哨兵通過發送命令,等待Redis服務器響應,從而監控運行的多個Redis實例。
單機哨兵
作用?
- 通過發送命令,讓Redis服務器返回監控其運行狀態,包括主服務器和從服務器。
- 當哨兵監測到master宕機,會自動將slave切換成master,然后通過發布訂閱模式通知其他的從服務器,修改配置文件,讓它們切換主機。?
然而一個哨兵進程對Redis服務器進行監控,可能會出現問題,為此,我們可以使用多個哨兵進行監控。各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。?
?假設主服務器宕機,哨兵1先檢測到這個結果,系統并不會馬上進行failover過程,僅僅是哨兵1主觀的認為主服務器不可用,這個現象成為主觀下線。當后面的哨兵也檢測到主服務器不可用,并且數量達到一定值時,那么哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行failover[故障轉移]操作。切換成功后,就會通過發布訂閱模式,讓各個哨兵把自己監控的從服務器實現切換主機,這個過程稱為客觀下線.
測試?
在一主二從的狀態下配置哨兵。
要新建一個redis容器來做這個東西。
新建一個sentinel.conf配置文件如下。
這個配置文件在容器里面的位置是/etc/redis/sentinel.conf,和/etc/redis/redis.conf配置文件在同一個目錄下。
所以這里要先新建好對應映射文件目錄。
在之前的基礎上新加一條
touch /docker/redis/conf/sentinel.conf
然后準備好對應的哨兵配置文件。
哨兵配置文件
bind 0.0.0.0
# 端口號
port 26379
# 關閉保護模式
protected-mode no
# 開啟后臺運行,這里哨兵的后臺運行也會和docker的后臺運行沖突
daemonize no
#日志
logfile "/data/sentinel.log"# 配置監聽的主服務器 sentinel monitor代表監控,myredis代表服務器名稱 1表示有一個哨兵,并且只要有一個哨兵認為主機不可用就會進行failover操作
sentinel monitor myredis 127.0.0.1 6380 1# sentinel auth-pass定義服務的密碼,myredis是服務名稱,123456是密碼
sentinel auth-pass myredis 123456# 設置主機多少秒無應答,就認為下線
sentinel down-after-milliseconds myredis 30000# 主備切換時,最多有幾個slave同時對新的redis進行同步,默認是1
sentinel parallel-syncs myredis 1# 故障轉移
sentinel failover-timeout myredis 180000
?啟動哨兵
重新創建一個新的redis容器并啟動哨兵服務服務。
--privileged=true根據情況選擇是否添加。?
docker run -itd --restart=always -p 26379:26379 -v /docker/redis/conf/sentinel.conf:/etc/redis/sentinel.conf --name redis_st redis redis-sentinel /etc/redis/sentinel.conf
啟動完成之后是可以看見有提示的。
無法真正重選主機?
但是在我嘗試掛掉主機去重新選舉時問題出現了。這里選來選去都是舊的主機。??
無法切換,有幾種情況:
1-redis保護模式開啟了
2-端口沒有放開;
3-master密碼和從密碼不一致。
4-master節點的redis.conf沒有添加masterauth
處理方法:
首先配置文件都要修改如下。
所有的redis配置文件都要改,以及哨兵的那個配置文件也要改。
bind 0.0.0.0
protected-mode no
?master密碼和從密碼不一樣
在哨兵配置的時候只配置了master的密碼, 加入master掛了,哨兵會拿著master的密碼去訪問從機。所以密碼應該設置一樣。
另外也要在matser節點中設置masterauth,否則會無法成為xinmaster節點的從節點。
真正的解決方案(docker部署集群的要點)
沒錯,上面的問題都不是我的問題,我真正的問題在這里。
因為我用的是docker進行redis集群的部署,我主機和從機開了三個docker。
映射關系分別是
6380->6379
6381->6379
6382->6379
這里的三個6379都是docker內的端口號。但是在哨兵那里看過去都是6379,但是實際上不應該是這樣,像下圖這里就是一個錯誤示范,也是用docker部署的錯誤點。
?哨兵在從機里面選舉時會按照6379這個端口訪問,但是實際上我的兩個從機在外部的端口應該是6381和6382才對,所以我前面才一直訪問不到。
現在只要將docker內redis服務的端口號和外部映射的端口號一一對應開即可。
6380->6380
6381->6381
6382->6382
并且這里是要將redis服務的端口改成6380,6381和6382的的才可以。
測試成功
然后等到我原本的master重新上線時就只能跟隨新產生的master了。(哨兵模式的規則)
?優點和缺點
優點
1、哨兵集群,基于主從復制模式,所有的主從配置優點,它全有
2、主從可以切換,故障可以轉移,系統的可用性就會更好
3、哨兵模式就是主從模式的升級,手動到自動,更加健壯!
缺點
1、Redis 不好啊在線擴容的,集群容量一旦到達上限,在線擴容就十分麻煩!
2、實現哨兵模式的配置其實是很麻煩的,里面有很多選擇。
哨兵模式的配置文件
下面這里還不是完整的配置,如果要做哨兵集群還要涉及到更多的東西。
還有什么保護模式,后臺運行,日志文件等等配置,下面都沒有列出來。
# Example sentinel.conf# 1、哨兵sentinel 實例運行的端口 默認26379
port 26379# 2、 哨兵 sentinel 的工作目錄
dir "/usr/local/bin"# 3、哨兵sentinel監控的redis主節點 host port
# - master-name 可以自己對 主節點 明明
# - quorum 配置多少個sentinel 哨兵認為master 主節點失聯,那么這個時候就客觀的認為失戀了
# sentinel monitor master-name host port quorum
sentinel monitor myredis 127.0.0.1 7371 1# 4、在Redis實例中開啟了密碼,這時,所有連接Redis的客戶端都需要密碼
# - 設置了哨兵sentinel 連接上主從的密碼,注意必須設置一樣的驗證碼
# sentinel auth-pass master-name password
sentinel auth-pass myredis 123456# 5、指定多少毫秒后 主節點沒有回答哨兵sentinel 此時 哨兵主觀上認為主節點離線 默認30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds myredis 30000# 6、這個配置指定了在發生failover 主備切換時最多可以由多少個slave同時對新的master進行同步- 這個數字越小,完成failover 所需的時間越長- 這個數字越大,就意味著越多的slave 因為repkication 而不可用- 可以通過將這個值設為 1 來保證每次只有一個slave 處于不能處理命令請求的狀態
# sentinel parallel-syncs <master-name> <numreplicas>
sentinel parallel-syncs mymaster 1# 7、故障轉移的時間 failover-timeout 可以用一下這些方面同一個sentinel 對同一個master 兩次failover 之間的間隔時間當想要取消一個正在進行的fai1over所需要的時間,直到slave 被糾正為向正確的master那里同步數據時當進行fai1over時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個超時,s1aves依然會被正確配置為指向 master,但是就不按para11e1-syncs所配置的規則來了
# sentinel failover-timeout <master-name> <milliseconds> 默認三分鐘
sentinel failover-timeout mymaster 180000# 8、配置當某一個事件發生時需要執行的腳本,可以通過腳本來通知管理員,例如當系統運行不正常時,發送郵件通知相關人員- 對于腳本的運行結果有以下規則:1.若腳本執行后返回1,那么該腳本稍后會重新執行,重復次數默認為102.若腳本執行后返回2,或者是比2更高的返回值,腳本將不會執行3.若腳本在執行過程中由于收到系統中斷信號被終止了,則同返回值1的時候的相同4.一個腳本執行的最大時間為60s,如果超過這個時間,腳本將會被一個SIGKILL信號終止,重新執行- 通知型腳本:當sentine1有任何警告級別的事件發生時(比如說re dis實例的主觀失效和客觀失效等等),將會去調用這個腳本,這時這個腳本應該通過郵件,SMS等方式去通知系統管理員關于系統不正常運行行的信息。調用該腳本時,將傳給腳本兩個參數,一個是事件的類型,一個是事件的描述。如果sentine1.conf配置文件中配置了這個腳本路路徑,那么必須保證這個腳本存在于這個路徑,并且是可執行的,否則 sentine1無法正常啟動成功。
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh# 9、客戶端重新配置主節點參數腳本- 當一個master 發生改變時,這個腳本就會被調用,通知相關的客戶端關于 master 地址已經發生改變- 一下參數將會在調用腳本的時候傳給腳本1. <master-name> <role> <state> <from-ip><from-port><to-ip><to-port>2. 目前<state>總是"failover”3. <ro1e>是"leader"或者"observer”中的一個。4. 參數from-ip,from-port,to-ip,to-port是用來和舊的master和新的master(即舊的s1ave)通信的5. 這個腳本應該是通用的,能被多次調用,不是針對性的
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
Redis緩存的使用,極大的提升了應用程序的性能和效率,特別是數據查詢方面。但同時,它也帶來了一些問題。其中,最要害的問題,就是數據的一致性問題,從嚴格意義上講,這個問題無解。如果對數據的一致性要求很高,那么就不能使用緩存。
另外的一些典型問題就是,緩存穿透、緩存雪崩和緩存擊穿。目前,業界也都有比較流行的解決方案。
?
緩存穿透(查不到)
概念
緩存穿透的概念很簡單,用戶想要查詢一個數據,發現redis內存數據庫沒有,也就是緩存沒有命中,于是向持久層數據庫查詢。發現也沒有,于是本次查詢失敗。當用戶很多的時候,緩存都沒有命中(秒殺服務),于是都去請求了持久層數據庫。這會給持久層數據庫造成很大的壓力,這時候就相當于出現了緩存穿透。
解決方案
布隆過濾器
布隆過濾器是一種數據結構,對所有可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則丟棄,從而避免了對底層存儲系統的查詢壓力。
?緩存空對象
當存儲層不命中后,即使返回的空對象也將其緩存起來,同時會設置一個過期時間,之后再訪問這個數據將會從緩存中獲取,保護了后端數據源;
?問題:
1、如果空值能夠被緩存起來,這就意味著緩存需要更多的空間存儲更多的鍵,因為這當中可能會有很多的空值的鍵
2、即使對空值設置了過期時間,還是會存在緩存層和存儲層的數據會有一段時間窗口的不一致,這對于需要保持一致性的業務會有影響。
緩存擊穿(量過大,緩存過期)
概述
這里需要注意和緩存擊穿的區別,緩存擊穿,是指一個key非常熱點,在不停的扛著大并發,大并發集中對這一個點進行訪問,當這個key在失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。
當某個key在過期的瞬間,有大量的請求并發訪問,這類數據一般是熱點數據,由于緩存過期,會同時訪問數據庫來查詢最新數據,并且回寫緩存,會導使數據庫瞬間壓力過大
解決方案
設置熱點數據永不過期
從緩存層面來看,沒有設置過期時間,所以不會出現熱點 key 過期后產生的問題。
加互斥鎖
分布式鎖:使用分布式鎖,保證對于每個key同時只有一個線程去查詢后端服務,其他線程沒有獲得分布式鎖的權限,因此只需要等待即可。這種方式將高并發的壓力轉移到了分布式鎖,因此對分布式鎖的考驗很大。
緩存雪崩
概念
緩存雪崩,是指在某一個時間段,緩存集中過期失效。Redis宕機。
立生雪崩的原因之一,比如在寫本文的時候,馬上就要到雙十二零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了緩存,假設緩存一個小時。那么到了凌晨一點鐘的時候,這批商品的緩存就都過期了。而對這批商品的訪問查詢,都落到了數據庫上,對于數據庫而言,就會產生周期性的壓力波峰。于是所有的請求都會達到存儲層,存儲層的調用量會暴增,造成存儲層也會掛掉的情況。
其實集中過期,倒不是非常致命,比較致命的緩存雪崩,是緩存服務器某個節點宕機或斷網。因為自然形成的緩存雪崩,一定是在某個時間段集中創建緩存,這個時候,數據庫也是可以頂住壓力的。無非就是對數據庫產生周期性的壓力而已。而緩存服務節點的宕機,對數據庫服務器造成的壓力是不可預知的,很有可能瞬間就把數據庫壓垮。
解決方案
redis高可用
這個思想的含義是,既然redis有可能掛掉,那多增設幾臺redis,這樣一臺掛掉之后其他的還可以繼續工作,其實就是搭建的集群。(異地多服)
限流降級
這個解決方案的思想是,在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。
數據預熱
數據加熱的含義就是在正式部署之前,我先把可能的數據先預先訪問一遍,這樣部分可能大量訪問的數據就會加載到緩存中。在即將發生大并發訪問前手動觸發加載緩存不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻.