螞蟻金服支付寶系統的單元化(轉載)

螞蟻金服支付寶系統的單元化java

在當今的互聯網業內,很多人對「單元化」這個詞已經耳熟能詳。不少大型互聯網系統,諸如阿里系的淘寶、支付寶、網商銀行等,都已經實現了單元化架構,並從中獲益匪淺。還有更多的公司,或在規劃着本身的系統架構向單元化演進,或已經在單元化的建設過程當中。git

單元化架構能給系統帶來什麼樣的能力,又會帶來哪些額外的成本,該不應決定作單元化,要作的話應該怎麼作。本文用螞蟻金服支付寶系統的單元化架構建設實踐,爲你們勾勒一下單元化的肢體骨架和細枝末節。github

2、爲何要作單元化

決策一個系統的總體架構方向,將對這個系統的將來產生深遠影響,而且會有實際的技術改造方面的人力投入。這樣的的決策必須是謹慎的,有依據的。因此,對於要不要單元化這個問題,這裏最想告訴你們的是一個忠告:切勿神話單元化。數據庫

回顧支付寶的整個單元化歷程,最初促成這個決策的緣由是一件看似無關的事情。早在 2011 年,支付寶系統就開始對核心數據庫作水平拆分,而更早以前,對多個關鍵業務數據庫的垂直拆分就已完成。到了 2013 年時,幾乎全部支付寶核心數據庫,都完成了水平拆分,拆分維度爲用戶,拆分爲 100 個數據分區。此時系統的部署模式是這樣的:服務器

image

同一個應用的全部節點,都會鏈接這個業務的全部數據分庫,每一個分庫上部署了若干數據分區。任意一個應用節點均可能接收到來自任意用戶的業務請求,而後再根據數據分區規則,訪問對應分庫的數據。網絡

這個架構幫助支付寶系統撐過了 2012 年雙 11,卻不管如何過不了 2013 年大促了,緣由在於數據庫鏈接不夠用了。主流的商業數據庫,鏈接都不是共享的,就是說一個事務必須獨佔一個鏈接。而鏈接卻又是數據庫很是寶貴的資源,不能無限增長。當時的支付寶,面臨的問題是不能再對應用集羣擴容,由於每加一臺機器,就須要在每一個數據分庫上新增若干鏈接,而此時幾個核心數據庫的鏈接數已經到達上限。應用不能擴容,意味着支付寶系統的容量定格了,不能再有任何業務量增加,別說大促,極可能再過一段時間連平常業務也支撐不了了。 若是 OceanBase 在當時已經成熟,能夠很好的解決 Sharding 帶來的鏈接數瓶頸問題,由於 OceanBase 是分佈式數據庫,鏈接能夠共享。然而那時並無一個合適的通過驗證的共享鏈接數據庫產品,所以單元化成爲了最好的也是惟一的解決辦法。架構

image

根據單元化的特性,每一個單元中的應用服務器僅鏈接本單元的數據分庫,若是有 n 個單元,這就至關於全部數據分庫的鏈接數馬上降爲原來的 1/n。框架

從支付寶並無倒在 2013 年雙 11 能夠知道,此次架構改造是成功的,解決了當初的燃眉之急,而且在落地單元化架構的過程當中,螞蟻技術團隊也充分拓展了單元化架構的應用場景和架構的能力,從中得到了更多的架構紅利,主要表如今如下幾個方面:運維

無限可伸縮微服務架構

經過中間件和 PaaS 平臺的配合,可以經過快速搭建一個業務完整的邏輯部署單元對系統進行總體擴容,對新機房擴容等操做帶來了很是大的便利。突破接入層、應用層和數據層的瓶頸,可支持無限擴展。分佈式

異地多活部署

除了具有異地容災能力之外,還能作到異地多城市多活,可隨時在多個城市間調配流量比例,在提高容災能力的同時,下降了成本。

全站藍綠髮布和線上灰度仿真

經過多單元之間靈活的流量調配機制,能夠實現大規模集羣的藍綠髮布,極大的提高了發佈效率。同時,經過單元內自包含的服務發現/路由和數據層的單元化分片,保證故障被切割的更小且具有獨立性,不會傳播到其餘機房,從而實現發佈時的故障自包含,螞蟻基於這個機制實現了線上全鏈路壓測和灰度仿真環境,爲業務提供了更真實的驗證環境,這對充分驗證業務正確性,下降技術故障起到了關鍵的做用,尤爲對金融類業務。

異構機房上的彈性混合雲架構

經過單元化伸縮的機制和容器化技術對底層虛擬化平臺的屏蔽,實現多個異構機房的資源充分利用,不管基於什麼架構,不管在哪一個城市,均可以快速建站部署單元,並在業務高峯期事後快速回收,完成數據的回遷。

