Berkeley DB -- 主從複製(HA)中部

轉至:http://blog.sina.com.cn/s/blog_466c6640010002h4.html

Synchronizing with a master
 
當一個client探測到replication組內一個新的master後,在它能去處理新的數據庫變化之前,這個client必須去同步這個新的master。同步是一個重量及操作,它能同時給
這個client和master增加負擔。這兒有一些措施,一個應用程序可以用來減輕同步的負擔。
 
延遲client同步:
 
當組內有了一個新的master,不論是被應用程序指定的還是因爲選舉的結果,所有的clients必須去同步這個新的master。這會使新的master的資源過度損耗,因爲很多clients可能都試圖去和它通信和從它那兒取得記錄。clients應用程序如果想延遲client的同步,應該用DB_REP_CONF_DELAYCLIENT標誌去調用DB_ENV->rep_set_config 方法。這個配置使得client總從DB_ENV->rep_process_message方法返回DB_REP_NEWMASTER,但是這個client將不會繼續去同步這個新的master。Client端應用程序選擇延遲同步,用這種方法,那麼將來再用DB_ENV->rep_sync方法去同步將是可靠的。
 
client-to-client的同步:
 
Clients可以接受和服務其他clients的請求。Clients請求記錄調用這個Client應用程序的傳輸回調函數。可以由其他Clients滿足的請求,傳輸函數的標誌被設置成DB_REP_ANYWHERE。應用程序可以選擇發送這些請求到任意client,或者忽略這個標誌,而把請求發送到這個消息的環境id所指定的站點。
 
Client應用程序可以用不管什麼算法,它們選擇來負載均衡到其它clients的請求。
任何client接受到一個它不能滿足的請求,都將回復給請求的client,告訴它,自己不能夠提供請求的信息,而那個最初的請求者,將重新請求這個信息。另外,如果這個最初的請求沒有到達發要發送給的那個目標client端,這個最初的發送請求的client也將重新請求這個信息。這這些任意一種情況下,這個重新的請求將把傳輸函數的標誌設置成DB_REP_REREQUEST 。應用程序可能通過把這個請求進一步傳遞給naster來響應這個DB_REP_REREQUEST 標誌(因爲是被這個消息的環境id指定的),或繼續把這個請求傳送給另一個client。
 
這延遲的同步和client-to-client的同步特性允許應用程序在replication組內做負載均衡。例如,考慮到一個組內有5個站點, A, B, C, D 和 E,站點E剛剛倒掉了,站點A被選舉爲master。站點C 和 D 被配置成延遲同步的,當B注意到站點A是一個新master,它立即進行同步。當B完成和master的同步的時候,站點C 和 D 上的應用程序調用 DB_ENV->rep_sync 方法,使它們也進行同步。站點C 和 D (和 E, 當它完成了重新引導) 可以發送他們的請求到站點 B, 而B可以負擔因爲同步而產生的工作和網絡流量的衝擊, 使的master,站點A,有空去處理正常的應用程序工作量和由於選舉而暫停的寫請求。
 
阻塞client的操作:
 
Clients在處理和master的同步的時候將阻塞bdb其它的操作。默認的,許多bdb方法將阻塞,直到client同步完成,然後,這些被阻塞的方法才繼續調用。
那些不能等待的Client應用程序,將更願意立即得到一個錯誤返回而不是阻塞,那麼就應該用DB_REP_CONF_NOWAIT 標誌調用DB_ENV->rep_set_config方法。如果這個clinet現在正在同步一個master,這個配置使得bdb方法調用立即返回一個DB_REP_LOCKOUT 錯誤,而不是阻塞。
 
Clients太落伍以至於不能同步:
 
Clients試圖去和master同步的時候可能會發現,同步是不可能的了,因爲client和master 已經失去聯繫很久了。默認地,client和master自動的檢測這個狀態和執行clinet內部初始化。因爲內部初始化需要傳輸整個數據庫到clinet,這可能會發費一個相對較長的時間,可能需要clinet應用程序的數據庫句柄重新被打開。
那些不能等待的應用程序,更願意推後內部初始化直到一個更加便利的時間,或者更希望做一個熱備份而不是執行內部初始化,應該用REP_CONF_NOAUTOINIT 標誌來調用DB_ENV->rep_set_config方法。這個配置使得bdb返回DB_REP_JOIN_FAILURE到應用程序而不是執行內部初始化。
 
Client應用程序如果選擇了延遲同步,這樣就有責任在將來的時間和master進行同步。這可以通過關閉DB_REP_CONF_NOAUTOINIT標誌和調用DB_ENV->rep_sync 方法來完成,或通過執行一個熱備份。
 
Initializing a new site
 
