支付寶架構(gòu)有多牛?還沒看完我就跪了...
圖片來自 包圖網(wǎng)
當(dāng)交易峰值曲線慢慢爬升,最后變得無比陡峭,值班室的同學(xué)都很激動,歡呼聲伴隨著爬升的曲線達到了頂峰,58.3 萬筆/秒,也是新的交易峰值記錄,但相比往年動輒翻一倍,漲 30%~40%,增長率還是小了很多。
2010 年雙 11 的支付峰值是 2 萬筆/分鐘,到 2017 雙 11 時變?yōu)榱?25.6 萬筆/秒,再到去年的 58.3 萬筆/秒,是 2009 年第一次雙 11 的一千多倍。
要抗住這么大的支付 TPS,螞蟻做了很多頂層架構(gòu)的設(shè)計和底層實現(xiàn)的優(yōu)化,其中最為最核心的就是 LDC 架構(gòu)。
LDC 的全稱為:Logic Data Center,邏輯數(shù)據(jù)中心,之所以叫 LDC,是跟傳統(tǒng)的 IDC(Internet Data Center)相比而提出來的概念。
IDC 相信大家都很清楚,就是物理的數(shù)據(jù)中心,說白了就是能夠建站的物理機房。
LDC(邏輯數(shù)據(jù)中心),核心架構(gòu)思想就是不管你物理機房部署是怎樣的,比如你可能有三個 IDC,分別在二個不同城市(常說的兩地三中心),在邏輯上是統(tǒng)一的,我邏輯上看成一個整體,統(tǒng)一協(xié)調(diào)調(diào)配。
為什么會出現(xiàn) LDC
LDC 是為了解決什么問題?還得從架構(gòu)的演進說起。之前講過機房容災(zāi)設(shè)計的架構(gòu)演進,我們用具體的應(yīng)用推演一次。
先看如下圖所示的單體應(yīng)用架構(gòu),請求到網(wǎng)關(guān)接口,網(wǎng)關(guān)接口直接調(diào)應(yīng)用或者服務(wù),服務(wù)調(diào)存儲層查詢或?qū)懭霐?shù)據(jù),一竿子捅到底。
這種架構(gòu)模式最大的風(fēng)險是服務(wù)、存儲都是單點的,訪問容量和性能受限于存儲和應(yīng)用的容量和性能,容災(zāi)方面,一旦發(fā)生故障只能死等單點應(yīng)用或存儲的恢復(fù)。
后來工程師們開始對應(yīng)用做水平拆分,對服務(wù)做垂直拆分。
水平拆分應(yīng)該都很熟悉,就是加服務(wù)器,每臺服務(wù)器都部署實例,垂直拆分就是把服務(wù)按域做拆分。
比如一個交易系統(tǒng),有商戶域、商品域、用戶域、訂單域等,拆分成多個微服務(wù),服務(wù)解耦,服務(wù)可以獨立發(fā)布,應(yīng)用的復(fù)雜度會更高。
這個分布式架構(gòu)解決了服務(wù)單點的問題,某臺服務(wù)器宕機,服務(wù)還是可用的,但是存儲層還是單點的,而且隨著業(yè)務(wù)增長,擴容加的機器越多,大家發(fā)現(xiàn)查詢寫入效率耗時到一定階段反倒是變慢了,分析發(fā)現(xiàn)存儲層出現(xiàn)了性能瓶頸。
上面圖只花了 2 臺服務(wù)器連接數(shù)據(jù)庫,真實分布式系統(tǒng)可能幾十百來臺,甚至上千臺,如果都連一臺 DB,連接數(shù)、鎖爭用等問題,SQL 性能變慢可想而知。
后來的事情大家也都知道,互聯(lián)網(wǎng)公司開始紛紛做讀寫分離,把讀請求和寫請求分開。
讀寫分離這里面隱含了一個邏輯,那就是數(shù)據(jù)寫入之后,不會立即被使用。
數(shù)據(jù)從寫入到被立即使用有個時間差,等從庫同步數(shù)據(jù)才會被讀取,實際統(tǒng)計發(fā)現(xiàn),常規(guī)的應(yīng)用,90% 的數(shù)據(jù)確實在寫入之后不會立即被使用,當(dāng)然我這里說的立即的時間單位是 ms,一般同步延遲也就是幾毫秒,不超過 10 ~20ms。
但是這個架構(gòu)并沒有解決寫的問題,隨著業(yè)務(wù)量的增長,寫數(shù)據(jù)成為了瓶頸。分庫分表應(yīng)運而生,分庫分表的中間件開始變得流行起來,現(xiàn)在基本成了中大型互聯(lián)網(wǎng)公司的標(biāo)配。
基本思想就是把數(shù)據(jù)按照指定維度拆分,比較常見的是 userId 維度,例如取 userId 的后 2 位,可以拆分成百庫百表,也有的除以指定模數(shù)取余數(shù),例如除以 64 取余,可以按余數(shù)范圍 0-63 拆成 64 個庫。
關(guān)于分庫分表,很多人都知道有垂直拆分和水平拆分二種(上面說的垂直和水平是系統(tǒng)的拆分,這里指的是存儲的)。
垂直拆分就是按照業(yè)務(wù)維度拆分,把同一個業(yè)務(wù)類型的表放到一個庫,經(jīng)常會按領(lǐng)域模型的概念拆分,比如訂單庫、用戶庫、商品庫等。
水平拆分就是把大數(shù)據(jù)量的表(庫)切分成很多個小數(shù)據(jù)量的表(庫),減小庫和表的訪問壓力,可以和系統(tǒng)的水平垂直切分比一下:
為什么叫水平和垂直呢?其實很好理解,你想象一張用戶表,里面放了很多字段,如下圖:
那垂直拆分,就是垂直從中間劃一刀,把藍(lán)色的用戶信息表和右邊綠色的訂單信息表拆分成 2 張表。庫拆分成用戶庫和訂單庫。
水平拆分,就是水平劃一刀,把數(shù)據(jù)量降低。
大家看到這,是不是以為問題都解決了,上面分庫分表之后,如果應(yīng)用層面扛得住,數(shù)據(jù)庫層面的確能做到并發(fā)量到萬這個級別。但是容量要再上一個數(shù)量級就有點困難了。
為什么呢?因為一個庫實例是被所有應(yīng)用共享的,也就是你每增加一臺機器,數(shù)據(jù)庫連接就會相應(yīng)的增加一些,增量是至少機器設(shè)置的最小連接數(shù)。
為什么應(yīng)用需要連接所有的數(shù)據(jù)庫實例呢?
答:網(wǎng)關(guān)層的流量可能走到任何一臺服務(wù)器,比如 A 用戶的請求到服務(wù)器上了,這時服務(wù)器一定要有 A 這個用戶 userId 分片的數(shù)據(jù)庫連接,否則要么把流量路由走,要么執(zhí)行失敗。
分庫分表只是解決了單庫單表訪問壓力的問題,但是由于每一臺服務(wù)器都同時連接所有的分庫實例,到一定階段是沒發(fā)繼續(xù)擴容的,因為庫實例的連接數(shù)有瓶頸。
那數(shù)據(jù)庫存在瓶頸怎么弄?
相信聰明的你們其實已經(jīng)猜到了,那就是按 userId 分片在應(yīng)用層就做隔離,在網(wǎng)關(guān)層流量路由的時候把指定 uid 分片的流量路由到指定應(yīng)用單元執(zhí)行,這個應(yīng)用單元流量內(nèi)部自消化,如下圖:
比如 uid = 37487834,最后二位是 34 屬于 00-49 范圍,那用戶流量直接路由到 00-49 這個應(yīng)用分組,在這個單元內(nèi)的完成所有數(shù)據(jù)交互的操作。
這樣 uid 00-49 這個分組單元中的應(yīng)用只用連 userId 00-49 分庫的數(shù)據(jù)庫,uid 50-99 分組單元的應(yīng)用也是如此,數(shù)據(jù)庫的連接數(shù)一下直接降一半,而且還可以拆分單元,現(xiàn)在是 2 個單元,最多可以拆分到 100 個單元。
這里我加重了單元這個詞,因為這個是 LDC 中核心概念,下面重點說一下單元這個詞的具體含義。
單元在螞蟻有個名稱叫做 Zone,Zone 內(nèi)部署的是完整的服務(wù)。
例如,一個用戶在一個 Zone 內(nèi)可以完成一整套業(yè)務(wù)流程,流量不需要其他 Zone 來提供服務(wù),擁有完成一整套服務(wù)的能力,在單個 Zone 就能完成一整套業(yè)務(wù),是邏輯自包含的。
這樣有什么好處?某個 Zone 如果出現(xiàn)故障,路由層直接把這個 Zone 流量轉(zhuǎn)移到其他 Zone,接受這個 Zone 流量的其他幾個 Zone 可以分?jǐn)偭髁?,流量調(diào)撥很方便。
下面這張圖是螞蟻 Zone 按照地區(qū)和 userId 分片的部署架構(gòu)示意圖,做了一些簡化,實際 Zone 部署單元會稍微復(fù)雜一點。
上面介紹的 Zone 是有能力完成 uid 維度的一整套業(yè)務(wù)流程的,應(yīng)用互相依賴的服務(wù)都由本 Zone 提供,服務(wù)之間的調(diào)用都在本 Zone 內(nèi)完成的。
但是聰明的你可以會想到一個問題,有的數(shù)據(jù)不能按照 userid 維度拆分,全局只有一份怎么搞,比如配置中心的數(shù)據(jù),那是集中存儲的,全局只有一份配置,配置后也是全局生效。
其實在螞蟻內(nèi)部,Zone 一共分為三種:
- RZone:上面說的邏輯自包含的,業(yè)務(wù)系統(tǒng)整體部署的最小單元,能夠按照userId維度拆分服務(wù)和庫的都部署在 RZone 內(nèi)。
- GZone:是 Global Zone,聽這個名字,也知道,GZone 的服務(wù)和庫全局只會部署一份,一定是在某個機房的,異地也會部署,但是只是為了災(zāi)備,不會啟用。
- CZone:比較有意思,為什么會有 CZone,是為了解決 GZone 的弊端而產(chǎn)生的,跨城調(diào)用,因為距離原因耗時比較高,如果 GZone 的服務(wù)部署在上海,杭州機房的服務(wù)需要用到 GZone 部署的服務(wù),只能跨城跨機房調(diào)用。
很可能一個服務(wù)有很多次 RPC 調(diào)用,這樣耗時一定會很爆炸,那怎么弄?在城市與城市之間架起一座數(shù)據(jù)同步的橋梁,CZone 就是起到了橋梁的作用,負(fù)責(zé)把 GZone 的數(shù)據(jù)在城市之前同步,C 是 city 的意思。
也是因為前面我提到的“寫讀時間差現(xiàn)象”,寫入 GZone 的數(shù)據(jù),允許一定的延遲,同步 CZone 同步給其他 CZone。
作者:安琪拉
編輯:陶家龍
出處:轉(zhuǎn)載自公眾號安琪拉的博客(ID:guofuangela)