摘 要: 為了利用廉價的普通桌面電腦構建高性能、高可靠、低成本的電子郵件備份系統,設計了基于SOA的對等網絡存儲架構,貫徹了低耦合、無狀態、異步通信和自適應的設計原則。系統將輸入數據流和輸出數據流分開處理,分別將郵件數據和索引信息保存在磁盤文件和數據庫中,兼顧了高容量和快速查找的的要求。
關鍵詞: 電子郵件;備份;分布式存儲;SOA;低成本
在一個在線電子郵件掃描系統中,需要設計一個安全可靠的存儲系統,暫時保存被隔離的電子郵件。這些郵件一直保留在系統內,直到用戶選擇釋放或者到期失效。這是一個需要精心設計的系統,考慮牽涉到的數據量和在線系統所要求的高可靠性,如何用盡可能低的成本實現這個系統,成為項目團隊面對的主要挑戰。
1 分布式郵件備份系統的技術需求和設計原則
郵件備份系統最基本的要求是高吞吐量,具體來講,要求能達到每秒1 000封郵件(平均大小10 KB)的最大輸入速度,用戶的郵件要能保存最多60天,系統總容量在20 TB以上,用戶的檢索速度應該控制在1 s以內。
作為一個商業運營的在線系統,除了具備很高的性能以外,還要具備很高的可靠性和盡可能低的成本。系統的SLA[1](Service Level Agreement)要達到99.99%以上,也就是說運行一年的停機時間必須控制在52 min以內。在線系統的主要成本包括數據中心的成本和運行維護成本。數據中心的成本主要由硬件成本、網絡成本、其他成本如電費、冷卻、機架空間等構成,而運營成本主要由運營維護、技術支持等費用構成。依據上述基本要求,確定了郵件備份系統的基本技術需求:(1)單機高效率,系統高吞吐;(2)使用低成本硬件,避免使用昂貴硬件;(3)提供高可伸縮性;(4)部署自動化;(5)管理智能化。
根據上述需求,確立系統整體設計的原則,主要包括下述四點:
(1)低耦合。耦合是指系統的子模塊之間結合的緊密程度,一個低耦合的系統不但要降低模塊之間的靜態依賴關系,而且要盡可能地降低模塊在時間和空間上的依賴關系。低耦合的系統可以降低模塊之間的相互影響,提高系統的擴展性。
?。?)無狀態。無狀態的服務不在內部保留狀態數據,上一個請求和下一個請求之間沒有任何關系。無狀態的服務更容易實現水平擴展。
?。?)異步通信。異步通信可以提高通信的效率,請求發送者無需等待服務的返回,節點之間不需要互相等待,可以提高每個節點的處理效率。
(4)自適應。自適應的系統能夠自動調整、優化運行參數、應對運行環境的變化。能夠自我調整,也就減少了人為干預的要求,降低了維護費用,而且自動調整顯然比人為干預反應更快、也更準確,所以也提高了可靠性。
2 分布式郵件備份系統的設計
2.1 整體框架設計
系統的整體設計采用SOA[2]的架構,系統由三種不同的角色構成,其關系如圖1所示。
組件A和B完成系統特定的某些功能,A和B對外部提供Restful[3]風格的Web應用接口,但是A和B之間互相沒有調用關系,也不知道彼此的存在。Registry是一個注冊服務器[4],所有的組件都在Registry注冊,并不斷通過心跳信號更新自己的狀態到Registry;而且Registry維護一張系統所有組件的狀態表,對于超時沒有更新的組件,就將其從列表中刪除。Helper負責將數據從一個組件傳送到另一個組件;可以從Registry得到當前系統的所有組件清單以及組件之間的邏輯聯系關系,并據此進行數據轉運工作;使用標準的HTTP命令從一個組件的輸出隊列得到數據,然后同樣用HTTP命令將數據發送到下游的組件。
同一類型的組件可以同時有多個實例存在,以提供高可靠性和任務負載的均衡擴充。Helper本身也可以有多個實例存在,提供多個上游組件和下游組件之間的動態數據交換和負載均衡。
組件工作在異步的模式下,每個組件都有一個輸入隊列和一個輸出隊列,需要處理的數據通過Web接口被放進輸入隊列,組件的數據處理程序依次從輸入隊列讀取數據,處理完成后放入輸出隊列,然后通過Web接口被取走。組件擁有完成處理工作所需要的所有資源和數據,可以獨立完成自己的任務。這是保證組件異步、高效工作的重要前提條件。
一個最簡單的系統至少包括三種不同的功能組件,它們分別是Generator、Processor和Terminator。它們之間的關系如圖2所示。
Generator是任務的發起方,一個Generator至少有一個任務輸出隊列和一個對應的ACK輸入隊列。Generator產生的任務數據在任務輸出隊列中排隊等候Helper轉送到Processor進行處理。一旦一個任務被送到Processor,這個任務就被放入一個等候確認的隊列,等候任務完成的確認。Processor至少有一個任務輸入隊列和一個結果輸出隊列,即從任務輸入隊列取得待處理任務,進行處理后放入結果輸出隊列,由Helper送到Terminator。Terminator對結果進行最后的處理后,生成對應的ACK,ACK被送回Generator,完成一個完整的任務處理生命周期。如果Generator在規定時間里沒有收到一個任務的ACK,說明這個任務可能在系統內被丟失了,按不同的業務邏輯,Generator可以重新發送這個任務,也可以丟棄這個任務。確認-重發機制保證了異步系統中數據的可靠性問題,較好地解決了節點失效時丟失任務的問題。此外,通過Helper橋接的設計允許在一個任務處理序列里組合多個不同的Processor來完成復雜的任務而不用修改程序,這種重組甚至可以在運行中的系統上動態完成,大大提高了系統的彈性。
圖3是郵件備份系統的架構圖,主要的組件是QtStorage和QtDAL。QtStorage負責存儲郵件的原始信息(包括郵件的原文、發送者、接收者等信息),將收到的郵件寫入存儲區域后,會將郵件及相關信息編制成摘要。QtDAL負責將郵件的摘要存儲在數據庫中,并為用戶提供檢索服務。為了實現高效率的運作,存儲系統的設計采用了讀寫分開的思想。大量原始數據的寫入在QtStorage上完成,QtStorage擁有多個實例,可以分散寫入的壓力,同時也能夠提供多重冗余,實現高可用性。QtStorage可以實現無縫的橫向擴展,其存儲能力和容量隨之擴展。經過QtStorage處理過的摘要信息,其容量已經大大縮減,所以可以采用單一的索引節點來保存,單一節點可以以較低的代價實現數據的一致性。這里的QtDAL就是這樣的一個索引節點,用戶的查找和讀取主要發生在QtDAL上,查找和讀取索引信息和數據的寫入發生在不同的節點上,這樣就實現了數據的讀寫分開,提高了運行效率。只有在用戶需要取回被隔離的原始郵件時,才會到QtStorage上去讀取,按照系統的設計邏輯,這是一個概率極低的操作,不會對系統構成很大的影響。
2.2 文件存儲服務
文件存儲服務為整個系統提供原始數據的存儲服務。根據經驗,這部分的成本是整個系統成本的主要構成部分。為了保持低成本,必須避免使用價格昂貴的高性能存儲設備,如SAN、NAS等。而且為了便于擴展和維護,一些需要特別硬件支持的存儲設備也不能考慮,如RAID陣列等。一個可行的設計思路是使用最廉價的PC和隨機安裝的硬盤來構成系統。商用的PC可以安裝4個處理核心的CPU和2 TB以上的硬盤,其性能和容量已經足以滿足系統的需求。但是不論是PC的硬件還是硬盤本身,其可靠性和穩定性都不能達到99.99%的可靠性。解決的方法是用多重冗余的方式構建系統,不但數據的保存是多重冗余的,而且處理節點也是多重冗余的。
2.2.1 數據的寫入
圖4是文件存儲系統的設計。Storage 1~3是3個存儲節點,各自帶有2 TB的硬盤存儲數據,并對外開放3個Web接口,分別是接收文件輸入的Input Queue、輸出文件索引信息的Index Queue和輸出文件同步包的Sync Queue。一個文件的存儲過程可以用以下步驟描述:
(1)Helper隨機挑選一個Storage節點(例如Storage 1),將待保存的文件及控制信息一起發送到Storage 1的Input Queue。
(2)Storage 1將文件存盤,生成文件的索引信息,將索引放到Index Queue。
?。?)Storage 1修改文件控制信息,將文件和控制信息添加到Sync Queue。
?。?)Helper從Storage 1的Sync Queue中將待同步文件取出,送到另一個Storage節點(例如Storage 2)。
?。?)Helper將索引信息從Storage 1取出,送到數據庫保存。
?。?)Storage 2重復上述步驟,直到重復存儲次數達到需要的冗余度為止。
這個設計的主要特點如下:
?。?)每個Storage節點都同時具有處理能力和存儲容量,添加節點就可以同時擴展處理能力和容量,系統的擴展是對稱的,非常利于管理和維護。
?。?)Storage節點之間沒有相互依賴性,任何一個Storage節點因為故障下線,都不會對整個系統產生影響。
?。?)每個文件需要多少冗余度、是否加密、是否壓縮,都可以單獨控制,非常靈活。
?。?)添加新的Storage節點后,負載會自動均衡到新的節點上,有利于資源的有效利用。
?。?)系統要求的保存文件期限最多60天,所以在3冗余或更多冗余的情況下,可以不用考慮損壞節點的文件恢復功能。即使使用可靠性較低的普通PC和SATA硬盤,也可以保證文件在60天內的可用性。
?。?)讀寫分開,大負荷的文件寫入被分散到數量眾多的Storage節點上,數據庫節點只負責少量、偶爾的用戶查詢操作,提高了硬件效率,降低了成本。
?。?)系統并不是嚴格一致的,通過犧牲部分一致性,獲得了較好的擴展性和可用性,是CAP[5]原則的具體實踐。
?。?)Storage節點之間是沒有聯系、沒有交互的,所有的數據交換都通過Helper進行。文件的控制信息隨同文件數據本身傳送,沒有任何一個節點管理和追蹤文件的去向,各個節點間通過合作完成任務,沒有中心控制節點。這個過程充分體現了“低耦合”、“異步”、“無狀態”的設計原則。
需要說明的是,Storage節點的數目建議大于系統設置的最高冗余度。例如對于3冗余的系統,Storage節點建議至少設置4個,這樣,在某一個節點因故下線的時候,系統仍然可以正常運行。當然,設置更多的節點可以獲得更好的可靠性和性能。
2.2.2 數據的查詢
數據的查詢相當簡單,按照用戶提供的查詢條件,可以在數據庫中查詢到符合條件的記錄,每條記錄中都包含對應的數據文件在Storage節點上的位置。如果用戶需要讀取原始數據,可以調用Storage節點上的API接口,提供位置信息,讀取原始數據。記錄中包含文件的多個冗余備份的位置,如果一個節點失效或者不能訪問,可以讀取備用節點上的信息。
2.2.3 數據的刪除
數據的刪除分為數據庫記錄的刪除和數據文件的刪除,數據庫節點和Storage節點都有內置的定時任務,可以按時間刪除已經過期的數據。
2.2.4 系統容量的擴展和故障節點的替換
當文件存儲系統的容量不能滿足要求時,需要對系統容量進行擴展,這種擴展應該是一種簡單的、無縫的操作,不能干擾系統的正常運行,不需要修改軟件,不需要停機以及盡量少的配置改動。本系統較好地實現了上述要求。
2.3 索引數據庫
索引數據庫保存著所有備份郵件的索引信息和位置信息。這是一個標準的關系型數據庫,采用開源的PostgresSQL實現。數據庫主要包括兩張表,如圖5所示。
為了提高數據的安全性,可以設置將備份的郵件在不同節點上拷貝多份冗余。圖7即為冗余度設置為2時的測試數據,考察了不同節點數量對性能的影響??梢钥吹?,隨著系統節點數的增加,系統性能也呈基本線性地增加,這充分反映了節點間異步通信的重要性。異步通信削弱了節點間在時間上的依賴關系,通過犧牲局部的、臨時的一致性,充分發揮了每個節點的處理能力,提高了系統的效率。
為了進一步提高數據可靠性,可以把冗余度設置到3,此時每封郵件在系統內有三份拷貝,達到了極高的可靠性。如圖8所示,在4節點3冗余的測試環境下,系統的吞吐速率達到了3 000封/s(10 KB郵件)和2 000封/s(30 KB郵件)。如果等價成單個節點的平均速率的話,分別達到2 250封/s和1 500封/s,比單節點的性能還要好些。這是因為隨節點的增多,不但存儲空間得到擴展、可靠性得到增加,CPU的數量和處理能力也得到加強,更多的CPU的加入,也在一定程度上提高了系統的整體處理能力。
3.3 結果分析
通過對結果的分析,發現在單節點場景下,采用30 KB郵件樣本時系統達到了42 MB/s的寫入速度,而10 KB郵件的寫入速度為18 MB/s,兩種測試環境中CPU占用均為30%左右,說明系統瓶頸不在CPU和I/O中。通過對代碼實現的審查發現,問題主要是同步寫文件導致的,對文件的同步讀寫操作降低了I/O的效率,并且隨樣本的縮小,讀寫操作的頻繁化而更趨惡化。這就是為什么小樣本性能不成比例增加的根本原因。全面采用異步磁盤I/O操作可以很好地改善這個問題,但是異步I/O程序遠較同步I/O復雜,而且在本項目里,即使是同步I/O也足夠滿足性能需求,所以本設計最后決定保持目前的代碼不變。
比較不同組合條件下的測試結果可以發現,性能隨冗余度的增加而降低、隨節點數目的增加而提高,三者間的關系接近線性關系。如果節點數目增加一倍,性能也能夠增加一倍。增加冗余度會降低性能,但可以通過增加節點來補償。同時添加節點數量和冗余度,能夠得到更好的可靠性和性能,并且收益并不隨節點數目的增加而遞減。對于一個分布式系統,這是一個非??少F的特質。因為管理者可以通過簡單的添加處理節點,獲取更多的存儲和處理能力。
為了最大限度地降低成本、提高可靠性,在設計的初期階段就確立了低耦合、無狀態、異步通信和自適應這四個設計準則。通過放寬對一致性的要求,僅保證最終一致性,充分解耦各個節點間的依賴關系,獲得了優異的可靠性和可擴展性。最終的測試結果也證明了這種設計思路的正確性,采用普通桌面計算機和廉價磁盤組成的系統足以在容量、性能、可靠性和可擴展性方面滿足要求,而成本僅為傳統方案的十分之一。
參考文獻
[1] TANENBAUM A S, STEEN M V. Distributed systems principles and paradigms[M].楊劍鋒,常曉波,李敏,譯,北京:清華大學出版社,2004.
[2] JOSUTTIS N M. SOA in practice[M].程樺,譯.北京:電子工業出版社,2008.
[3] ROCHARDSON L, RUBY S. RESTful Web Services中文版[M].徐涵,李紅軍,胡偉,譯.北京:電子工業出版社,2008.
[4] 杜宗霞, 懷進鵬, 主動分布式Web服務注冊機制研究與實現[J]. 軟件學報,2006,17(3):454-462
[5] BREWER E A. Towards robust distributed systems. (Invited Talk)Principles of Distributed Computing, Portland, Oregon, July 2000.