默認地,添加一個新站點到一個replication組,只需要這個client去加入。bdb將自動從master到client給它執行內部初始化,引導這個client和master同步。儘管如此,還依賴於網絡和底層結構,在一些場合下使用“熱備份”在組內去初始化一個client還是比較有利的。Clients不想自動執行內部初始化應該用DB_REP_CONF_NOAUTOINIT標誌調用DB_ENV->rep_set_config 方法。這個配置使得bdb返回DB_REP_JOIN_FAILURE到應用程序的DB_ENV->rep_process_message方法,而不是執行內部初始化。
 
爲了使用熱備份去初始化一個到replication組的clinet,執行下面的步驟:
 
做個一master環境的檔案備份,就像在“數據庫和日誌文件檔案”(Database and log file archival)中描述的那樣。這個備份可以是常規的備份或一個熱備份。
 
拷貝這個檔案備份到client的一個乾淨的環境目錄中。在client的新環境裏執行災難恢復,就像在恢復程序中描述的那樣。
 
重新配置和重新打開這個環境作爲組內的一個client成員。如果拷貝這個備份到client,相對於用db_archive公用程序或用DB_ENV->log_archive方法再造日誌文件的週期來說,發費較長的時間,它可能需要抑制日誌再造(reclamation),直到這個新啓動的client已經追上(caught up)和應用了所有在停工期間產生的log記錄。
 
就像任何bdb應用程序一樣,當應用程序啓動的時候數據庫環境必須在一個一致的(consistent)狀態。這是可以通過在一個線程或一個進程啓動時執行恢復來最簡單的確定的。這是對clients和masters來說無害的,即使它們不是嚴格的必需的,也就是說即使他們實際上沒什麼需要恢復的。
 
Bulk transfer
 
組內的站點們可能通過用DB_REP_CONF_BULK標誌調用DB_ENV->rep_set_config 方法,而把配置成使用批量傳輸的。當被配置成批量傳輸,站點們將在一個緩衝區內積聚記錄,然後在一次單一的網絡傳輸中把它們傳送給另一個站點。配置批量傳輸對master來說當然很有意義。另外,使用client-to-client同步的應用程序可能會發現,配置成批量傳輸對clients站點們來說也是很有幫助的。
 
當一個master正在產生新的log記錄時,或者,或請求任何master的信息時,如果批量傳輸被配置,記錄將堆積在一個批量緩衝區中。當緩衝區被裝滿了或一個永久的記錄(例如,一個事務提交或一個檢查點記錄)被這個client排隊等待,批量緩衝區將發送給client。

當一個client在響應另一個client的請求的信息的時候,如果批量傳輸被配置,記錄將在批量緩衝區中堆積。批量緩衝區將發送給client,當緩衝區被裝滿了或當這個client的請求已經被滿足了,再沒有特別類型的記錄將需要這緩衝區去發送了。
批量緩衝區的大小,它自己已經內定了不能被配置。儘管如此,在一次傳輸數據的總的大小可以通過使用DB_ENV->set_rep_limit方法來限制。


 
Transactional guarantees
 
在總的數據庫環境的事務保證的上下文中去考慮replication是和重要的。作爲簡要的回顧,在一個非複製(non-replicated )中事務保證,是基於寫log文件記錄到穩定的存儲設備上,通常是一個磁盤驅動器。如果應用程序回系統出了故障,bdb的日誌信息將在恢復時被回顧,而且數據庫被更新,以使已提交的事物的改變部分出現,所有未提交的而改變的部分不出現。在這種情況下,沒有信息將會丟失。
 
如果一個數據庫環境不要求當事務提交的時候把log寫到穩定存儲設備上(使用DB_TXN_NOSYNC標誌能以犧牲事務的經久性爲代價來增加性能),bdb恢復將只能把這個存儲系統恢復到最後一個提交了的被保存在磁盤上了的狀態。在這種情況下,信息可能已經丟失(例如,一些已經由事物提交了的改變可能在恢復之後不會出現在數據庫中)。
 
 更進一步。如果這兒有數據庫或log文件丟失或腐爛(例如,如果一個磁盤驅動器出了故障),然後災難恢復將是必要的,bdb恢復將只能把這個系統重新存儲到最後一次歸檔log那兒。在這中情況下,信息仍然可能被丟失。
 
 
複製(Replicating)這個數據庫環境通過添加一個新的組成到“穩定存儲”上擴展了這個模式:這個clinet的replicated信息。如果一個數據庫環境是replicated,在數據庫或log丟失的情況下,這兒也不會有信息丟失,因爲這個複製系統可以被配置成包含數據庫和log記錄直到故障點的全部的設置。一個數據庫丟失了一個磁盤驅動器能使這個磁盤被複制,然後,它有能重新加入這個複製(replication)組。
 