雖然結果很好,整個單元化演進的過程也是極其艱辛的。在關鍵業務數據庫都已經水平拆分完畢的狀況下,支付寶仍是用了將近 1 年的時間,改造了幾乎全站業務系統以支持單元化。除此以外,還花費了至關大的力量改造系統使用的各種中間件,包括微服務框架、消息中間件、調度系統等,還建設了專門的單元化運維監控平臺。不管在架構方案上仍是技術產品上,螞蟻技術團隊都積累了大量的經驗。

這個過程帶來的啓示是,單元化確實能帶來很多激動人心的特性,但同時也會讓系統架構變的複雜。這不只會對系統的運維平臺提出更高要求,也會給業務研發帶來一些理解成本,這個思想很是像業界流行的 Cloud Native 的思想,要充分利用雲架構的好處,還須要讓應用層架構設計遵守必定的範式,而螞蟻逐步將這些範式和能力沉澱到了 PaaS 平臺、中間件和數據庫中,成爲一種原生 (Native) 的能力,爲業務開發提供單元化能力支撐。

因此說,單元化不能被神話,它有利有弊,只是看着它的好處就貿然決定開始的作法不可取。應當充分評估當前的系統現狀,識別其中存在的和潛在的問題,判斷單元化是否能解決以及解決所帶來的成本,選擇最合適的性價比最高的架構來支撐業務發展。 固然,若是最後的判斷是須要引入單元化,那麼必定義無反顧,畢竟它產生的價值及其誘人。

3、能不能單元化

若是您是新建一套系統,那麼恭喜你,你只要考慮這個系統的重要性,即未來是否須要在可擴展性、容災能力、業務連續性、成本控制等方面有很高的要求,若是答案是確定的,那能夠一開始就按照單元化的方式去設計,這套架構徹底能支持業務從單機房到同城多機房,再到異地多活機房的平滑演進。但若是是一套老系統,就須要評估一下它是否具有單元化的基礎了。

所謂單元,是指一個能完成全部業務操做的自包含集合,在這個集合中包含了全部業務所需的全部服務,以及分配給這個單元的數據。單元化架構就是把單元做爲系統部署的基本單位,在全站全部機房中部署數個單元,每一個機房裏的單元數目不定,任意一個單元都部署了系統所需的全部的應用,數據則是全量數據按照某種維度劃分後的一部分。 傳統意義上的 SOA 化(服務化)架構,服務是分層的,每層的節點數量不盡相同,上層調用下層時,隨機選擇節點。

image

單元化架構下,服務仍然是分層的,不一樣的是每一層中的任意一個節點都屬於且僅屬於某一個單元,上層調用下層時,僅會選擇本單元內的節點。

image

一個單元,是一個五臟俱全的縮小版整站,它是全能的,由於部署了全部應用;但它不是全量的,由於只能操做一部分數據。可以單元化的系統,很容易在多機房中部署,由於能夠輕易的把幾個單元部署在一個機房,而把另外幾個部署在其餘機房。藉由在業務入口處設置一個流量調配器,能夠調整業務流量在單元之間的比例。

image

從這個對單元的定義和特性描述中,能夠推導出單元化架構要求系統必須具有的一項能力:數據分區,實際上正是數據分區決定了各個單元可承擔的業務流量比例。數據分區(shard),便是把全局數據按照某一個維度水平劃分開來,每一個分區的數據內容互不重疊,這也就是數據庫水平拆分所作的事情。 僅把數據分區了還不夠,單元化的另一個必要條件是,全站全部業務數據分區所用的拆分維度和拆分規則都必須同樣。如果以用戶分區數據,那交易、收單、微貸、支付、帳務等,全鏈路業務都應該基於用戶維度拆分數據,而且採用同樣的規則拆分出一樣的分區數。好比,以用戶 id 末 2 位做爲標識,將每一個業務的全量數據都劃分爲 100 個分區(00-99)。

有了以上兩個基礎,單元化纔可能成爲現實。把一個或幾個數據分區,部署在某個單元裏,這些數據分區佔總量數據的比例,就是這個單元可以承擔的業務流量比例。 選擇數據分區維度,是個很重要的問題。一個好的維度,應該: 粒度合適。粒度過大,會讓流量調配的靈活性和精細度收到制約;粒度太小,會給數據的支撐資源、訪問邏輯帶來負擔。 足夠平均。按這個維度劃分後,每一個分區的數據量應該幾乎一致。 以用戶爲服務主體的系統(To C),好比支付寶,一般能夠按照用戶維度對數據分區,這是一個最佳實踐。

4、怎麼作單元化

在真正動手以前,有一個必需要知曉並始終記之在心的事實,完美的單元化是不存在的。 從單元化的角度,在一個系統當中實際上存在 3 類數據:

