參考
圖靈課堂
https://zhuanlan.zhihu.com/p/443951927
https://blog.csdn.net/weixin_37548768/article/details/124538778?spm=1001.2014.3001.5502
https://www.runoob.com/redis/redis-transactions.html
redis支援持久化到磁碟,這樣可用進一步保證資料的完整性。
redis持久化分為兩種,一個是RDB,一個是AOF。
RDB快照(snapshot)
RDB是Redis的一種資料持久化到磁碟的策略,是一種以記憶體快照形式儲存Redis資料的方式。所謂快照,就是把某一時刻的狀態以檔案的形式進行全量備份到磁碟,這個快照檔案就稱為RDB檔案,其中RDB是Redis DataBase的縮寫。
bgsave的寫時複製(COW)機制
save和bgsave的對比
命令 | save | bgsave |
IO型別 | 同步 | 非同步 |
是否阻塞redis其它命令 | 是 |
否(在生成子程序執行呼叫fork函
數時會有短暫阻塞)
|
複雜度 | O(n) | O(n) |
優點 | 不會消耗額外記憶體 | 不阻塞客戶端命令 |
缺點 | 阻塞客戶端命令 |
需要fork子程序,消耗記憶體
|
AOF(append-only file)
3
$3
set
$6
tuling
$3
888
*3
$9
PEXPIREAT
$6
tuling
$13
1604249786301
- 1 appendfsync always:每次有新命令追加到 AOF 檔案時就執行一次 fsync ,非常慢,也非常安全。
- 2 appendfsync everysec:每秒 fsync 一次,足夠快,並且在故障時只會丟失 1 秒鐘的資料。
- 3 appendfsync no:從不 fsync ,將資料交給作業系統來處理。更快,也更不安全的選擇。
aof重寫
生產環境可以都啟用,redis啟動時如果既有rdb檔案又有aof檔案則優先選擇aof檔案恢復資料,因為aof一般來說資料更全一點。
混合持久化
Redis資料備份策略:
- 1. 寫crontab定時排程指令碼,每小時都copy一份rdb或aof的備份到一個目錄中去,僅僅保留最近48小時的備份
- 2. 每天都保留一份當日的資料備份到一個目錄中去,可以保留最近1個月的備份
- 3. 每次copy備份的時候,都把太舊的備份給刪了
- 4. 每天晚上將當前機器上的備份複製一份到其他機器上,以防機器損壞
Redis主從架構
1、複製一份redis.conf檔案 2、將相關配置修改為如下值: port 6380 pidfile /var/run/redis_6380.pid # 把pid程序號寫入pidfile配置的檔案 logfile "6380.log" dir /usr/local/redis-5.0.3/data/6380 # 指定資料存放目錄
# 需要註釋掉bind # bind 127.0.0.1(bind繫結的是自己機器網路卡的ip,如果有多塊網路卡可以配多個ip,代表允許客戶端透過機器的哪些網路卡ip去訪問,內網一般可以不配置bind,註釋掉即可) 3、配置主從複製 replicaof 本機的IP 6379 # 從本機6379的redis例項複製資料,Redis 5.0之前使用slaveof replica-read-only yes # 配置從節點只讀 4、啟動從節點 redis-server redis.conf # redis.conf檔案務必用你複製並修改了之後的redis.conf檔案 5、連線從節點 redis-cli -p 6380 6、測試在6379例項上寫資料,6380例項是否能及時同步新修改資料 7、可以自己再配置一個6381的從節點
Redis主從工作原理
資料部分複製:斷點續傳
主從複製風暴
如果主節點掛載的從節點太多,那麼就可能會導致主節點複製壓力太大,從而影響對外部的服務。降低redis的可用性。這就是主從複製風暴。為了避免這樣的情況發生,可以將從節點掛載到從節點上,形成分層的結構。主節點直連的從節點數量降低。
主從架構的優缺點
Redis的主從架構(Master-Slave)是一種常用的資料複製和擴充套件策略,其優缺點主要體現在以下幾個方面:
優點:
- 資料備份和容災:主從架構提供了資料的備份功能,從節點可以實時或非同步地複製主節點的資料,確保資料的可靠性。當主節點發生故障時,從節點可以迅速切換為主節點,保證服務的連續性。
- 讀寫分離:主節點通常負責寫操作,而從節點則負責讀操作。這種讀寫分離的策略可以顯著提高系統的效能,因為讀操作通常比寫操作更頻繁,而多個從節點可以並行處理讀請求。
- 擴充套件性:主從架構允許透過增加從節點的數量來擴充套件系統的讀效能。當讀請求量增加時,可以新增更多的從節點來分擔讀壓力。
- 靈活性:主從架構支援多種同步策略,如全量同步和增量同步。全量同步適用於主從節點之間資料量差異較大的情況,而增量同步則適用於資料量差異較小的情況。
缺點:
- 可靠性問題:雖然主從架構提供了資料備份的功能,但仍然存在可靠性問題。如果主節點和從節點同時當機,那麼整個系統將無法提供服務。此外,如果主節點在當機前有部分資料未能及時同步到從節點,那麼在切換主節點後可能會導致資料不一致的問題。如果主節點異常,從節點並不能主動頂上去,還需要人工干預。
- 複雜性和管理成本:主從架構的配置和管理相對複雜,需要確保主節點和從節點之間的網路連線穩定可靠,並需要定期監控主從節點的狀態和效能。此外,當需要新增或刪除從節點時,也需要進行額外的配置和管理操作。
- 延遲問題:由於從節點需要複製主節點的資料,因此存在一定的延遲。這種延遲可能會影響系統的實時性和一致性。特別是當主節點的寫操作非常頻繁時,從節點的延遲可能會更加嚴重。
- 容量和效能瓶頸:雖然從節點可以擴充套件系統的讀效能,但整個系統的容量和效能仍然受限於主節點的處理能力。如果主節點的處理能力不足,那麼即使新增再多的從節點也無法提高系統的整體效能。
綜上所述,Redis的主從架構具有資料備份、讀寫分離、擴充套件性和靈活性等優點,但也存在可靠性問題、複雜性和管理成本、延遲問題以及容量和效能瓶頸等缺點。因此,在選擇是否使用主從架構時需要根據具體的業務需求和場景進行權衡和決策。
管道(Pipeline)
事務
Redis 事務可以一次執行多個命令, 並且帶有以下三個重要的保證:
- 批次操作在傳送 EXEC 命令前被放入佇列快取。批次操作在傳送 EXEC 命令前被放入佇列快取,並不會被實際執行,也就不存在事務內的查詢要看到事務裡的更新,事務外查詢不能看到。
- 收到 EXEC 命令後進入事務執行,事務中任意命令執行失敗,其餘的命令依然被執行。
- 在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
一個事務從開始到執行會經歷以下三個階段:
- 開始事務。
- 命令入隊。
- 執行事務。
單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行並不是原子性的。
事務可以理解為一個打包的批次執行指令碼,但批次指令並非原子化的操作,中間某條指令的失敗不會導致前面已做指令的回滾,也不會造成後續的指令不做。
命令:
1 | DISCARD 取消事務,放棄執行事務塊內的所有命令。 |
2 | EXEC 執行所有事務塊內的命令。 |
3 | MULTI 標記一個事務塊的開始。 |
4 | UNWATCH 取消 WATCH 命令對所有 key 的監視。 |
5 | WATCH key [key ...] 監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。 |
注意事項:
lua指令碼
哨兵架構
哨兵啟動流程
在Redis哨兵架構中,通常需要先啟動服務節點(主節點和從節點),然後再啟動哨兵節點。
這是因為哨兵節點的作用是監控Redis節點的狀態,並在主節點發生故障時自動將從節點切換為主節點,從而實現自動故障轉移。如果先啟動哨兵節點而沒有服務節點可監控,那麼哨兵節點將無法正常工作。具體來說,啟動Redis哨兵架構的步驟大致如下:
- 配置並啟動Redis服務節點,包括主節點和從節點。
- 配置Redis哨兵,指定要監控的主節點和從節點的資訊。這可以透過配置檔案或命令列引數來完成。
- 啟動Redis哨兵節點。在啟動後,哨兵節點會開始監控指定的Redis節點,並等待故障轉移事件的發生。
需要注意的是,在啟動哨兵節點之前,必須確保主從模式已經正確安裝和配置,並且所有的Redis工作節點都已經正常執行。這是因為哨兵模式依賴於主從模式來監控Redis節點的狀態,並在必要時進行故障轉移。
哨兵搭建過程
1、複製一份sentinel.conf檔案
cp sentinel.conf sentinel-26379.conf
2、將相關配置修改為如下值:
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "26379.log"
dir "/usr/local/redis-5.0.3/data"
# sentinel monitor <master-redis-name> <master-redis-ip> <master-redis-port> <quorum>
# quorum是一個數字,指明當有多少個sentinel認為一個master失效時(值一般為:sentinel總數/2 + 1),master才算真正失效
sentinel monitor mymaster 本機IP 6379 2 # mymaster這個名字隨便取,客戶端訪問時會用到,必須是要和客戶端訪問值一模一樣
3、啟動sentinel哨兵例項
src/redis-sentinel sentinel-26379.conf
4、檢視sentinel的info資訊
src/redis-cli -p 26379
127.0.0.1:26379>info
可以看到Sentinel的info裡已經識別出了redis的主從
5、可以自己再配置兩個sentinel,埠26380和26381,注意上述配置檔案裡的對應數字都要修改
sentinel known-replica mymaster 192.168.0.60 6380 #代表redis主節點的從節點資訊
sentinel known-replica mymaster 192.168.0.60 6381 #代表redis主節點的從節點資訊
sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f #代表感知到的其它哨兵節點
sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6 #代表感知到的其它哨兵節點
當redis主節點如果掛了,哨兵叢集會重新選舉出新的redis主節點,同時會修改所有sentinel節點配置檔案的叢集後設資料資訊,比如6379的redis如果掛了,假設選舉出的新主節點是6380,則sentinel檔案裡的叢集後設資料資訊會變成如下所示:
sentinel known-replica mymaster 192.168.0.60 6379 #代表主節點的從節點資訊
sentinel known-replica mymaster 192.168.0.60 6381 #代表主節點的從節點資訊
sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f #代表感知到的其它哨兵節點
sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6 #代表感知到的其它哨兵節點
sentinel monitor mymaster 192.168.0.60 6380 2
當6379的redis例項再次啟動時,哨兵叢集根據叢集後設資料資訊就可以將6379埠的redis節點作為從節點加入叢集
哨兵架構的優缺點
Redis哨兵(Sentinel)系統是Redis用來實現高可用性和監控的工具,它能夠幫助管理多個Redis伺服器例項,並在出現故障時進行適當的動作,比如自動故障遷移或傳送警告。以下是Redis哨兵架構的一些優缺點:
優點:
1. 高可用性:哨兵系統能夠確保在主Redis例項出現故障時,自動將備用例項提升為新的主例項,以實現服務的持續可用性。
2. 監控:哨兵會不斷地監控Redis例項的健康狀況,包括節點是否可達、是否響應命令等,並在出現問題時發出警告。
3. 故障遷移:當主Redis例項不可用時,哨兵可以根據配置的規則自動將一個從例項轉換為主例項,以實現故障的無縫遷移。
4. 配置靈活:哨兵允許使用者配置多種引數,如選舉超時時間、故障轉移的策略等,以適應不同的業務需求。
5. 支援多資料中心:哨兵支援設定多個哨兵例項,每個例項負責不同的Redis主從叢集,這樣就可以實現跨資料中心的故障轉移能力。
缺點:
1. 複雜性:相對於單例項的Redis,哨兵架構引入了更多的配置和元件,這可能會增加系統的複雜性。
2. 效能開銷:哨兵系統會有一部分的效能開銷,因為它需要監控和維護額外的資訊,並處理故障轉移等邏輯。
3. 多哨兵配置複雜:在複雜的環境中,多個哨兵之間的協調和配置可能會變得複雜,需要仔細規劃。
4. 不支援讀寫分離:哨兵架構不支援傳統的讀寫分離,因為從例項在故障轉移時可能被提升為新的主例項。
5. 資料一致性:在某些複雜的故障轉移情況下,可能會出現短暫的資料不一致問題,雖然Redis支援事務和持久化機制,但在極端情況下仍需注意資料一致性。
總體而言,Redis哨兵系統在提供高可用性和監控功能的同時,也帶來了一定的複雜性和效能考慮。對於需要高可用性的Redis應用場景,哨兵是一個很好的選擇,但在規劃和部署時需要仔細考慮上述優缺點。
同時哨兵架構中,主節點會儲存全部的資料,增加節點只是可以減少訪問併發的壓力,對寫入記憶體壓力來說沒有什麼提升。
哨兵模式下故障轉移過程
在Redis哨兵(Sentinel)模式下,故障轉移是指當主Redis例項因某些原因不可用時,哨兵系統將會觸發一個流程,將一個從例項(Slave)升級為新的主例項(Master),並確保所有從例項跟隨新的主例項。以下是故障轉移的基本流程:
1. **監控狀態**:哨兵系統持續監控Redis主例項和從例項的健康狀態。它透過向例項傳送PING命令並監聽例項的回覆來判斷例項是否健康。
2. **故障檢測**:如果哨兵檢測到主例項不可達或者響應命令出現異常,它將認為主例項出現了故障。
3. **選舉過程**:當哨兵確定主例項不可用時,它將開始一個選舉(Election)過程。選舉過程中,哨兵會嘗試聯絡其他哨兵例項,以確定是否有其他哨兵已經發起了一個有效的選舉。
4. **領導者選舉**:如果哨兵例項在選舉過程中被選為領導者(Leader),它將負責協調故障轉移過程。如果多個哨兵例項同時爭奪領導地位,它們將透過一個基於Redis投票機制的方式決定領導者。
5. **命令複製**:領導者哨兵會從剩餘的從例項中選擇一個例項(通常是具有最高執行序號的例項)作為新的主例項,並透過Redis命令複製協議(REPL)來同步這個例項的記憶體狀態到其他從例項。
6. **更新配置**:一旦新的主例項被選舉出來,哨兵將更新配置,使得其他從例項開始複製新的主例項的資料。這個過程可能包括更新從例項的配置檔案或者直接透過Redis命令來更改從屬關係。
7. **故障轉移完成**:在新的主例項準備好並配置所有從例項之後,故障轉移過程完成。此時,哨兵會向客戶端傳送訊息,告知它們新的主例項的位置,客戶端可以根據這個資訊更新它們的連線。
8. **後續處理**:舊的故障的主例項在恢復後,可能會被配置為從例項並開始複製新的主例項的資料,或者根據具體情況被移除或重新配置。
整個故障轉移過程是由哨兵系統自動完成的,不需要人工干預。但是,為了確保故障轉移的順利進行,需要正確配置哨兵系統,包括指定主例項和從例項、設定選舉超時時間、配置故障轉移策略等。
故障轉移中如何保證資料的一致性
在Redis哨兵(Sentinel)模式的故障轉移過程中,確保資料一致性是一個重要的考慮點。以下是一些措施和機制,用於確保在故障轉移過程中資料的一致性:
1. **寫入確認**:在故障轉移過程中,新的主例項在接替舊的主例項之前,會等待一些寫入操作被確認。這可以透過配置引數`redis-sentinel min-slaves-to-write`來實現,它指定了一個最小數量的從例項必須處於“線上”(UP)狀態,主例項才能執行寫操作。
2. **複製偏移量**:Redis使用複製偏移量(replication offset)來跟蹤主例項和從例項之間資料同步的位置。在故障轉移過程中,新的主例項會等待直到它的複製偏移量追趕上其他從例項,確保從例項有最新的一致性資料。
3. **斷線重連**:在故障轉移後,從例項會嘗試與新的主例項重新建立連線,並繼續同步資料。如果從例項在一定時間內無法連線到新的主例項,它會嘗試重新連線到舊的 主例項(如果舊的 主例項恢復了),這樣可以避免資料不一致。
4. **配置更新**:故障轉移後,從例項會根據新的主例項資訊更新它們的配置,確保所有從例項都知道新的主例項的位置。
5. **Sentinel監控**:哨兵系統會繼續監控所有例項的健康狀態,並在檢測到任何不一致性時採取行動。例如,如果一個從例項落後於新的主例項太多,哨兵可能會嘗試將該從例項從舊的 主例項那裡重新同步資料。
6. **客戶端重連**:客戶端應用需要監聽主例項的變化,並在必要時更新它們連線的主例項。通常,這可以透過使用Redis客戶端的哨兵支援來實現,客戶端會自動重連到新的主例項。
7. **持久化機制**:Redis提供了資料持久化機制,如RDB快照和AOF日誌,這些機制可以幫助在故障轉移後恢復資料。確保在故障轉移前有最新的快照或AOF日誌重做,可以減少資料不一致的風險。
透過上述機制,Redis哨兵系統在故障轉移過程中儘量保證了資料的一致性。然而,在實際操作中,特別是在故障轉移的初期階段,可能會存在短暫的資料不一致。因此,設計系統時應考慮這種短暫的不一致性,並在必要時實施額外的資料一致性保障措施。
請推薦一些確保資料一致性的最佳實踐。
確保資料一致性是分散式系統設計中的一個重要方面,特別是在像Redis這樣的資料儲存系統中。以下是一些確保資料一致性的最佳實踐:
1. **使用同步複製**:在Redis中,確保使用同步複製(sync replication)模式,這樣主例項在寫入資料後,會等待從例項確認接收到了這些資料,然後再回復客戶端。這可以透過設定`replica-ping-timeout`和`replica-offset-threshold`引數來調整。
2. **最小同步偏移量**:透過設定`min-slaves-to-write`引數,可以指定主例項需要至少有一定數量的從例項處於線上狀態並且同步偏移量小於閾值時,才能執行寫操作。這樣可以確保主例項寫入的資料被至少一個從例項確認。
3. **使用Redis事務**:雖然Redis事務不能像關係型資料庫那樣保證原子性和一致性,但在執行涉及多個操作的任務時,使用`MULTI`、`EXEC`、`DISCARD`和`WATCH`命令可以幫助避免部分寫入問題。
4. **使用Lua指令碼**:對於複雜的操作,可以使用Lua指令碼在Redis中執行,這樣可以確保多個步驟要麼全部成功,要麼全部失敗,從而保持資料的一致性。
5. **快照和持久化**:定期建立RDB快照和/或使用AOF日誌記錄所有的寫操作,可以幫助在系統故障時恢復資料。確保在發生故障轉移之前有最新的快照或AOF日誌重做。
6. **哨兵和叢集配置**:正確配置Redis哨兵,確保它在檢測到故障時可以正確地執行故障轉移。同時,如果使用Redis叢集,確保叢集模式下的資料分佈和複製配置是合理的。
7. **監控和報警**:實施監控系統來跟蹤Redis例項的健康狀態和效能指標。在檢測到任何異常時,確保有報警系統通知運維人員。
8. **分散式鎖或事務管理**:在需要原子性操作的場景中,可以使用分散式鎖或者其他事務管理工具(如Redis事務或基於Redis的分散式鎖庫)來確保資料一致性。
9. **客戶端重試機制**:在客戶端實現重試機制,當遇到資料不一致或服務不可用時,可以嘗試重新連線或重新執行操作。
10. **最小化資料不一致視窗**:在設計系統時,儘量減少資料不一致性的視窗時間。例如,使用分散式訊息佇列或其他佇列技術來緩衝寫入操作,直到資料一致性得到保證。
11. **定期審查和測試**:定期審查系統的資料一致性措施,並進行故障轉移和恢復流程的測試,以確保在實際故障發生時,系統能夠按照預期工作。
這些實踐可以幫助設計更加健壯和一致性的Redis應用程式,但需要注意的是,在分散式系統中完全消除資料不一致性是不可能的,關鍵是要在可用性和一致性之間找到合適的平衡點。