Redis 實戰 —— 07. 復制、處理故障、事務及性能優化


復制簡介 P61

關系型數據庫通常會使用一個主服務器 (master) 向多個從服務器 (slave) 發送更新,並使用從服務器來處理所有讀請求。 Redis 也采用了同樣的方法實現自己的復制特性,並將其用作擴展性能的一種手段。 P69

在接收到主服務器發送的數據初始副本 (initial copy of the data) 之后,客戶端每次向主服務器進行寫入時,從服務器都會實時地得到更新。 P69

復制 P62

對於一個正在運行的 Redis 服務器,用戶可以通過發送 SLAVEOF NO ONE 命令來讓服務器終止復制操作,不再接受主服務器的數據更新;也可以通過發送 SLAVEOF host port 命令來讓服務器開始復制一個新的主服務器。 P69

配置選項
# 設置本機為指定服務器的從服務器
#
# slaveof <master-host> <master-port>

# 當主服務器設置了密碼保護時(用 requirepass 指定的密碼)
# 從服務器服務連接主服務器需要設置相應的密碼
#
# masterauth <master-password>


# 當從服務器 與主服務器失去連接 或者 正在進行復制 時
# yes: 從服務器會繼續響應客戶端的請求(默認 yes)
# no: 除了 INFO 和 SLAVOF 命令之外的任何請求都會
#     返回一個錯誤 "SYNC with master in progress"
#
slave-serve-stale-data yes

# 從服務器每隔一定時間會向主服務器發送 ping
# 默認 10 秒
#
# repl-ping-slave-period 10

# ping 回復 或 主服務器批量數據傳輸 超時時長
# 默認 60 秒
# 確保 repl-timeout 大於 repl-ping-slave-period
#
# repl-timeout 60
從服務器連接主服務器時的步驟 P70
步驟 主服務器操作 從服務器操作
1 (等待命令進入) 連接(或者重連)主服務器,發送 SYNC 命令
2 開始執行 BGSAVE ,並使用緩沖區記錄 BGSAVE 之后執行所有寫命令 根據配置選項 (slave-serve-stale-data) 來決定是繼續使用現有的數據(如果有的話)來處理客戶端的命令請求,還是向客戶端返回錯誤
3 BGSAVE 執行完畢,向從服務器發送快照文件,並在發送期間繼續使用緩沖區記錄被執行的寫命令 丟棄所有舊數據(如果有的話),開始載入主服務器發來的快照文件
4 快照文件發送完畢,開始向從服務器發送存儲在緩沖區里面的寫命令 完成對快照文件的解釋操作,像往常一樣開始接受命令請求
5 緩沖區存儲的寫命令發送完畢;從現在開始,每執行一個寫命令,就向從服務器發送相同的寫命令 執行主服務器發來的所有存儲在緩沖區里面的寫命令;並從現在開始,接受並執行主服務器傳來的每個寫命令

在實際中最好讓主服務器只使用 50% ~ 65% 的內存,留下 30% ~ 45% 的內存用於執行 BGSAVE 命令和創建記錄寫命令的緩沖區。 P70

從服務器在進行同步時,會清空自己的所有數據。 P70

Redis 不支持主主復制 (master-master replication) P71

當一個從服務器連接一個已有的主服務器時,有時可以重用已有的快照文件: P71

  • 步驟 3 尚未執行:所有從服務器都會接收到相同的快照文件和相同的緩沖區寫命令
  • 步驟 3 正在執行或已經執行完畢:當主服務器與比較早進行連接的從服務器執行完復制所需的 5 個步驟之后,主服務器會與新連接的從服務器執行一次新的步驟 1 至步驟 5
主從鏈 P71

Redis 的主服務器和從服務器沒有什么特別不同的地方,所以從服務器也可以擁有自己的從服務器,並由此形成主從鏈 (master/slave chaining) 。 P71

不過,如果從服務器 X 擁有從服務器 Y ,那么當從服務器 X 在執行步驟 4 時,它將斷開與從服務器 Y 的連接,導致從服務器 Y 需要重新連接並重新同步。 P71

