溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

發(fā)布時(shí)間:2021-11-10 15:33:32 來(lái)源:億速云 閱讀:155 作者:iii 欄目:關(guān)系型數(shù)據(jù)庫(kù)

本篇內(nèi)容介紹了“Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

摘要: 2014 年,Uber 構(gòu)建了可擴(kuò)展的容錯(cuò)數(shù)據(jù)庫(kù) Schemaless,但隨著業(yè)務(wù)的增長(zhǎng),原實(shí)現(xiàn)方式對(duì)資源消耗更多,同時(shí)請(qǐng)求延遲也在增加,為了保持 Schemaless 的性能,Uber 在不影響生產(chǎn)服務(wù)的情況下用 Go 重寫(xiě)了 Schemaless 數(shù)據(jù)庫(kù)的分片層,完成了將產(chǎn)品系統(tǒng)從舊實(shí)現(xiàn)遷移到新實(shí)現(xiàn)的 Frontless 項(xiàng)目。

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

2014 年,Uber 工程構(gòu)建了可擴(kuò)展的容錯(cuò)數(shù)據(jù)庫(kù) Schemaless ,為公司的快速發(fā)展提供了便利。我們僅在 2016 年就部署了 40 多個(gè) Schemaless 實(shí)例和數(shù)千個(gè)存儲(chǔ)節(jié)點(diǎn)。

隨著業(yè)務(wù)的增長(zhǎng),我們的資源消耗和延遲也在增長(zhǎng);為了保持 Schemaless 的性能,我們需要一個(gè)能夠很好的支持大規(guī)模應(yīng)用的解決方案。在明確了假如將現(xiàn)有 Schemaless“集群”的 Python 工作節(jié)點(diǎn)用 Go (一種支持輕量級(jí)并發(fā)特性的語(yǔ)言) 重寫(xiě)的話(huà),我們的數(shù)據(jù)庫(kù)可以獲得顯著的性能提升后,我們?cè)诓挥绊懻Ia(chǎn)的情況下,完成了將產(chǎn)品系統(tǒng)從舊實(shí)現(xiàn)遷移到新實(shí)現(xiàn)的任務(wù)。這一任務(wù)被稱(chēng)為 Frontless 項(xiàng)目,它證明了我們可以在不影響生產(chǎn)服務(wù)的情況下重寫(xiě)大型數(shù)據(jù)庫(kù)的前端。

在本文中, 我們會(huì)討論如何將 Schemaless 分片層從 Python 遷移到 Go,這一改變可以使我們用更少的資源來(lái)處理更多的流量,從而改善用戶(hù)對(duì)我們服務(wù)的體驗(yàn)。

Schemaless 的背景

作為 Mezzanine 項(xiàng)目 ,Schemaless 于 2014 年 10 月首次推出,當(dāng)初計(jì)劃將 Uber 的核心 trip 數(shù)據(jù)庫(kù)從一個(gè)獨(dú)立的 Postgres 實(shí)例遷移到一個(gè)高可用的數(shù)據(jù)庫(kù)中。

包含核心 trip 數(shù)據(jù)的 Mezzanine 數(shù)據(jù)庫(kù)被構(gòu)建為第一個(gè) Schemaless 實(shí)例。從那時(shí)算起,目前已經(jīng)部署了 40 多個(gè) Schemaless 實(shí)例用于眾多客戶(hù)端服務(wù)。(關(guān)于我們內(nèi)部數(shù)據(jù)庫(kù)的完整歷史演進(jìn)過(guò)程,請(qǐng)參閱我們的三篇系列文章,Schemaless 的 設(shè)計(jì) 、 架構(gòu) 和 triggers 概述)。