可分區數據

能夠按照選擇好的維度進行分區的數據,真正能被單元化的數據。這類數據一般在系統業務鏈路中處於核心位置,單元化建設最重要的目標實際上就是把這些數據處理好。好比訂單數據、支付流水數據、帳戶數據等,都屬於這一類型。 這類數據在系統中的佔比越高,總體單元化的程度就越高,若是系統中所有都是這樣的數據,那咱們就能打造一個完美單元化的架構。不過現實中這種狀況存在的可能性幾乎爲零,由於下面提到的兩類數據,或多或少都會存在於系統當中。

全局數據,不被關鍵鏈路業務頻繁訪問

不能被分區的數據,全局只能有一份。比較典型的是一些配置類數據,它們可能會被關鍵鏈路業務訪問,但並不頻繁,所以即便訪問速度不夠快,也不會對業務性能形成太大的影響。 由於不能分區,這類數據不能被部署在經典的單元中,必須創造一種非典型單元用以承載它們。

全局數據,須要被關鍵鏈路業務頻繁訪問

乍看與上面一類類似,但二者有一個顯著的區別,便是否會被關鍵鏈路業務頻繁訪問。若是系統不追求異地部署,那麼這個區別不會產生什麼影響;但若是但願經過單元化得到多地多活的能力,這僅有的一點兒不一樣,會讓對這兩類數據的處理方式大相徑庭,後者所要消耗的成本和帶來的複雜度都大幅增長。

究其緣由是異地部署所產生的網絡時延問題。根據實際測試,在網絡施工精細的前提下,相距約 2000 千米的 2 個機房,單向通訊延時大約 20ms 左右,據此推算在國內任意兩地部署的機房,之間延時在 30ms 上下。假如一筆業務須要 1 次異地機房的同步調用,就須要至少 60ms 的延時(請求去,響應回)。若是某個不能單元化的數據須要被關鍵業務頻繁訪問,而業務的大部分服務都部署在異地單元中,網絡耗時 60ms 的調用在一筆業務中可能有個幾十次,這就是說有可能用戶點擊一個按鈕後,要等待數秒甚至數十秒,系統的服務性能被大幅拉低。

這類數據的典型表明是會員數據,對於支付寶這類 To C 的系統來講,幾乎全部的業務都須要使用到會員信息,而會員數據卻又是公共的。由於業務必然是雙邊的,會員數據是不能以用戶維度分區的。

支付寶的單元化架構中,把單元稱之爲 「zone」,而且爲上面所說的3類數據分別設計了三種不一樣類型的 zone:

  • RZone(Region Zone):最符合理論上單元定義的 zone,每一個 RZone 都是自包含的,擁有本身的數據,能完成全部業務。
  • GZone(Global Zone):部署了不可拆分的數據和服務,這些數據或服務可能會被RZone依賴。GZone 在全局只有一組,數據僅有一份。
  • CZone(City Zone):一樣部署了不可拆分的數據和服務,也會被 RZone 依賴。跟 GZone 不一樣的是,CZone 中的數據或服務會被 RZone 頻繁訪問,每一筆業務至少會訪問一次;而 GZone 被 RZone 訪問的頻率則低的多。

image

RZone 是成組部署的,組內 A/B 集羣互爲備份,可隨時調整 A/B 之間的流量比例。能夠把一組 RZone 部署的任意機房中,包括異地機房,數據隨着 zone 一塊兒走。

GZone 也是成組部署的,A/B 互備,一樣能夠調整流量。GZone 只有一組,必須部署在同一個城市中。

CZone 是一種很特殊的 zone,它是爲了解決最讓人頭疼的異地延時問題而誕生的,能夠說是支付寶單元化架構的一個創新。 CZone 解決這個問題的核心思想是:把數據搬到本地,並基於一個假設:大部分數據被建立(寫入)和被使用(讀取)之間是有時間差的。

  • 把數據搬到本地:在某個機房建立或更新的公共數據,以增量的方式同步給異地全部機房,而且同步是雙向的,也就是說在大多數時間,全部機房裏的公共數據庫,內容都是同樣的。這就使得部署在任何城市的 RZone,均可以在本地訪問公共數據,消除了跨地訪問的影響。整個過程當中惟一受到異地延時影響的,就只有數據同步,而這影響,也會被下面所說的時間差抹掉。

  • 時間差假設:舉例說明,2 個用戶分屬兩個不一樣的 RZone,分別部署在兩地,用戶 A 要給用戶 B 作一筆轉帳,系統處理時必須同時拿到 A 和 B 的會員信息;而 B 是一個剛剛新建的用戶,它建立後,其會員信息會進入它所在機房的公共數據庫,而後再同步給 A 所在的機房。若是 A 發起轉帳的時候,B 的信息尚未同步給 A 的機房,這筆業務就會失敗。時間差假設就是,對於 80% 以上的公共數據,這種狀況不會發生,也就是說 B 的會員信息建立後,過了足夠長的時間後,A 纔會發起對 B 的轉帳。