當讀請求比寫請求重要,且讀請求的數量遠遠超過一台 Redis 服務器可以處理的范圍時,就需要添加新的從服務器來處理讀請求。隨着負載不斷上升,主服務器可能會無法快速地更新所有從服務器,或者因為重新連接和重新同步從服務器而導致系統超載。為了緩解這個問題,可以創建一個由 Redis 主從節點 (master/slave node) 組成的中間層來分擔主服務器的復制工作。 P71

通過同時使用復制和 AOF 持久化,用戶可以增強 Redis 對於系統崩潰的抵抗能力。 P73

處理系統故障

驗證快照文件和 AOF 文件

redis-check-aof [--fix] <file.aof> 可以檢查 AOF 文件,並且可以進行修復:將第一個出錯命令(大部分情況下在文件末尾)及之后的所有命令刪除。 P74

redis-check-dump <dump.rdb> 可以檢查快照文件。快照文件目前無法進行修復,因為快照文件本身進行了壓縮。 P74

事務

Redis 事務的作用: P76

  • 防止數據出錯
  • 在某些情況下提升性能。利用事務一次性發送多個命令,然后等待所有回復出現實現流水線 (pipeline)。通過減少客戶端與 Redis 服務器之間的網絡通信次數來提升 Redis 在執行多個命令時的性能。

關系數據庫事務與 Redis 事務的區別: P76

  • 關系數據庫:先向數據庫服務器發送 BEGIN ,然后執行各個相互一致 (consistent) 的讀寫操作,最后可以選擇發送 COMMIT 來確認之前的修改,或者發送 ROLLBACK 來放棄之前的修改。
  • Redis :以特殊命令 MULTI 開始,然后傳入多個命令,最后以 EXEC 結束,並依次執行傳入的命令。Redis 事務不能以一致的形式讀取數據,使得某一類型的問題難以解決,且無法實現二階段提交。

通過使用 WATCH, MULTI/EXEC, UNWATCH/DISCARD 等命令,程序可以在執行某些重要操作時,通過確保自己正在使用的數據沒有發生變化來避免出錯。 P78

  • WATCH: 使用 WATCh 對鍵進行監視之后,直到用戶執行 EXEC 的這段時間里面,如果有其他客戶端搶先對任何被監視的鍵進行了替換、更新或刪除等操作,那么當用戶嘗試執行 EXEC 時,事務將失敗並返回一個錯誤。(之后用戶可選擇重試事務或者放棄事務)
  • UNWATCH: 可以在 WATCH 執行之后、 MULTI 執行之前對連接進行重置 (reset)
  • DISCARD: 可以在 MULTI 執行之后、 EXEC 執行之前對連接進行重置,即取消 WATCH 並清空所有已入隊命令

為什么 Redis 沒有實現典型的加鎖功能? P82

  • 加鎖是悲觀鎖,持有鎖的客戶端運行越慢,等待解鎖的客戶端被阻塞的時間越長
  • WATCH 是樂觀鎖,客戶端不必等待取得鎖,只需要在事務執行失敗時重試即可,樂觀鎖可以提高並發能力

非事務型流水線 (non-transactional pipeline)

對於無需事務的大量操作可以使用非事務型流水線,可以避免事務消耗資源。

Python 中通過修改入參即可將事務改為非事務型流水線,而 Go 中根據具體框架的不同,可能需要手動封裝流水線的處理邏輯。

性能優化

要對 Redis 的性能進行優化,首先需要弄清楚各種類型的 Redis 命令能跑多塊,而這一點可以通過調用 Redis 附帶的性能測試程序 redis-benchmark 得知。 P85

切記不要將輸出結果看作是應用程序的實際性能,因為 redis-benchmark 不會處理執行命令所獲得的命令回復,所以它節約了大量用於對命令回復進行語法分析的時間。 P86

可能影響性能的原因 P86
  • 未使用流水線:可視情況適當使用流水線
  • 對於每個命令或每組命令都創建了新的連接:使用連接池重用 Redis 連接
  • Redis 的數據結構或命令不合理(value 非常大,使用 keys, hgetall 等):優化數據結構和命令

本文首發於公眾號:滿賦諸機(點擊查看原文) 開源在 GitHub :reading-notes/redis-in-action


免責聲明!

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



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