由於這個新的穩定存儲的組成部分,指定DB_TXN_NOSYNC到一個複製組將不再犧牲耐久性了,只要具備一個或多個clients有公認的master所發送消息的收條。因爲網絡連接通常比本地同步磁盤寫的快,replication成爲大幅度提高它們的性能和可靠性的一個方法。
應用程序發送函數的返回狀態必須被應用程序設置成確保應用程序想要提供的事務保障。無論什麼時候,發送函數返回失敗,本地數據庫環境的log將被刷新(flushed),以確保任危急到到數據庫完整性的信息不被丟失。因爲這個刷新是一個昂貴的開銷,會影響數據庫性能,如果可能的話,應用程序應該避免從發送函數那返回一個錯誤信息。
 
 
replication事務保障唯一感興趣的消息類型是當應用程序的發送函數指定了DB_REP_PERMANENT 標誌被調用。如果發送函數曾經返回失敗這兒將是沒有原因的,除非
DB_REP_PERMANENT 標誌被指定--消息沒有DB_REP_PERMANENT被指定,不會使數據庫有明顯的改變,而且發送函數可以成功返回到bdb,只要這個消息被髮送到client(s),或僅僅被拷貝到本地應用程序內存中預備發送。
 
 
當一個client收到一個DB_REP_PERMANENT 消息,這個client將在返回前刷新它的log到穩定存儲設備上(除非這個client環境曾經用DB_TXN_NOSYNC 選項配置過)。
如果這個client不能刷新一個全部的事務記錄到磁盤,不管什麼原因(例如,在被標誌的消息前丟失了一個log記錄),在client上調用DB_ENV->rep_process_message方法將返回DB_REP_NOTPERM 和在ret_lsnp參數中返回這個記錄的LSN到應用程序。
 

這個應用程序的client或master消息處理的循環應該適當的帶些動作以確保在這種情況下的正確的事務保障。當丟失的記錄到達,而且允許隨後處理這些以前存儲的永久記錄,在clinet上調用DB_ENV->rep_process_message 方法將返回DB_REP_ISPERM和返回永曾經被刷新到磁盤中的久記錄的最大的LSN。Client 應用次序可以用這些LSN決定性的知道是否某些特定的LSN被永久存儲了。
 
 
一個應用程序依賴於client的能力去成爲master,而且保證沒有數據曾經被丟失,將需要編寫發送函數返回一個錯誤,無論什麼時候它都不能保證將贏得下一次選舉的站點會有這個記錄。
 
 
應用程序不要求這個級別的事務保證將不需要讓這發送函數返回失敗(除非master的數據庫環境用DB_TXN_NOSYNC配置過),因爲任何危急到數據庫完整性的信息在發送被調用前已經被刷新到本地log文件。
 
 
總的來說,發送函數要返回失敗的唯一的原因是當master的數據庫環境被配置成當事務提交的時候不去刷新log(也就是說,在master上DB_TXN_NOSYNC被配置了), DB_REP_PERMANENT 標誌被指定給消息, 而且發送函數不能決定哪些clients收到了當前的消息(和所有在當前消息之前的消息)。多少clients在發送函數成功返回之前需要接收這個消息那是應用程序的選擇(可能不是過多的依賴於特定數目的cleints報告成功作爲一個或多個物理上分佈式的 clients)。
 
如果,儘管如此,master上的應用程序確實需要在磁盤上的耐久性,那麼這個應用程序應該被配置成當事務提交的時候同步的刷新記錄。如果一個client沒被配置成同步刷新log,也就是說,一個client運行的時候DB_TXN_NOSYNC是被被配置的,當它變成master的時候,那麼它將取決於應用程序去適當地重新配置那個client。也就是說,這個應用程序必須明確的調用DB_ENV->set_flags去重新配置這個新成爲master的client,使異步log刷新無效。
 
當然,確保replicated master和client環境確實是互相獨立的很重要。例如,如果master和clients在同一個能源供給上(on the same power supply),一個client承認收到一個消息對事情是沒什麼幫助的,因爲能源供給的失敗仍然潛在地會使信息丟失。
 
配置的你基於replication的應用程序,能事務和性能上找到最佳結合點,是很複雜的。簡言之,這兒有一些應用程序可以設置的地方以調節:爲master環境指定DB_TXN_NOSYNC;爲client環境指定DB_TXN_NOSYNC;不同的站點一起參加選舉的那個優先權;應用程序發送函數的行爲。
 
首先,在一個replication client中當一個事物提交的時候,寫和同步刷新log幾乎沒什麼用處。如果這些系統共享一個資源或多個系統同時出故障也許寫和同步刷新log還有點用。默認地,所有的bdb環境,不管是master還是client,當事務提交的時候或預先地,都同步地刷新log。