在 2016 年中,有數(shù)千個(gè)工作節(jié)點(diǎn)在 Schemaless 實(shí)例中運(yùn)行,每個(gè)工作節(jié)點(diǎn)都消耗大量的資源。工作節(jié)點(diǎn)最初是使用 Python 和由 NGINX 交付的 uWSGI 應(yīng)用程序服務(wù)器進(jìn)程中的一個(gè) Flask 微框架構(gòu)建的,每個(gè) uWSGI 進(jìn)程一次處理一個(gè)請(qǐng)求。

該模型簡(jiǎn)單易行,易于建立,但不能有效地滿(mǎn)足我們的需求。為了處理額外的同步請(qǐng)求,我們必須增加更多的 uWSGI 進(jìn)程,每個(gè)進(jìn)程都作為一個(gè)需要額外開(kāi)銷(xiāo)的新的 Linux 進(jìn)程,因而這從根本上限制了并發(fā)線(xiàn)程的數(shù)量。在 Go 中,goroutines 被用來(lái)構(gòu)建并發(fā)程序。goroutine 采用輕量級(jí)設(shè)計(jì),是由 Go 的運(yùn)行時(shí)系統(tǒng)管理的線(xiàn)程。

為了研究重寫(xiě) Schemaless 分片層的優(yōu)化增益,我們創(chuàng)建了一個(gè)實(shí)驗(yàn)性的工作節(jié)點(diǎn),該節(jié)點(diǎn)實(shí)現(xiàn)了一個(gè)使用頻率較高、資源消耗也比較高的端點(diǎn)。重寫(xiě)的結(jié)果顯示,延遲減少了 85%,資源消耗減少的甚至更多。

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

圖 1:該圖描述了 Frontless 形式實(shí)現(xiàn)的端點(diǎn)中值請(qǐng)求延遲情況

在進(jìn)行了這個(gè)實(shí)驗(yàn)之后,我們明確了重寫(xiě)將使 Schemaless 通過(guò)釋放 CPU 和內(nèi)存來(lái)支持其所有實(shí)例中的依賴(lài)服務(wù)和工作節(jié)點(diǎn)。有了這些知識(shí)基礎(chǔ),我們啟動(dòng)了這個(gè) Frontless 項(xiàng)目,用 Go 重寫(xiě)整個(gè) Schemaless 分片層。

Frontless 架構(gòu)設(shè)計(jì)

為了成功地重寫(xiě) Uber 技術(shù)堆棧 的這個(gè)重要部分,我們需要確保我們的重新實(shí)現(xiàn) 100% 與現(xiàn)有的工作節(jié)點(diǎn)兼容。我們做了一個(gè)關(guān)鍵的決定,以驗(yàn)證新實(shí)現(xiàn)與原始代碼的關(guān)系,這意味著每個(gè)對(duì)新 Go 工作節(jié)點(diǎn)的請(qǐng)求都要得到跟之前對(duì) Python 工作節(jié)點(diǎn)請(qǐng)求相同的結(jié)果。

我們估計(jì)一個(gè)完整的重寫(xiě)會(huì)花費(fèi)我們六個(gè)月的時(shí)間。在此期間,在 Uber 的生產(chǎn)系統(tǒng)中實(shí)現(xiàn)的新功能和 bug 修復(fù)將在 Schemaless 的情況下進(jìn)行,所以我們的遷移有了一個(gè)動(dòng)態(tài)的目標(biāo)。我們選擇了迭代開(kāi)發(fā)形式,這樣我們就可以一次性在一個(gè)端點(diǎn)上不斷的從遺留的 Python 代碼庫(kù)中遷移出功能,并同時(shí)在新的 Go 代碼庫(kù)中驗(yàn)證。

最初,F(xiàn)rontless 工作節(jié)點(diǎn)只是在現(xiàn)有的 uWSGI Schemaless 工作節(jié)點(diǎn)前面的一個(gè)代理,所有請(qǐng)求都通過(guò)該節(jié)點(diǎn)。迭代將從重新實(shí)現(xiàn)一個(gè)端點(diǎn)開(kāi)始,然后在生產(chǎn)中進(jìn)行驗(yàn)證;當(dāng)不再有錯(cuò)誤出現(xiàn)后,新的實(shí)現(xiàn)才會(huì)正式上線(xiàn)。

