系統怎麼配置讀寫分離
❶ Redis早期的主從架構原理分析,早期如何實現讀寫分離的
基於主從復制架構,實現讀寫分離,redis slave node節點只讀,默認開啟配置:slave-read-only yes。開啟了只讀的節點redis slave node,會拒絕所有寫操作,這樣可以強制搭建成讀寫分離的架構。
(1)redis採用非同步方式復制數據到slave節點。
(2)一個master node是可以配置多個slave node的。
(3)slave node也可以連接其他的slave node。
(4)slave node做復制的時候,是不會block master node的正常工作的。
(5)slave node在做復制的時候,也不會block對自己的查詢操作,它會用舊的數據集來提供服務; 但是復制完成的時候,需要刪除舊數據集,載入新數據集,這個時候就會暫停對外服務了。
(6)slave node主要用來進行橫向擴容,做讀寫分離,擴容的slave node可以提高讀的吞吐量。
如果採用了主從架構,那麼建議必須開啟master node的持久化!不建議用slave node作為master node的數據熱備,因為那樣的話,如果你關掉master的持久化,可能在master宕機重啟的時候數據是空的,然後可能一經過復制,salve node數據也丟了。
(1)當啟動一個slave node的時候,它會發送一個 PSYNC 命令給master node。
(2)如果這是slave node 重新連接 master node,那麼master node僅僅會 復制給slave部分缺少的數據 ,否則如果是slave node 第一次連接 master node,那麼會觸發一次 full resynchronization ,master會啟動一個後台線程,開始生成一份RDB快照文件,同時還會將從客戶端收到的所有寫命令 緩存在內存中 。RDB文件生成完畢之後,master會先將這個RDB發送給slave,slave會先寫入本地磁碟,然後再從本地磁碟載入到內存中。然後master會將內存中 緩存的寫命令 發送給slave,slave也會同步這些數據。
(3)slave node如果跟master node有網路故障,斷開了連接,會自動重連。master如果發現有多個slave node都來重新連接,僅僅會啟動一個rdb save操作,用一份數據服務所有slave node。
從redis 2.8開始,就支持主從復制的斷點續傳,如果主從復制過程中,網路連接斷掉了,那麼可以接著上次復制的地方,繼續復制下去,而不是從頭開始復制。master node會在內存中建一個 backlog ,master和slave都會保存一個 replica offset 還有一個 master id(run id) ,offset就是保存在backlog中的。如果master和slave網路連接斷掉了,slave會讓master從上次的replica offset開始繼續復制,但是如果沒有找到對應的offset,那麼就會執行一次full resynchronization全量同步。
master在內存中直接創建rdb,然後發送給slave,不會在自己本地落地磁碟了。
repl-diskless-sync no 改為開啟就可以了
repl-diskless-sync-delay,等待一定時長再開始復制,因為要等更多slave重新連接過來,用一分數據提供服務。
slave node不會過期key,只會等待master過期key。如果master過期了一個key,或者通過LRU淘汰了一個key,那麼會模擬一條del命令發送給slave。
(1)slave node啟動,僅僅保存master node的信息,包括master node的host和ip,但是復制流程沒開始。master host和ip是從哪兒來的?redis.conf裡面的slaveof配置的。
(2)slave node內部有個定時任務,每秒檢查是否有新的master node要連接和復制,如果發現,就跟master node建立socket網路連接。
(3)slave node發送ping命令給master node。
(4)口令認證,如果master設置了requirepass(master上啟用安全認證配置,requirepass 自己取名 ),那麼salve node必須發送masterauth的口令過去進行認證(masterauth 自己取名 )
(5)master node第一次執行全量復制,將所有數據發給slave node。
(6)master node後續持續將寫命令,增量非同步復制給slave node。
指的就是第一次slave連接msater的時候,執行的全量復制,這個過程裡面的一些細節的機制
(1)master和slave都會維護一個offset
master會在自身不斷累加offset,slave也會在自身不斷累加offset。slave每秒都會上報自己的offset給master,同時master也會保存每個slave的offset。這個倒不是說特定就用在全量復制的,主要是master和slave都要知道各自的數據的offset,才能知道互相之間的數據不一致的情況。
(2)backlog
master node有一個backlog,默認是1MB大小,master node給slave node復制數據時,也會將數據在backlog中同步寫一份。backlog主要是用來做全量復制中斷後的增量復制的。
(3)master run id
info server命令,可以看到master run id。如果根據host+ip定位master node,是不靠譜的,如果master node重啟或者數據出現了變化,那麼slave node應該根據不同的run id區分,run id不同就做全量復制。如果需要不更改run id重啟redis,可以使用redis-cli debug reload命令。
(4)psync
從節點使用psync從master node進行復制psync runid offset。master node會根據自身的情況返回響應信息,可能是FULLRESYNC runid offset觸發全量復制,可能是繼續觸發增量復制。
(1)master執行bgsave,在本地生成一份rdb快照文件。
(2)master node將rdb快照文件發送給salve node,如果rdb復制時間超過60秒(repl-timeout),那麼slave node就會認為復制失敗,可以適當調節大這個參數。
(3)對於千兆網卡的機器,一般每秒傳輸100MB,6G文件,很可能超過60s。
(4)master node在生成rdb時,會將所有新的寫命令緩存在內存中,在salve node保存了rdb之後,再將新的寫命令復制給salve node。
(5)client-output-buffer-limit slave 256MB 64MB 60,如果在復制期間,內存緩沖區持續消耗超過64MB,或者一次性超過256MB,或復制時間超過60秒,那麼停止復制,復制失敗。
(6)slave node接收到rdb之後,然後重新載入rdb到自己的內存中,同時基於舊的數據版本對外提供服務,寫入後,清空自己的舊數據,用新的對外提供讀服務。
(7)如果slave node開啟了AOF,那麼會立即執行BGREWRITEAOF,重寫AOF。在這個過程中,rdb生成、rdb通過網路拷貝、slave舊數據的清理、slave node aof rewrite,很耗費時間的。
(1)如果全量復制過程中,master-slave網路連接斷掉,那麼salve重新連接master時,會觸發增量復制。
(2)master直接從自己的backlog中獲取部分丟失的數據,發送給slave node,默認backlog就是1MB。
(3)master就是根據slave發送的psync中的offset來從backlog中獲取數據的。
下節講解哨兵架構,在講之前,你能否處理下面兩個問題呢?
1、非同步復制導致的數據丟失
哨兵可以解決主從架構下,因master宕機後不能接收寫請求而進行選舉salve為新的master,達到高可用的效果。
因為master -> slave的復制是非同步的,所以可能有部分數據還沒復制到slave,master就宕機了,此時這些部分數據就丟失了,此時應該怎麼處理?
2、腦裂導致的數據丟失
腦裂,也就是說,某個master所在機器突然脫離了正常的網路,跟其他slave機器不能連接,但是實際上master還運行著。
此時哨兵可能就會認為master宕機了,然後開啟選舉,將其他slave切換成了master這個時候,集群里就會有兩個master,也就是所謂的腦裂。
此時雖然某個slave被切換成了master,但是可能client還沒來得及切換到新的master,還繼續寫向舊master的數據可能也丟失了,因此舊master再次恢復的時候,會被作為一個slave掛到新的master上去,自己的數據會清空,重新從新的master復制數據,導致數據丟失,怎麼處理腦裂導致的數據丟失呢?
先考慮一下,我們下節進行講解。
❷ 怎麼實現讀寫分離
為了確保資料庫產品的穩定性,很多資料庫擁有雙機熱備功能。也就是,第一台資料庫伺服器,是對外提供增刪改業務的生產伺服器;第二台資料庫伺服器,主要進行讀的操作。·
讀寫分離(Read/Write Splitting)。
1.原理:讓主資料庫(master)處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從資料庫(slave)處理SELECT查詢操作。
2.誕生原因:
2.1 為了確保資料庫產品的穩定性,很多資料庫擁有雙機熱備功能。也就是,第一台資料庫伺服器,是對外提供增刪改查業務的生產伺服器;第二台資料庫伺服器,僅僅接收來自第一台伺服器的備份數據(注意,不同資料庫產品,第一台資料庫伺服器,向第二台資料庫伺服器發送備份數據的方式不同)。當第一台資料庫崩潰後,第二台資料庫伺服器,可以立即上線來代替第一台資料庫伺服器,並且,在第一台資料庫伺服器崩潰後,寶貴的數據,依然會存在於第二台資料庫伺服器里(根據目前業界的備份數據發送方式來看,當第一台資料庫崩潰後,第一台資料庫里的仍然會有少量的新數據,沒能來得及被發送到第二台資料庫伺服器,所以,這部分數據就丟失了)。
2.2 一般來說,為了配置方便,以及穩定性,這兩台資料庫伺服器,都用的是相同的配置(思考一下,如果兩台伺服器的配置不同,會導致什麼結果)。
2.3 從上文的描述中,大家能看到,在實際運行中,第一台資料庫伺服器的壓力,遠遠大於第二台資料庫伺服器。因此,很多人希望合理利用第二台資料庫伺服器的空閑資源。那麼,第二台資料庫伺服器能做些什麼事情呢?
2.4 從資料庫的基本業務來看,資料庫的操作無非就是增刪改查這4個操作。但對於「增刪改」這三個操作,如果是雙機熱備的環境中做,一台機器做了這三個操作的某一個之後,需要立即將這個操作,同步到另一台伺服器上。單向的同步,不復雜。但如果兩台機器都需要向對方進行同步,那邏輯就非常復雜,而且還會大大降低性能。(從保證ACID特性的角度,思考一下為什麼雙向同步會非常復雜且低性能?而單向同步卻不會?)出於這個原因,第二台備用的伺服器,就只做了查詢操作。進一步,為了降低第一台伺服器的壓力,乾脆就把查詢操作全部丟給第二台資料庫伺服器去做,第一台資料庫伺服器就只做增刪改了。
2.4 到這一步,就實現了所謂的讀寫分離。這樣做,缺點也非常明顯了。本來第二台資料庫伺服器,是用來做熱備的,它就應該在一個壓力非常小的環境下,保證運行的穩定性。而讀寫分離,卻增加了它的壓力,也就增加了不穩定性。因此,讀寫分離,實質上是一個在資金比較缺乏,但又需要保證數據安全的需求下,在雙機熱備方案上,做出的一種折中的擴展方案。
簡單實現
通過RAID技術,RAID是英文Rendant Array of Independent Disks的縮寫,翻譯成中文意思是「獨立磁碟冗餘陣列」,有時也簡稱磁碟陣列(Disk Array)。
簡單的說,RAID是一種把多塊獨立的硬碟(物理硬碟)按不同的方式組合起來形成一個硬碟組(邏輯硬碟),從而提供比單個硬碟更高的存儲性能和提供數據備份技術。