gitlab-ee使用mysql_在 GitLab 我们是如何扩展数据库的
很長(zhǎng)時(shí)間以來 GitLab.com 使用了一個(gè)單個(gè)的 PostgreSQL 數(shù)據(jù)庫服務(wù)器和一個(gè)用于災(zāi)難恢復(fù)的單個(gè)復(fù)制。在 GitLab.com 最初的幾年,它工作的還是很好的,但是隨著時(shí)間的推移,我們看到這種設(shè)置的很多問題,例如,數(shù)據(jù)庫長(zhǎng)久處于重壓之下, CPU 使用率幾乎所有時(shí)間都處于 70% 左右。
在我們使用 PostgreSQL 去跟蹤這些問題時(shí),使用了以下的四種技術(shù):
1、優(yōu)化你的應(yīng)用程序代碼,以使查詢更加高效。
2、使用一個(gè)連接池去減少必需的數(shù)據(jù)庫連接數(shù)量及相關(guān)的資源。
3、跨多個(gè)數(shù)據(jù)庫服務(wù)器去平衡負(fù)載。
4、分片數(shù)據(jù)庫。
連接池
在 PostgreSQL 中,一個(gè)連接是通過啟動(dòng)一個(gè)操作系統(tǒng)進(jìn)程來處理的,這反過來又需要大量的資源,更多的連接(及這些進(jìn)程)將使用你的數(shù)據(jù)庫上的更多的資源。 PostgreSQL 也在?max_connections?設(shè)置中定義了一個(gè)強(qiáng)制的最大連接數(shù)量。一旦達(dá)到這個(gè)限制,PostgreSQL 將拒絕新的連接, 比如,下面的圖表示的設(shè)置:
這里我們的客戶端直接連接到 PostgreSQL,這樣每個(gè)客戶端請(qǐng)求一個(gè)連接。
通過連接池,我們可以有多個(gè)客戶端側(cè)的連接重復(fù)使用一個(gè) PostgreSQL 連接。例如,沒有連接池時(shí),我們需要 100 個(gè) PostgreSQL 連接去處理 100 個(gè)客戶端連接;使用連接池后,我們僅需要 10 個(gè),或者依據(jù)我們配置的 PostgreSQL 連接。這意味著我們的連接圖表將變成下面看到的那樣:
這里我們展示了一個(gè)示例,四個(gè)客戶端連接到 pgbouncer,但不是使用了四個(gè) PostgreSQL 連接,而是僅需要兩個(gè)。
對(duì)于 PostgreSQL 有兩個(gè)最常用的連接池:
pgpool 有一點(diǎn)特殊,因?yàn)樗粌H僅是連接池:它有一個(gè)內(nèi)置的查詢緩存機(jī)制,可以跨多個(gè)數(shù)據(jù)庫負(fù)載均衡、管理復(fù)制等等。另一個(gè) pgbouncer 是很簡(jiǎn)單的:它就是一個(gè)連接池。
數(shù)據(jù)庫負(fù)載均衡
數(shù)據(jù)庫級(jí)的負(fù)載均衡一般是使用 PostgreSQL 的 “熱備機(jī)hot-standby” 特性來實(shí)現(xiàn)的。 熱備機(jī)是允許你去運(yùn)行只讀 SQL 查詢的 PostgreSQL 副本,與不允許運(yùn)行任何 SQL 查詢的普通備用機(jī)standby相反。要使用負(fù)載均衡,你需要設(shè)置一個(gè)或多個(gè)熱備服務(wù)器,并且以某些方式去平衡這些跨主機(jī)的只讀查詢,同時(shí)將其它操作發(fā)送到主服務(wù)器上。擴(kuò)展這樣的一個(gè)設(shè)置是很容易的:(如果需要的話)簡(jiǎn)單地增加多個(gè)熱備機(jī)以增加只讀流量。
這種方法的另一個(gè)好處是擁有一個(gè)更具彈性的數(shù)據(jù)庫集群。即使主服務(wù)器出現(xiàn)問題,僅使用次級(jí)服務(wù)器也可以繼續(xù)處理 Web 請(qǐng)求;當(dāng)然,如果這些請(qǐng)求最終使用主服務(wù)器,你可能仍然會(huì)遇到錯(cuò)誤。
然而,這種方法很難實(shí)現(xiàn)。例如,一旦它們包含寫操作,事務(wù)顯然需要在主服務(wù)器上運(yùn)行。此外,在寫操作完成之后,我們希望繼續(xù)使用主服務(wù)器一會(huì)兒,因?yàn)樵谑褂卯惒綇?fù)制的時(shí)候,熱備機(jī)服務(wù)器上可能還沒有這些更改。
分片
分片是水平分割你的數(shù)據(jù)的行為。這意味著數(shù)據(jù)保存在特定的服務(wù)器上并且使用一個(gè)分片鍵檢索。例如,你可以按項(xiàng)目分片數(shù)據(jù)并且使用項(xiàng)目 ID 做為分片鍵。當(dāng)你的寫負(fù)載很高時(shí),分片數(shù)據(jù)庫是很有用的(除了一個(gè)多主設(shè)置外,均衡寫操作沒有其它的簡(jiǎn)單方法),或者當(dāng)你有大量的數(shù)據(jù)并且你不再使用傳統(tǒng)方式保存它也是有用的(比如,你不能把它簡(jiǎn)單地全部放進(jìn)一個(gè)單個(gè)磁盤中)。
不幸的是,設(shè)置分片數(shù)據(jù)庫是一個(gè)任務(wù)量很大的過程,甚至,在我們使用諸如?Citus 的軟件時(shí)也是這樣。你不僅需要設(shè)置基礎(chǔ)設(shè)施 (不同的復(fù)雜程序取決于是你運(yùn)行在你自己的數(shù)據(jù)中心還是托管主機(jī)的解決方案),你還得需要調(diào)整你的應(yīng)用程序中很大的一部分去支持分片。
GitLab 的連接池
對(duì)于連接池我們有兩個(gè)主要的訴求:
1、它必須工作的很好(很顯然這是必需的)。
2、它必須易于在我們的 Omnibus 包中運(yùn)用,以便于我們的用戶也可以從連接池中得到好處。
用下面兩步去評(píng)估這兩個(gè)解決方案(pgpool 和 pgbouncer):
1、執(zhí)行各種技術(shù)測(cè)試(是否有效,配置是否容易,等等)。
2、找出使用這個(gè)解決方案的其它用戶的經(jīng)驗(yàn),他們遇到了什么問題?怎么去解決的?等等。
pgpool 是我們考察的第一個(gè)解決方案,主要是因?yàn)樗峁┑暮芏嗵匦钥雌饋砗苡形ΑN覀兤渲械囊恍y(cè)試數(shù)據(jù)可以在?這里?找到。
最終,基于多個(gè)因素,我們決定不使用 pgpool 。例如, pgpool 不支持粘連接sticky connection。 當(dāng)執(zhí)行一個(gè)寫入并(嘗試)立即顯示結(jié)果時(shí),它會(huì)出現(xiàn)問題。想像一下,創(chuàng)建一個(gè)工單issue并立即重定向到這個(gè)頁面, 沒有想到會(huì)出現(xiàn) HTTP 404,這是因?yàn)槿魏斡糜谥蛔x查詢的服務(wù)器還沒有收到數(shù)據(jù)。針對(duì)這種情況的一種解決辦法是使用同步復(fù)制,但這會(huì)給表帶來更多的其它問題,而我們希望避免這些問題。
另一個(gè)問題是, pgpool 的負(fù)載均衡邏輯與你的應(yīng)用程序是不相干的,是通過解析 SQL 查詢并將它們發(fā)送到正確的服務(wù)器。因?yàn)檫@發(fā)生在你的應(yīng)用程序之外,你幾乎無法控制查詢運(yùn)行在哪里。這實(shí)際上對(duì)某些人也可能是有好處的, 因?yàn)槟悴恍枰~外的應(yīng)用程序邏輯。但是,它也妨礙了你在需要的情況下調(diào)整路由邏輯。
由于配置選項(xiàng)非常多,配置 pgpool 也是很困難的。或許促使我們最終決定不使用它的原因是我們從過去使用過它的那些人中得到的反饋。即使是在大多數(shù)的案例都不是很詳細(xì)的情況下,我們收到的反饋對(duì) pgpool 通常都持有負(fù)面的觀點(diǎn)。雖然出現(xiàn)的報(bào)怨大多數(shù)都與早期版本的 pgpool 有關(guān),但仍然讓我們懷疑使用它是否是個(gè)正確的選擇。
結(jié)合上面描述的問題和反饋,最終我們決定不使用 pgpool 而是使用 pgbouncer 。我們用 pgbouncer 執(zhí)行了一套類似的測(cè)試,并且對(duì)它的結(jié)果是非常滿意的。它非常容易配置(而且一開始不需要很多的配置),運(yùn)用相對(duì)容易,僅專注于連接池(而且它真的很好),而且沒有明顯的負(fù)載開銷(如果有的話)。也許我唯一的報(bào)怨是,pgbouncer 的網(wǎng)站有點(diǎn)難以導(dǎo)航。
使用 pgbouncer 后,通過使用事務(wù)池transaction pooling我們可以將活動(dòng)的 PostgreSQL 連接數(shù)從幾百個(gè)降到僅 10 - 20 個(gè)。我們選擇事務(wù)池是因?yàn)?Rails 數(shù)據(jù)庫連接是持久的。這個(gè)設(shè)置中,使用會(huì)話池session pooling不能讓我們降低 PostgreSQL 連接數(shù),從而受益(如果有的話)。通過使用事務(wù)池,我們可以調(diào)低 PostgreSQL 的?max_connections?的設(shè)置值,從 3000 (這個(gè)特定值的原因我們也不清楚) 到 300 。這樣配置的 pgbouncer ,即使在尖峰時(shí),我們也僅需要 200 個(gè)連接,這為我們提供了一些額外連接的空間,如?psql?控制臺(tái)和維護(hù)任務(wù)。
對(duì)于使用事務(wù)池的負(fù)面影響方面,你不能使用預(yù)處理語句,因?yàn)?PREPARE?和?EXECUTE?命令也許最終在不同的連接中運(yùn)行,從而產(chǎn)生錯(cuò)誤的結(jié)果。 幸運(yùn)的是,當(dāng)我們禁用了預(yù)處理語句時(shí),并沒有測(cè)量到任何響應(yīng)時(shí)間的增加,但是我們?確定 測(cè)量到在我們的數(shù)據(jù)庫服務(wù)器上內(nèi)存使用減少了大約 20 GB。
為確保我們的 web 請(qǐng)求和后臺(tái)作業(yè)都有可用連接,我們?cè)O(shè)置了兩個(gè)獨(dú)立的池: 一個(gè)有 150 個(gè)連接的后臺(tái)進(jìn)程連接池,和一個(gè)有 50 個(gè)連接的 web 請(qǐng)求連接池。對(duì)于 web 連接需要的請(qǐng)求,我們很少超過 20 個(gè),但是,對(duì)于后臺(tái)進(jìn)程,由于在 GitLab.com 上后臺(tái)運(yùn)行著大量的進(jìn)程,我們的尖峰值可以很容易達(dá)到 100 個(gè)連接。
今天,我們提供 pgbouncer 作為 GitLab EE 高可用包的一部分。對(duì)于更多的信息,你可以參考?“Omnibus GitLab PostgreSQL High Availability”。
整合連接池和數(shù)據(jù)庫負(fù)載均衡
整合連接池和數(shù)據(jù)庫負(fù)載均衡可以讓我們?nèi)ゴ蠓鶞p少運(yùn)行數(shù)據(jù)庫集群所需要的資源和在分發(fā)到熱備機(jī)上的負(fù)載。例如,以前我們的主服務(wù)器 CPU 使用率一直徘徊在 70%,現(xiàn)在它一般在 10% 到 20% 之間,而我們的兩臺(tái)熱備機(jī)服務(wù)器則大部分時(shí)間在 20% 左右:
CPU Percentage
在這里,?db3.cluster.gitlab.com?是我們的主服務(wù)器,而其它的兩臺(tái)是我們的次級(jí)服務(wù)器。
其它的負(fù)載相關(guān)的因素,如平均負(fù)載、磁盤使用、內(nèi)存使用也大為改善。例如,主服務(wù)器現(xiàn)在的平均負(fù)載幾乎不會(huì)超過 10,而不像以前它一直徘徊在 20 左右:
CPU Percentage
在業(yè)務(wù)繁忙期間,我們的次級(jí)服務(wù)器每秒事務(wù)數(shù)在 12000 左右(大約為每分鐘 740000),而主服務(wù)器每秒事務(wù)數(shù)在 6000 左右(大約每分鐘 340000):
Transactions Per Second
可惜的是,在部署 pgbouncer 和我們的數(shù)據(jù)庫負(fù)載均衡器之前,我們沒有關(guān)于事務(wù)速率的任何數(shù)據(jù)。
我們的 PostgreSQL 的最新統(tǒng)計(jì)數(shù)據(jù)的摘要可以在我們的?public Grafana dashboard 上找到。
我們的其中一些 pgbouncer 的設(shè)置如下:
設(shè)置值
default_pool_size
100
reserve_pool_size
5
reserve_pool_timeout
3
max_client_conn
2048
pool_mode
transaction
server_idle_timeout
30
除了前面所說的這些外,還有一些工作要作,比如: 部署服務(wù)發(fā)現(xiàn)(#2042), 持續(xù)改善如何檢查次級(jí)服務(wù)器是否可用(#2866),和忽略落后于主服務(wù)器太多的次級(jí)服務(wù)器 (#2197)。
值得一提的是,到目前為止,我們還沒有任何計(jì)劃將我們的負(fù)載均衡解決方案,獨(dú)立打包成一個(gè)你可以在 GitLab 之外使用的庫,相反,我們的重點(diǎn)是為 GitLab EE 提供一個(gè)可靠的負(fù)載均衡解決方案。
如果你對(duì)它感興趣,并喜歡使用數(shù)據(jù)庫、改善應(yīng)用程序性能、給 GitLab上增加數(shù)據(jù)庫相關(guān)的特性(比如:?服務(wù)發(fā)現(xiàn)),你一定要去查看一下我們的?招聘職位?和 ?數(shù)據(jù)庫專家手冊(cè)?去獲取更多信息。
總結(jié)
以上是生活随笔為你收集整理的gitlab-ee使用mysql_在 GitLab 我们是如何扩展数据库的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Rulo扫地机器人app_扫地机器人怎么
- 下一篇: jspx格式手机打开_制作手机浏览器显示