從部署的角度來(lái)看,F(xiàn)rontless 和 uWSGI Schemaless 的工作是一起構(gòu)建和部署的,這使得在所有實(shí)例中都可以實(shí)現(xiàn)統(tǒng)一的 Frontless,并同時(shí)支持所有生產(chǎn)場(chǎng)景的驗(yàn)證。

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

圖 2:在我們的遷移過(guò)程中,一個(gè)名為 worker 節(jié)點(diǎn)的服務(wù),其中 Frontless 和 Schemaless 在同一個(gè)容器中運(yùn)行。Frontless 隨后收到請(qǐng)求,并決定是否應(yīng)該將其轉(zhuǎn)發(fā)給 Schemaless,或者由 Frontless 處理。最后,Schemaless 或 Frontless 從存儲(chǔ)節(jié)點(diǎn)獲取結(jié)果,并將其返回給服務(wù)。

讀取端點(diǎn): 對(duì)比驗(yàn)證

我們首先聚焦在用 Go 重新實(shí)現(xiàn)讀取端點(diǎn)上。在我們最初的實(shí)現(xiàn)中,Schemaless 實(shí)例上讀取端點(diǎn)處理平均占用 90% 的流量,并且它也是最消耗資源的。

當(dāng)一個(gè)端點(diǎn)用 Frontless 實(shí)現(xiàn)后,將會(huì)啟動(dòng)驗(yàn)證進(jìn)程,檢測(cè)與 Python 實(shí)現(xiàn)的差異性。Frontless 和 Schemaless 執(zhí)行請(qǐng)求操作時(shí)便會(huì)觸發(fā)驗(yàn)證并對(duì)比響應(yīng)結(jié)果。

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

圖 3:當(dāng)一個(gè)服務(wù)發(fā)送請(qǐng)求到 Frontless 時(shí),它會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給 Schemaless,該請(qǐng)求將通過(guò)查詢(xún)存儲(chǔ)節(jié)點(diǎn)生成響應(yīng)。然后,由 Schemaless 做出的響應(yīng)將返回到 Frontless,并將其轉(zhuǎn)發(fā)給服務(wù)。Frontless 還將通過(guò)查詢(xún)存儲(chǔ)節(jié)點(diǎn)來(lái)創(chuàng)建響應(yīng)。這兩種響應(yīng)是由 Frontless 和 Schemaless 構(gòu)建的,如果出現(xiàn)任何差異,結(jié)果將作為 bug 報(bào)告發(fā)送給 Schemaless 開(kāi)發(fā)團(tuán)隊(duì)。

使用此方法驗(yàn)證,將使發(fā)送到存儲(chǔ)工作節(jié)點(diǎn)的請(qǐng)求數(shù)量增加一倍;為了使請(qǐng)求數(shù)量增加后工作正常,我們添加了配置標(biāo)志來(lái)激活每個(gè)端點(diǎn)的驗(yàn)證,并調(diào)整請(qǐng)求驗(yàn)證的百分比閾值。這樣便可以在幾秒內(nèi)啟動(dòng)或禁用對(duì)指定端點(diǎn)任意部分的驗(yàn)證功能。

寫(xiě)入端點(diǎn):自動(dòng)集成測(cè)試

Schemaless 的寫(xiě)入請(qǐng)求只能一次性成功,所以為了驗(yàn)證這些我們不能再使用以前的策略了。然而,由于與讀取端點(diǎn)相比,在 Schemaless 中寫(xiě)入端點(diǎn)要簡(jiǎn)單得多,因此我們決定通過(guò)自動(dòng)化集成測(cè)試來(lái)測(cè)試它們。