經過對支付寶 RZone 業務的分析發現,時間差假設是成立的,實際上超過 90% 的業務,都對數據被建立和被使用之間的時間間隔要求很低。餘下的那些不能忍受時間差的業務(即要求數據被建立後就必須立刻可用,要不就乾脆不能訪問),則必須進行業務改造,忍受異地訪問延時。

5、須要哪些支持

前面提到,支付寶系統早已實現了數據水平拆分,而且全站拆分維度一致,在具有了這個重要基礎能力的前提下,仍然舉全站之力用了近一年時間才完成單元化改造,除了由於要改造業務系統以妥善處理 GZone/CZone 的數據之外,還有一項工做也耗費了大量人力和時間,那就是建設起了一個單元化技術支持平臺。 單元化架構增長了構複雜性和運維複雜度,若是沒有這樣一個平臺支撐,很難把如此複雜的一個系統健康的維護起來。 所謂單元化技術支持平臺,至少應該包含三方面功能。

一套支持單元化的中間件

支付寶的業務開發因單元化架構而變得複雜、不易理解,而實際上如今看到的複雜性比起它的本來的程度來講已經下降了太多。這其中最大程度屏蔽了單元化細節,讓單元化架構儘可能對業務層透明,起到相當重要做用的,就是一整套專門針對單元化而研製的中間件,也即上文提到的原生 (Native) 單元化能力。

比較關鍵的幾個包括,數據訪問層中間件,把數據水平分庫分表的細節隱藏在水面之下,上層業務使用起來跟單庫單表沒什麼區別。更進一步的,數據訪問層能實時動態感知單元化分流規則,根據規則變化決策是否鏈接某個數據分庫,以及一筆業務是否容許訪問某個數據分庫。能夠說單元化的本質就是對數據的邏輯隔離,有這樣一個數據訪問中間件對單元化建設來講是必不可少的,它解耦了業務層對數據層結構的依賴,大大下降了理解成本。

另外更爲重要的是幾個負責信息傳遞的中間件,正是它們讓單元能夠成爲單元。這其中有微服務框架、消息中間件等,它們可以根據單元化規則把系統應用間的服務調用或消息流轉約束在一個邏輯區域內,再配合上數據訪問中間件對數據訪問的約束,就讓這一個個邏輯區域造成了一個個單元。若是有些調用必須跨單元發生,也由它們根據規則執行轉發,不須要業務層關心。

一個規則管理和流量調撥系統

前面屢次提到了「規則」這個詞,在單元化架構中,規則舉足輕重,業務流量在單元間怎麼分配,哪一個單元能訪問哪一個數據分庫,某次服務調用可否跨出單元,這些都由規則掌管。可想而知,必須有一個統一的位置來全局惟一的管理這套規則,並在變動時可以及時準確的的推送給各個執行點,不然不一樣模塊識別到的規則不一樣,將會形成全系統信息混亂。

規則管理系統的目的就是成爲這樣一個單元化規則權威持有者,運維人員對規則的全部變動,都在這個系統上操做。它經過某種協議鏈接着系統中全部須要感知規則的模塊,一旦發生規則變化就實時把新規則內容推送給各個模塊,並識別推送結果,對推送失敗的模塊執行重試,確保規則下發到全部位置。

一個面向單元的發佈部署和監控平臺

單元化後,一個系統被劃分紅了數量衆多的邏輯單元,這讓系統發佈換版的粒度更細,試錯成本更低,但也讓發佈這件事情更難作,因此一個能面向單元進行發佈的部署平臺就變的很是必要。 這個部署平臺可以以單元爲維度執行發佈,單元間能夠互不影響的獨立部署。

同時,平臺須要有能力統一編排和控制不一樣單元的部署進程,從而可以實現基於單元的全站藍綠髮布等高階功能。

此外,監控系統要求可以細化到單元粒度展現監控信息和發送報警,以協助判斷每一個單元中的系統健康程度,爲快速執行流量切換以隔離故障等操做提供依據。

以上幾項是一個單元化技術支持平臺必需要具有的能力,在支付寶的單元化進程中,已經沉澱出了完整的這樣一套平臺,並在逐步產品化爲具有完整單元化能力的 SOFA 平臺和 OceanBase 數據庫,搭載在螞蟻金融雲上對外輸出。在幾年中前後支持了螞蟻保險、網商銀行的單元化改造,在將來也將爲更多的金融生態合做夥伴提供服務。

轉自做者: chenshiying007

相關文章
相關標籤/搜索