考慮兩個有網絡連接的的系統。一個作爲master,一個作爲只讀的client。如果master倒掉了client取代之,在這次故障後,master又重新加入到replication組。master 和client都被配置成當事務提交的時候不同步刷新日誌(也就是說DB_TXN_NOSYNC 在兩個系統上都被配置)。這個應用程序的發送函數從不返回失敗到bdb庫,只個簡單的傳遞消息到這個client(或許基於一個廣播機制),而且總是返回成功。在client上,由client的DB_ENV->rep_process_message方法返回的DB_REP_NOTPERM也將被忽略。這個系統配置有優秀的性能,但在某些失敗的模式下有可能丟失數據。
 
如果這個master和client都一下子到掉了,就有可能丟失已經提交了的事務,也就是說,事務的耐久性沒有被維持。有責任去提高系統的能源供給的獨立性和把他們放在物理上隔離的地方。
 
如果這兩個系統間的連接出了故障(或者僅僅是一些消息丟失了),並且隨後這個master倒掉了,也有可能失去已提交的事務。又是因爲事務的耐久性沒有被維護。下面的一些方法中可以提高可靠性:
 
使用可靠的網絡協議(例如,tcp而不是udp)。
 
增加clients和網絡路徑的數目,以使消息不太可能被丟失。在這種情況下,確保 client確實收到了這消息以贏得任何隨後的選舉也是很重要的。 如果一個client沒有受到這個消息而贏得了隨後的選舉,那麼數據仍然可能被丟失。
 
進一步的,系統可能想保證消息交付給了client(s)(例如,去阻止網絡連接簡單的丟棄消息)。一些系統可能想確保clients從來不返回已過期的信息,也就是說,一旦事務提交後在master上返回成功,將沒有client在響應只讀請求時返回舊的信息。下面的改變可能會用來闡述這些觀點:

編寫應用程序的發送函數,使它們直到一個或多個client承認收到了這個消息時才返回到bdb。這個clients的數目的選擇是由應用程序決定的:你將很可能會想網絡隔離(確保每個物理站點的client收到這個消息)和地理上多樣性(確保一個client在每條線路“each coast ”上都收到這個消息)。
 
 
編寫client的消息處理循環,使直到DB_ENV->rep_process_message返回成功的時候才承認收到這條信息。當DB_ENV->rep_process_message 方法返回DB_REP_NOTPERM 時意味着這個消息不能被刷新到client的磁盤。如果這個client不向master承認收到這個消息直到隨後調用的DB_ENV->rep_process_message方法返回DB_REP_ISPERM而且這個返回的LSN至少和這個消息的LSN一樣大,然後這個master的發送函數將不會返回success到bdb庫。這意味着,直到那些經由挑選的clients已經收到了這個消息而且認爲完成了,mastet上正在提交事務的這個線程將才被允許繼續下去。
 
作爲選擇,client的消息處理循環可以向master承認收到了這個消息,但是用一個錯誤代碼指明那個應用程序的發送函數不要返回到bdb庫,直到一個隨後的來自同一個client的確認成功。
 
應用程序的發送回調函數被bdb調用包括一個記錄的LSN被髮送(如果對那個記錄來說是適當的)。當DB_ENV->rep_process_message 返回指示一個永久的記錄已經被寫入,然後它也回返回這個被寫入的永久記錄的最大LSN 。
 
 
這兒最後的兩關需要考慮。首先,當應用程序的發送函數被調用的後,事務是不可被中途中斷的,因爲這個 master可能已經把事物提交日誌記錄寫入磁盤,所以中途中斷將不再是一個可選擇項。第二,一個相近的問題是,如果發送函數返回失敗,儘管這個master將試圖去刷新本地log,這個刷新操作將可能失敗(例如,當本地磁盤是滿的)。此外,事務不能被中途中斷,因爲一個或多個clients可能已經提交了這個事務即使發送函數返回失敗。傑出的應用程序可能也忍受不了這些不太可能的失敗方式。在那中情況下應用程序可能想:
 
1,配置這master總去同步本地提交的事務(關閉DB_TXN_NOSYNC 配置項)。這樣將對性能有很大的影響,當然(使用replication的其中的一個原因是避免本地磁盤的寫操作),在這種配置下,不管什麼情況,寫本地日誌失敗將使事務中途中斷。
 
 
2,在任何情況下都不要從應用程序的發送函數中返回,除非挑選的那些client已經承認了收到那個消息。直到這個發送函數返回到這個bdb庫,master上這個正在提交事務的線程都將等待,所以沒有應用程序能表現出承認事務已經被提交了。

最後可供牽扯到這些類型的失敗的應用程序選擇的是使用分佈式事務,保證完全的一致性實現全局的事務管理和垮過多bdb環境履行兩階段提交。更多的瞭解這個可以參見分“the Distributed Transactions”那一章。

發佈了43 篇原創文章 · 獲贊 138 · 訪問量 70萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章