我們建立起了集成測(cè)試環(huán)境,這樣 Schemaless Python 和 Frontless Go 就可以運(yùn)行相同的測(cè)試場(chǎng)景了。測(cè)試是自動(dòng)化的,可以在本地執(zhí)行,也可以在幾分鐘內(nèi)通過(guò)持續(xù)的集成來(lái)執(zhí)行,這可以加快開(kāi)發(fā)周期。

為了規(guī)?;瘻y(cè)試我們的實(shí)現(xiàn),我們?cè)O(shè)置了一個(gè) Schemaless 測(cè)試實(shí)例,其中流量測(cè)試模擬了生產(chǎn)流量。在這個(gè)測(cè)試實(shí)例中,我們將 Schemaless 的 Python 流量寫(xiě)入實(shí)現(xiàn)遷移到了 Frontless 上,并運(yùn)行驗(yàn)證來(lái)確保寫(xiě)入的正確性。

最后,一旦所有實(shí)現(xiàn)都滿(mǎn)足生產(chǎn)環(huán)境時(shí),我們就可以通過(guò)運(yùn)行時(shí)配置將 Schemaless 的 Python 實(shí)現(xiàn)的流量寫(xiě)入功能緩慢地遷移到 Frontless 上,這樣便可以在幾秒鐘內(nèi)將部分流量寫(xiě)入工作移動(dòng)到新的實(shí)現(xiàn)中。

Frontless 的成果

到 2016 年 12 月為止,所有的 Mezzanine 數(shù)據(jù)庫(kù)都是由 Frontless 處理的。如圖 4 所示,所有請(qǐng)求的中值延遲降低了 85%,p99 請(qǐng)求延遲降低了 70%:

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

圖 4:上圖展示了由 Python(Schemaless 的工作語(yǔ)言,用紅色表示) 和 Go(Frontless 的工作語(yǔ)言,用藍(lán)色表示) 實(shí)現(xiàn)時(shí)數(shù)據(jù)庫(kù)請(qǐng)求處理的時(shí)間。

隨著我們 Go 的實(shí)現(xiàn),Schemaless 的 CPU 使用率下降了 85% 以上。這種效率的增加讓我們減少了在所有 Schemaless 實(shí)例中使用工作節(jié)點(diǎn)的數(shù)量,這些節(jié)點(diǎn)也是基于與以前相同的 QPS,這從而提高了節(jié)點(diǎn)利用率。

Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析

圖 5:上面的圖展示了在我們的數(shù)據(jù)庫(kù)中由 Python(Schemaless 工作語(yǔ)言,紅色的) 和 Go(Frontless 的工作語(yǔ)言,藍(lán)色的) 處理的一個(gè)穩(wěn)定的請(qǐng)求流中的 CPU 使用情況。

Frontless 的未來(lái)

Frontless 項(xiàng)目表明,我們有可能在零停機(jī)的情況下,用一種全新的語(yǔ)言重寫(xiě)一個(gè)關(guān)鍵系統(tǒng)。通過(guò)重新實(shí)現(xiàn)服務(wù)而不改變 Schemaless 的現(xiàn)有客戶(hù)端,我們能夠在幾天內(nèi)而不是數(shù)周或幾個(gè)月內(nèi)實(shí)現(xiàn)、驗(yàn)證和啟用端點(diǎn)。重點(diǎn)是,驗(yàn)證過(guò)程 (新的端點(diǎn)實(shí)現(xiàn)與現(xiàn)有生產(chǎn)中的實(shí)現(xiàn)進(jìn)行比較) 給了我們信心,因?yàn)?Frontless 和 Schemaless 可以得到相同的結(jié)果。

然而,最重要的是,我們?cè)谏a(chǎn)中重寫(xiě)關(guān)鍵系統(tǒng)的能力證明了 Uber 迭代開(kāi)發(fā)過(guò)程的可伸縮性。

“Uber用Go重寫(xiě)Schemaless數(shù)據(jù)庫(kù)的分片層分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI