如何構(gòu)建企業(yè)內(nèi)的 TiDB 自運(yùn)維體系
1、前言
得物 App 從創(chuàng)立之初,關(guān)系型數(shù)據(jù)庫(kù)一直使用的開(kāi)源數(shù)據(jù)庫(kù)產(chǎn)品 MySQL。和絕大部分互聯(lián)網(wǎng)公司一樣,隨著業(yè)務(wù)高速增長(zhǎng)、數(shù)據(jù)量逐步增多,單實(shí)例、單庫(kù)、單表出現(xiàn)性能瓶頸和存儲(chǔ)瓶頸。從選型和架構(gòu)設(shè)計(jì)角度來(lái)看這很符合發(fā)展規(guī)律,一開(kāi)始沒(méi)必要引入過(guò)于復(fù)雜的架構(gòu)導(dǎo)致資源成本和開(kāi)發(fā)成本過(guò)高,而是逐步隨著業(yè)務(wù)發(fā)展速度去迭代架構(gòu)。為了應(yīng)對(duì)這些問(wèn)題,我們采取了諸多措施如單庫(kù)按業(yè)務(wù)邏輯拆分成多個(gè)庫(kù)的垂直拆分,分庫(kù)分表的水平拆分、一主多從讀寫(xiě)分離等。這些技改同時(shí)也使得整個(gè)業(yè)務(wù)層架構(gòu)更加復(fù)雜,且無(wú)法做到透明的彈性,因此我們逐步把目光轉(zhuǎn)向了已經(jīng)趨于成熟的分布式關(guān)系型數(shù)據(jù)庫(kù) TiDB。
?自 2020 年初開(kāi)始使用 TiDB,隨著運(yùn)維體系的逐步完善,產(chǎn)品自身能力的逐步提升,接入業(yè)務(wù)已經(jīng)涉及得物的多個(gè) 業(yè)務(wù)線,其中個(gè)別為關(guān)鍵業(yè)務(wù)場(chǎng)景。業(yè)界關(guān)于 TiDB 的功能剖析、場(chǎng)景落地、平臺(tái)化建設(shè)都有很多優(yōu)秀的文章。本文基于得物內(nèi)部的實(shí)踐情況,會(huì)從選型策略、運(yùn)維手段、運(yùn)營(yíng)方式、核心場(chǎng)景實(shí)踐等幾個(gè)方向講述TiDB 在得物實(shí)踐落地過(guò)程。
2、TiDB 架構(gòu)
上圖是我們目前的接入方式和整體架構(gòu)。TiDB 的部署架構(gòu)這里就不做贅述了,需要了解的同學(xué)可以參考官方文檔。我們之所以采用 SLB 來(lái)做 TiDB 的負(fù)載均衡接入,就是為了簡(jiǎn)化接入成本與運(yùn)維成本,訪問(wèn)流量的負(fù)載均衡以及節(jié)點(diǎn)擴(kuò)縮容可以通過(guò)調(diào)整 SLB 解決。當(dāng)然如果能夠?qū)崿F(xiàn) SDK 負(fù)載均衡與故障剔除,結(jié)合配置中心的流量調(diào)度也是非常好的解決方案。得物 TiDB 部署均采用單機(jī)單實(shí)例部署,TiDB Server、PD 采用無(wú)本地 SSD 機(jī)型,TiKV 采用本地 SSD 機(jī)型。既兼顧了性能,又能降低成本。詳細(xì)的機(jī)型選擇會(huì)在后面的內(nèi)容提到。
3、MySQL 與 TiDB 的對(duì)比
圈內(nèi)一直流傳著一句話,沒(méi)有一種數(shù)據(jù)庫(kù)是"銀彈"。絕大部分用戶選擇 TiDB 就是為了彌補(bǔ) MySQL 的不足,所以選型階段對(duì)兩者做些比較也是在所難免的。本文基于我們內(nèi)部的現(xiàn)狀和場(chǎng)景對(duì)兩個(gè)產(chǎn)品我們關(guān)注的點(diǎn)進(jìn)行了簡(jiǎn)要對(duì)比。對(duì)比的目的不是為了去印證那個(gè)數(shù)據(jù)庫(kù)產(chǎn)品能力更強(qiáng)。而是想通過(guò)對(duì)比來(lái)幫助團(tuán)隊(duì)在合適的場(chǎng)景選擇合適的產(chǎn)品。
擴(kuò)展性
MySQL
MySQL 就自身擴(kuò)展能力而言主要是來(lái)自于垂直擴(kuò)容,但是這個(gè)會(huì)受限于機(jī)器的規(guī)格上限。水平擴(kuò)容涉及業(yè)務(wù)改造和使用成本提升。改造為分庫(kù)分表,對(duì)研發(fā)來(lái)說(shuō)是一個(gè)費(fèi)力度很高的方案。需要引入 Sharding 邏輯,改造完成后需要業(yè)務(wù) SQL 必須帶 Sharding Key 才能執(zhí)行或者高效執(zhí)行。所以并不是說(shuō)做不到可擴(kuò)展。
TiDB
由于 TiDB 是計(jì)算存儲(chǔ)分離的架構(gòu),且有狀態(tài)的存儲(chǔ)層 TiKV 是分布式存儲(chǔ)。所以單從上面定義的擴(kuò)展性來(lái)說(shuō),確實(shí)對(duì)比 MySQL 有很大優(yōu)勢(shì)。集群處理能力和存儲(chǔ)能力,可以通過(guò)擴(kuò)容 TiDB Server、TiKV 簡(jiǎn)單實(shí)現(xiàn)。這里需要注意的是,TiKV 屬于有狀態(tài)服務(wù),擴(kuò)容會(huì)涉及到數(shù)據(jù)的 Reblance,過(guò)程中 TiKV(region 遷移) 和 PD(調(diào)度) 產(chǎn)生大量交互,為避免影響業(yè)務(wù),擴(kuò)縮容過(guò)程中需要關(guān)注集群情況,根據(jù)需求適當(dāng)調(diào)整遷移力度。
性能
MySQL
關(guān)于 RT。MySQL 由于是單機(jī)數(shù)據(jù)庫(kù),所以對(duì)于點(diǎn)查或簡(jiǎn)單查詢的 RT、熱點(diǎn)更新的 RT 與 TPS ,相比分布式數(shù)據(jù)庫(kù)有天然優(yōu)勢(shì)。數(shù)據(jù)獲取鏈路短(單機(jī)數(shù)據(jù)庫(kù)本地調(diào)用,分布式數(shù)據(jù)庫(kù)涉及存算分離),且不用考慮分布式事務(wù)的沖突檢測(cè)。所以總體的訪問(wèn) RT 要低于 TiDB,具體數(shù)據(jù)這邊就不羅列了,社區(qū)有不少性能壓測(cè)的帖子。
關(guān)于聚合查詢。互聯(lián)網(wǎng)公司在 C 端基本不存在此類(lèi)問(wèn)題,也是不允許的。所以主要是場(chǎng)景在 B 端。解決方法一般是分為幾種:1.提供專(zhuān)門(mén)的只讀實(shí)例給 B 端提供查詢能力;2.異構(gòu)數(shù)據(jù)來(lái)解決(MySQL+ES、ADB 等等)。
關(guān)于優(yōu)化器。MySQL 多年的積累,在優(yōu)化器的穩(wěn)定性雖然不如商用數(shù)據(jù)庫(kù)那么可靠,偶爾也有走錯(cuò)索引的情況。一般只能通過(guò)修改 SQL、修改索引來(lái)解決,切記別用 force index 這種有坑的解決方案。但是總體來(lái)說(shuō)我們遇到的 MySQL 走錯(cuò)索引的情況要遠(yuǎn)低于 TiDB。
TiDB
關(guān)于 RT。分布式數(shù)據(jù)庫(kù)解決的更多是吞吐量和容量上的需求,比如點(diǎn)查或簡(jiǎn)單查詢的 RT 無(wú)法像單機(jī)數(shù)據(jù)庫(kù)那么短,但是可以通過(guò)節(jié)點(diǎn)擴(kuò)容的方式提升 QPS 吞吐量。熱點(diǎn)數(shù)據(jù)這里就不展開(kāi)講了,它本身也不是分布式數(shù)據(jù)庫(kù)能解決的范疇。如果你的業(yè)務(wù)場(chǎng)景是一個(gè)對(duì) RT 要求很高的場(chǎng)景,那么優(yōu)先使用 MySQL。如果是高吞吐量需求優(yōu)先,可以嘗試使用 TiDB。
關(guān)于聚合查詢。由于 TiDB 的存儲(chǔ)節(jié)點(diǎn) TiKV 不只是具備存儲(chǔ)能力,TiKV 實(shí)現(xiàn)了coprocessor 框架來(lái)支持分布式計(jì)算的能力。所以理論上通過(guò)加機(jī)器就能擴(kuò)展計(jì)算能力,從我們實(shí)際使用的場(chǎng)景來(lái)看也是如此,這部分的能力就要優(yōu)于 MySQL。具體的效果在本文最后的章節(jié)會(huì)有體現(xiàn)。
關(guān)于優(yōu)化器。這個(gè)是大家對(duì) TiDB 一直以來(lái)吐槽的點(diǎn)之一,有時(shí)候統(tǒng)計(jì)信息健康度 90 以上的情況下,還是會(huì)走錯(cuò)索引,當(dāng)然這里有一部分原因可能是條件過(guò)多和索引過(guò)多導(dǎo)致的。為了解決問(wèn)題,核心服務(wù)上線的 SQL 就必須一一 Review。如果無(wú)法正確使用索引的就使用 SPM 綁定,雖然能解決,但是使用成本還是略高。希望官方繼續(xù)加油。
資源成本
MySQL
如果是一個(gè)數(shù)據(jù)量小且查詢模型比較簡(jiǎn)單的需求(比如:1-2TB,簡(jiǎn)單查詢?yōu)橹?,那么肯定是 MySQL 成本較低。以我們 TiDB 基礎(chǔ)配置為例,相比 MySQL 成本高出 27%(該成本是用高可用的 MySQL 對(duì)標(biāo)3 TiDB、3 TiKV、3 PD 的 TiDB)。所以得物內(nèi)部選型,單從資源成本角度考慮,還是首選 MySQL。
TiDB
如果是一個(gè)數(shù)據(jù)量較大且持續(xù)增長(zhǎng)或查詢模型比較復(fù)雜的需求(比如:3-5 TB 以上,多條件查詢、聚合查詢等)。一般該類(lèi)型的業(yè)務(wù)都采用分庫(kù)分表的解決方案。以得物一個(gè)分庫(kù)分表的集群(10個(gè)寫(xiě)實(shí)例、10個(gè)讀實(shí)例)為例,替換為 TiDB(6 TiDB、12 TiKV、3 PD),成本相比 MySQL 成本節(jié)省 58%。此例子只作為得物一個(gè)業(yè)務(wù)場(chǎng)景的替換結(jié)果,不代表所有場(chǎng)景。為了驗(yàn)證這個(gè)結(jié)論,本文后面的內(nèi)容會(huì)講到這個(gè)核心場(chǎng)景的實(shí)踐。
運(yùn)維成本
MySQL
MySQL 作為被使用最多的開(kāi)源關(guān)系型數(shù)據(jù)庫(kù),從社區(qū)活躍度、產(chǎn)品成熟度、周邊生態(tài)工具、解決方案積累等方面來(lái)看都是非常優(yōu)先的產(chǎn)品。主從架構(gòu)的 MySQL 維護(hù)成本極低,當(dāng)主庫(kù)異常或無(wú)法修復(fù)時(shí),我們只需要切換即可。
另外得益于優(yōu)秀的社區(qū)生態(tài),運(yùn)維工具、數(shù)據(jù)庫(kù)接入組件、數(shù)據(jù)同步組件都有非常多的成熟工具,稍加改造就可以實(shí)現(xiàn)本地化適配。
TiDB
分布式的架構(gòu)的設(shè)計(jì)沒(méi)有像 MySQL 這樣的主從,每個(gè)存儲(chǔ)節(jié)點(diǎn)都是提供讀寫(xiě)。當(dāng)一個(gè)節(jié)點(diǎn)出問(wèn)題的時(shí)候,會(huì)影響整個(gè)集群的訪問(wèn)。無(wú)法實(shí)現(xiàn) MySQL 這樣通過(guò)主從切換實(shí)現(xiàn)快速的故障隔離。
TiDB 由 3 個(gè)角色組成,當(dāng)出現(xiàn)問(wèn)題的時(shí)候無(wú)法快速定位問(wèn)題(當(dāng)然也是我們個(gè)人能力需要提升的點(diǎn)),比如當(dāng)某個(gè)時(shí)間點(diǎn)的查詢超過(guò)預(yù)期的時(shí)候,需要排查執(zhí)行計(jì)劃、各個(gè)節(jié)點(diǎn)的負(fù)載情況、各節(jié)點(diǎn)的網(wǎng)絡(luò)情況。雖然提供了完善的監(jiān)控,但是指標(biāo)與節(jié)點(diǎn)過(guò)多需要一一排查才能有結(jié)論。不像 MySQL 出現(xiàn)查詢超預(yù)期的問(wèn)題,基本上通過(guò)幾個(gè)核心指標(biāo)就能判斷出根因。
結(jié)構(gòu)變更(DDL)
MySQL
這里以我們主要使用的 MySQL 5.7 為例,較大數(shù)據(jù)量的情況下 DDL 成本較高,為了規(guī)避鎖表和主從延遲的問(wèn)題,一般都是用工具去執(zhí)行。我們通常使用的兩個(gè)知名開(kāi)源無(wú)鎖 DDL 工具:Percona 開(kāi)源的 pt-osc、Github 開(kāi)源的 gh-ost。目前我們和大部分公司一樣都在通過(guò)定制化開(kāi)發(fā)的 gh-ost 來(lái)變更。但是用工具只是解決了前面提到的鎖表和主從延遲問(wèn)題,隨著數(shù)據(jù)量規(guī)模上升,變更時(shí)長(zhǎng)也逐步上升。另外工具的 Bug 也會(huì)帶來(lái)數(shù)據(jù)丟失的風(fēng)險(xiǎn)。當(dāng)然 MySQL 8.0 的特性 Instant Add Column 推出以后解決了加列的痛點(diǎn),但是也只解決了一部分。
TiDB
TiDB 的 DDL 通過(guò)實(shí)現(xiàn) Google F1 的在線異步 schema 變更算法,來(lái)完成在分布式場(chǎng)景下的無(wú)鎖,在線 schema 變更。DDL 變更中除過(guò) add index 以外其他都不需要做數(shù)據(jù)回填,修改完元信息即可,所以可以立即完成。而 add index 會(huì)做兩件事情:1.修改 table 的元信息,把 indexInfo加入到 table 的元信息中去;2.把 table 中已有了的數(shù)據(jù)行,把 index columns的值全部回填到 index record中去。變更速度取決于表中的數(shù)據(jù)和系統(tǒng)負(fù)載。所以 TiDB 在 DDL 操作上解決了很多 MySQL 上的痛點(diǎn),但是與 MySQL 相比,TiDB 的 DDL 還是有些不一樣的地方的,也帶來(lái)了一些限制:
- 不能在單條 ALTER TABLE 語(yǔ)句中完成多個(gè)操作。MySQL 下會(huì)把多個(gè)同一張表的 DDL 進(jìn)行合并,然后使用 gh-ost 或者 pt-osc 工具一次性執(zhí)行。TiDB 里只能一個(gè)個(gè)單獨(dú)去執(zhí)行;(6.2 已經(jīng)支持了ALTER TABLE語(yǔ)句增刪改多個(gè)列或索引)
- 不支持不同類(lèi)型的索引 (HASH|BTREE|RTREE|FULLTEXT);
- 不支持添加 / 刪除主鍵,除非開(kāi)啟了 alter-primary-key 配置項(xiàng);
- 不支持將字段類(lèi)型修改為其超集,例如不支持從 INTEGER 修改為 VARCHAR,或者從 TIMESTAMP 修改為 DATETIME,否則可能輸出的錯(cuò)誤信息 Unsupported modify column
- 更改 / 修改數(shù)據(jù)類(lèi)型時(shí),尚未支持“有損更改”,例如不支持從 BIGINT 更改為 INT;
- 更改 / 修改 DECIMAL 類(lèi)型時(shí),不支持更改精度 ;
- 更改 / 修改整數(shù)列時(shí),不允許更改 UNSIGNED 屬性 ;
這里大部分限制可以在結(jié)構(gòu)設(shè)計(jì)階段和后期規(guī)范來(lái)規(guī)避掉,比如一個(gè)表的多個(gè) DDL 操作無(wú)法合并的問(wèn)題,可以通過(guò)自動(dòng)化手段降低復(fù)雜度;BIGINT 更改為 INT 這種長(zhǎng)改短的就是日常變更規(guī)范中要管控的。
產(chǎn)品流行度
MySQL
如果我們從 MySQL 1.0 開(kāi)始算起至今已經(jīng)有 26 年了。這期間幾經(jīng)周轉(zhuǎn),最終歸到了 Oracle 旗下。版本也從 1.0 來(lái)到了 8.0。作為一個(gè)久經(jīng)錘煉的數(shù)據(jù),特別是作為互聯(lián)網(wǎng)盛行時(shí)期依賴(lài)的主流數(shù)據(jù)庫(kù),不論是產(chǎn)品成熟度和社區(qū)活躍度都得到了極大的促進(jìn)。MySQL 在 DB-Engines 的開(kāi)源數(shù)據(jù)庫(kù)中排名久居第一。
圖片數(shù)據(jù)來(lái)源 DB-engines 官網(wǎng)
TiDB
TiDB 從 2015 年創(chuàng)立并開(kāi)源至今已經(jīng) 7 年,作為一個(gè)復(fù)雜的基礎(chǔ)軟件來(lái)說(shuō)確實(shí)還比較年輕。依賴(lài)早期的 3 個(gè)創(chuàng)始人互聯(lián)網(wǎng)背景出身,深知大家在關(guān)系型數(shù)據(jù)庫(kù)上的痛點(diǎn)。所以 TiDB 推出后獲得了不少用戶的推崇,特別是互聯(lián)網(wǎng)行業(yè)。社區(qū)在 TiDB 的發(fā)展中也起到了至關(guān)重要的作用,從打磨產(chǎn)品、需求提煉、落地場(chǎng)景總結(jié)等。目前 TiDB 在 DB-Engines 排名為 98,進(jìn)一步證明了基礎(chǔ)軟件的難度以及作為一款國(guó)產(chǎn)數(shù)據(jù)庫(kù)在國(guó)際化進(jìn)程中還有很大的空間。從墨天輪中國(guó)數(shù)據(jù)庫(kù)排行的情況,可以看到 TiDB 長(zhǎng)期以來(lái)保持第一的位置。在 12 月跌落榜首,由 OceanBase 取代。
圖片數(shù)據(jù)來(lái)源 墨天輪
4、TiDB 在得物的運(yùn)維體系落地及探索?
4.1 選型
關(guān)于數(shù)據(jù)庫(kù)選型,我們一向非常謹(jǐn)慎,會(huì)根據(jù)具體的業(yè)務(wù)情況來(lái)推薦合適的數(shù)據(jù)庫(kù)。要避免陷入“手拿鐵錘的人,看什么都像釘子”的誤區(qū)。不是為了使用 TiDB 而使用,要去解決一些 MySQL 無(wú)法滿足或者改造成本比較高的場(chǎng)景。關(guān)系型數(shù)據(jù)庫(kù)我們還是優(yōu)先推薦MySQL。能用分庫(kù)分表能解決的問(wèn)題盡量選擇 MySQL。畢竟運(yùn)維成本相對(duì)較低、數(shù)據(jù)庫(kù)版本更加穩(wěn)定、單點(diǎn)查詢速度更快、單機(jī)QPS性能更高這些特性是分布式數(shù)據(jù)庫(kù)無(wú)法滿足的。以下是我們總結(jié)的關(guān)于選型的兩個(gè)大方向。
適合接入的場(chǎng)景:
- 分庫(kù)分表場(chǎng)景:上游 MySQL 分庫(kù)分表,業(yè)務(wù)查詢時(shí)無(wú)法使用到分片
- 磁盤(pán)使用大場(chǎng)景: CPU 和內(nèi)存使用率低但磁盤(pán)容量達(dá)到 MySQL 瓶頸
- 分析 SQL 多場(chǎng)景:業(yè)務(wù)邏輯比較復(fù)雜,存在并發(fā)查詢+分析查詢
- 數(shù)據(jù)歸檔場(chǎng)景:數(shù)據(jù)冷熱分離、定期歸檔、數(shù)據(jù)重要,不能丟失
- 日志流水場(chǎng)景:日志流水業(yè)務(wù)、單表較大、寫(xiě)入平穩(wěn)、查詢不多
不適合接入的場(chǎng)景:
- 數(shù)據(jù)抽取場(chǎng)景:下游存在大數(shù)據(jù)或者其他業(yè)務(wù)部門(mén)進(jìn)行數(shù)據(jù)抽取
- 讀寫(xiě)分離的場(chǎng)景: TIDB 沒(méi)有主從的概念,無(wú)法進(jìn)行讀寫(xiě)分離
- 指定點(diǎn)恢復(fù)場(chǎng)景:指定時(shí)間點(diǎn)級(jí)別恢復(fù),需要恢復(fù)到某個(gè)時(shí)間點(diǎn)
- 數(shù)據(jù)熱點(diǎn)場(chǎng)景:高并發(fā)單行更新、熱點(diǎn)小表、熱點(diǎn)庫(kù)存
4.2 運(yùn)維標(biāo)準(zhǔn)化
業(yè)務(wù)接入
場(chǎng)景:當(dāng)業(yè)務(wù)選型考慮TiDB時(shí),我們會(huì)根據(jù)業(yè)務(wù)的使用場(chǎng)景和業(yè)務(wù)特點(diǎn)綜合評(píng)估是否適合TiDB(優(yōu)先 推薦使用MySQL)。
配置:評(píng)估業(yè)務(wù)成本壓力和未來(lái)一年數(shù)據(jù)量、TPS,選擇合適的TiDB集群配置。
使用:給使用方提供 MySQL 和 TiDB 的差異及其規(guī)范,避免增加開(kāi)發(fā)周期和成本。
資源規(guī)格
根據(jù)不同業(yè)務(wù)場(chǎng)景,我們定義了不同的服務(wù)器配置。由于借助云上的資源交付能力和隔離能力, 我們無(wú)需像 IDC 那樣,在高規(guī)格機(jī)器上采用多實(shí)例部署。這樣避免了混部帶來(lái)兩個(gè)問(wèn)題:1.多個(gè)實(shí)例之間的資源爭(zhēng)奪;2.高規(guī)則機(jī)器部署密度與穩(wěn)定性的權(quán)衡。
節(jié)點(diǎn) | 數(shù)量 | 配置 |
TIDB | 3 | 基礎(chǔ)規(guī)格:8C32G200GB(云盤(pán)) 高配規(guī)格:16C64G200GB(云盤(pán)) |
PD | 3 | 基礎(chǔ)規(guī)格:8C16G200GB(云盤(pán)) 高配規(guī)格:16C64G200G(云盤(pán)) |
Monitor | 1 | 4C16G200GB(云盤(pán)) |
TIKV/TIFLASH | 3 | 基礎(chǔ)規(guī)格:8C32G1788G(本地SSD) 高配規(guī)格:16C64G1788G(本地SSD) |
數(shù)據(jù)庫(kù)備份
備份工具:BR[官方物理備份工具]
備份策略:凌晨低峰期進(jìn)行數(shù)據(jù)全量備份
備份保留周期:7天
在線業(yè)務(wù)
對(duì)于在線業(yè)務(wù),除了常規(guī)的BR備份外會(huì)額外調(diào)整 tikv_gc_life_time 時(shí)間為 1-3 天,當(dāng)業(yè)務(wù)出現(xiàn)誤操作時(shí)可以恢復(fù)三天內(nèi)任意時(shí)間的數(shù)據(jù)。
離線業(yè)務(wù)
TiDB集群離線業(yè)務(wù)大部分是從上游RDS同步到TiDB的場(chǎng)景。上游RDS會(huì)有一份最近的數(shù)據(jù),所以對(duì)于離線業(yè)務(wù)只有常規(guī)的BR備份。
4.3 穩(wěn)定性治理
變更管理
面向 DBA 的流程管控
上圖的流程主要是用于管控非白屏化的 TiDB 基礎(chǔ)設(shè)施變更。通過(guò)變更文檔整理、運(yùn)維小組 Review 的機(jī)制,確保復(fù)雜變更的規(guī)范化。
面向研發(fā)變更的系統(tǒng)管控
DML\DDL 變更工單風(fēng)險(xiǎn)自動(dòng)化識(shí)別
語(yǔ)法檢查:
- DDL 與 DML 類(lèi)型判斷,確保每次執(zhí)行的內(nèi)容是同一個(gè)類(lèi)型
- SQL 語(yǔ)法檢查,確保提交的 SQL 語(yǔ)法是正確的
合規(guī)檢查:
變更合規(guī)性檢查,確保提交的 SQL 是可以按照 DBA 定義的規(guī)范設(shè)計(jì)(可以使用的字段類(lèi)型、字段命名、索引命名、索引數(shù)量,字段長(zhǎng)度由長(zhǎng)修改短等限制),簡(jiǎn)單說(shuō)就是要么允許,要么不允許
風(fēng)險(xiǎn)識(shí)別:
- 該項(xiàng)的作用是將允許執(zhí)行的進(jìn)行風(fēng)險(xiǎn)識(shí)別,研發(fā)可以根據(jù)風(fēng)險(xiǎn)等級(jí)選擇執(zhí)行時(shí)間,DBA 也能在審批階段判斷是否合理,并修改執(zhí)行時(shí)間。
- 相關(guān)風(fēng)險(xiǎn)定義
變更類(lèi)型 | 變更項(xiàng) | 風(fēng)險(xiǎn)提示 |
DDL | Create table | 低 |
Add index | 測(cè)試環(huán)境(低) 生產(chǎn)環(huán)境(表大小,低/中/高) | |
Add column | 低 | |
Modify column 類(lèi)型有限修改 | 高 | |
Modify column 長(zhǎng)度 變長(zhǎng) | 低 | |
Drop index | 測(cè)試環(huán)境(低) 生產(chǎn)環(huán)境(高) | |
Truncate table | 測(cè)試環(huán)境(低) 生產(chǎn)環(huán)境(高) | |
DML | update/delete | 測(cè)試環(huán)境(低) 生產(chǎn)環(huán)境(修改數(shù)量,低/中/高) |
insert | 低 |
下圖是基于以上提到的能力,實(shí)現(xiàn)的 TiDB 變更管控功能。
穩(wěn)定性巡檢
數(shù)據(jù)庫(kù)巡檢手段是相當(dāng)于告警比較前置的一個(gè)動(dòng)作,巡檢閾值相比告警較低,目的是為了提前發(fā)現(xiàn)問(wèn)題并跟進(jìn)解決。收益是:1.降低告警數(shù)量;2.避免小問(wèn)題逐步積累導(dǎo)致大問(wèn)題。我們的做法是按照自定義的評(píng)分規(guī)則,雙日晨會(huì)對(duì)焦,對(duì)有風(fēng)險(xiǎn)的服務(wù)進(jìn)行問(wèn)題跟進(jìn)。
巡檢指標(biāo)的數(shù)據(jù)采集來(lái)自于監(jiān)控系統(tǒng),我們會(huì)統(tǒng)計(jì)相關(guān)指標(biāo)的峰值。每天記錄一個(gè)點(diǎn),展示近 30 天內(nèi)的指標(biāo)值。
某集群的巡檢情況?
慢查治理
雖然 TiDB 自帶的 Dashboard 可以提供慢查的白屏化,但是這需要提供賬號(hào)給研發(fā),5.0 之前的版本還必須使用 root 賬號(hào)登錄,另外就是我們希望慢查治理可以結(jié)合內(nèi)部系統(tǒng)進(jìn)行管理。所以對(duì)于這部分做了些自研工作,將日志采集并加工后存入 ES。DBA 平臺(tái)可以通過(guò)報(bào)表等手段進(jìn)行推進(jìn)治理。
下面兩張圖就是我們內(nèi)部的平臺(tái)對(duì)慢查治理的閉環(huán)管理方案。DBA 或者研發(fā) TL 在平臺(tái)指派 SQL,處理人就會(huì)收到治理消息,處理完成后可以在后臺(tái)進(jìn)行狀態(tài)變更。然后基于這些數(shù)據(jù)可以做報(bào)表優(yōu)化治理效果。
告警管理
基于 TiDB 官方的監(jiān)控方案,我們?cè)诟婢糠肿隽诵┒ㄖ苹琍rometheus 中配置的 rule 觸發(fā)后會(huì)把告警信息推送至我們自己的數(shù)據(jù)庫(kù)管理平臺(tái) OneDBA,由平臺(tái)處理后進(jìn)行發(fā)送。平臺(tái)的告警管理模塊的實(shí)現(xiàn)類(lèi)似于 Alertmanager,不同的我們新增了自定義的需求,比如元信息關(guān)聯(lián)、支持集群指標(biāo)級(jí)別的閾值定義、告警沉默、告警降噪、告警治理閉環(huán)(有告警通知和認(rèn)領(lǐng),確保及時(shí)跟進(jìn)處理)。另外這里的 Prometheus 主要功能是做數(shù)據(jù)采集與告警,數(shù)據(jù)存儲(chǔ)與趨勢(shì)圖查看在公司統(tǒng)一監(jiān)控平臺(tái),降低不必要的存儲(chǔ)資源投入。由于我們管理的數(shù)據(jù)庫(kù)類(lèi)型比較多,所以在告警方案上做了收斂。這里講到的方案就是得物數(shù)據(jù)庫(kù)團(tuán)隊(duì)目前針對(duì)負(fù)責(zé)的所有數(shù)據(jù)庫(kù)的管理方案。
閾值管理
故障演練
故障演練的目的是為了鞏固目前的系統(tǒng)高可用。我們針對(duì) TiDB 制定了一套故意演練流程,包含了 8 個(gè)場(chǎng)景。
【演練場(chǎng)景1】TiKV Server 1 個(gè)節(jié)點(diǎn)宕機(jī)
【演練場(chǎng)景2】TiDB Server 1 個(gè)節(jié)點(diǎn)宕機(jī)
【演練場(chǎng)景3】PD Server 1 個(gè)節(jié)點(diǎn)宕機(jī)
【演練場(chǎng)景4】PD Server 節(jié)點(diǎn)重啟
【演練場(chǎng)景5】TiKV Server 節(jié)點(diǎn)重啟
【演練場(chǎng)景6】應(yīng)用高并發(fā)寫(xiě)入,CPU、IO告警是否及時(shí)發(fā)送
【演練場(chǎng)景7】PD Server Leader、follow節(jié)點(diǎn)重啟
【演練場(chǎng)景8】TiDB 集群 宕機(jī)一個(gè)TiDB Server節(jié)點(diǎn)
以上的場(chǎng)景我們通過(guò) ChaosBlade 實(shí)現(xiàn)了 100% 自動(dòng)化故障注入。故障演練也促使我們達(dá)成整個(gè)技術(shù)部的目標(biāo):1 分鐘發(fā)現(xiàn),5 分鐘止損,10 分鐘定位。目前也正在計(jì)劃將該流程引入新集群交付前以及版本升級(jí)后的標(biāo)準(zhǔn)化流程。
4.4 人才儲(chǔ)備
專(zhuān)業(yè)認(rèn)證
PingCAP 目前有三個(gè)認(rèn)證,分別是 PCTA、PCTP、PCSD。前兩個(gè)是早期推出面向 DBA 從業(yè)者崗位初高級(jí)認(rèn)證。得物 DBA 團(tuán)隊(duì)有 6 位同學(xué)獲得TiDB的 PCTA 認(rèn)證考試、其中 5 位同學(xué)獲得了進(jìn)階的 PCTP (TiDB專(zhuān)家)認(rèn)證考試。認(rèn)證雖然不能完全代表實(shí)力,但是代表了 DBA 團(tuán)隊(duì)對(duì)技術(shù)的追求和 DBA 團(tuán)隊(duì)在得物做好 TiDB 服務(wù)支持的決心與態(tài)度。
通過(guò)PCTP認(rèn)證學(xué)習(xí),團(tuán)隊(duì)成員深入了解TiDB數(shù)據(jù)庫(kù)的體系架構(gòu)、設(shè)計(jì)理念與各個(gè)組件的運(yùn)行原理。學(xué)習(xí)并掌握 TiDB 數(shù)據(jù)庫(kù)的體系架構(gòu),設(shè)計(jì)實(shí)踐,性能監(jiān)控、參數(shù)優(yōu)化、故障排除、SQL優(yōu)化和高可用設(shè)計(jì)。這個(gè)對(duì)于公司和團(tuán)隊(duì)來(lái)說(shuō)就是人才和技術(shù)上的儲(chǔ)備。
部分在職的 PCTP 得物 DBA 證書(shū)截圖
運(yùn)維小組
對(duì)自建數(shù)據(jù)庫(kù)服務(wù)我們采用了小組負(fù)責(zé)制,以 TiDB 為例,會(huì)有 3 名同學(xué)負(fù)責(zé)基礎(chǔ)設(shè)施運(yùn)維的工作(資源評(píng)估、變更流程評(píng)估、二線問(wèn)題處理等),其中一名是 Owner。關(guān)于日常業(yè)務(wù)側(cè)的變更、SQL 優(yōu)化等由具體對(duì)接業(yè)務(wù)的 DBA 負(fù)責(zé)處理。這樣既解決了人員互備問(wèn)題,又解決了變更風(fēng)險(xiǎn)評(píng)估問(wèn)題,還解決了運(yùn)維小組運(yùn)維壓力的問(wèn)題。
4.5 技術(shù)運(yùn)營(yíng)
對(duì)于一個(gè)新興數(shù)據(jù)庫(kù),DBA 基于產(chǎn)品特性介紹、場(chǎng)景分析、案例分享等,在公司內(nèi)部的技術(shù)運(yùn)營(yíng)也非常重要。它決定了研發(fā)同學(xué)對(duì)這個(gè)產(chǎn)品的認(rèn)知和信心。好的技術(shù)氛圍一定是得益于公司內(nèi)部完善的機(jī)制和平臺(tái),同時(shí)你也能合理的加以利用。這里沒(méi)有講到對(duì)外分享,是因?yàn)槲覀兊脑瓌t是先內(nèi)部沉淀修煉,然后再對(duì)外分享。以下是我們對(duì)于 TiDB 的技術(shù)運(yùn)營(yíng)在公司內(nèi)部的 3 個(gè)主戰(zhàn)場(chǎng)。
技術(shù)分享
技術(shù)夜校是得物技術(shù)部技術(shù)文化的特色之一。為技術(shù)部有意分享的同學(xué)提供一個(gè)平臺(tái),就現(xiàn)有技術(shù)實(shí)戰(zhàn)經(jīng)驗(yàn)、技術(shù)研究成果、重點(diǎn)項(xiàng)目回顧等,在技術(shù)部與同學(xué)們做分享和交流,營(yíng)造濃厚的技術(shù)分享氛圍,形成技術(shù)知識(shí)沉淀,打造學(xué)習(xí)型組織,提升技術(shù)影響力,拓寬技術(shù)同學(xué)的知識(shí)面。
這是一個(gè)能夠有力促進(jìn)技術(shù)影響力和產(chǎn)品影響力的機(jī)會(huì),我們當(dāng)然也不能錯(cuò)過(guò)。本文的作者在剛?cè)肼毜梦锏臅r(shí)候就分享了《分布式數(shù)據(jù)庫(kù) TiDB 的設(shè)計(jì)和架構(gòu)》,培訓(xùn)教室座無(wú)虛席,參與人次創(chuàng)下新高。這次分享讓研發(fā)對(duì) TiDB 也有了一個(gè)全面的認(rèn)識(shí)。所以技術(shù)分享一定程度上解決了前面說(shuō)的產(chǎn)品能力認(rèn)知問(wèn)題。
技術(shù)博客
"毒"家博客也是得物技術(shù)部技術(shù)文化的特色之一。初衷是為了各位同學(xué)們交流技術(shù)心得,通過(guò)輸入與輸出的方式促進(jìn)進(jìn)步、相互成長(zhǎng)。很多高質(zhì)量文章也被推送到了得物技術(shù)公眾號(hào)。
DBA 團(tuán)隊(duì)借助內(nèi)部的技術(shù)博客平臺(tái),輸出了多篇有關(guān) TiDB 的技術(shù)文章。內(nèi)容涵蓋核心原理分析、優(yōu)化案例、故障 case 分析、業(yè)務(wù)場(chǎng)景落地等。在整個(gè)氛圍的帶動(dòng)下,不少研發(fā)同學(xué)也發(fā)表了關(guān)于 TiDB 的學(xué)習(xí)和落地的技術(shù)文章。
課程錄制
組織內(nèi)部的技術(shù)分享的投入較大,分享的頻次不宜太高,否則參與度也會(huì)比較低。而且從內(nèi)容深度、知識(shí)獲取效率、自助學(xué)習(xí)來(lái)看,分享也不是長(zhǎng)期的方案。錄制視頻課程的事情就提上日程了,視頻課程的好處是可以濃縮知識(shí)點(diǎn),將技術(shù)分享 40 分鐘的內(nèi)容(有一些不必要的內(nèi)容,比如重復(fù)的話、口頭語(yǔ)等)壓縮至 15 分鐘。完美解決了前面提到的問(wèn)題。正好公司內(nèi)部有一個(gè)自研的學(xué)習(xí)平臺(tái),日常就用于發(fā)布各種培訓(xùn)、學(xué)習(xí)的視頻。為確保錄制效果和效率我們前期的課程都準(zhǔn)備了稿件。我們基于這個(gè)平臺(tái)也發(fā)布了一期( 5 節(jié))課程,最近已經(jīng)在籌備第二期的課程內(nèi)容了。
課程錄制也可以使 DBA 再一次復(fù)習(xí)細(xì)節(jié)知識(shí),因?yàn)橐v清楚知識(shí)點(diǎn),就必須自己深入理解。這個(gè)一定程度上表明了我們對(duì) TiDB 的了解程度和做好它的決心,也給了研發(fā)使用的信心。
5、TiDB 在核心業(yè)務(wù)場(chǎng)景實(shí)踐
5.1 業(yè)務(wù)痛點(diǎn)
得物商家訂單庫(kù)由早期 MySQL 單庫(kù)進(jìn)階到 MySQL 分庫(kù)分表,這個(gè)方案支撐了業(yè)務(wù)的高速發(fā)展。而以商家 ID 做 shareding-key,會(huì)使的同一個(gè)商家的訂單數(shù)據(jù)都會(huì)在一個(gè)表中,隨著訂單量的逐步提升,最終大商家的查詢會(huì)形成了單點(diǎn)性能問(wèn)題。主要體現(xiàn)在慢 SQL 較多和 數(shù)據(jù)庫(kù)負(fù)載上升,每天約 1W 條慢 SQL,部分統(tǒng)計(jì)類(lèi)查詢已經(jīng)超 10S。另外就是單機(jī)容量也有上限,垂直擴(kuò)容受限。隨著訂單量的上升,系統(tǒng)整體的性能和容量需要最進(jìn)一步的規(guī)劃。
5.2 解決思路
優(yōu)點(diǎn) | 缺點(diǎn) | |
規(guī)格調(diào)整 |
|
|
數(shù)據(jù)歸檔 |
|
|
調(diào)整分片規(guī)則 |
|
|
分布式數(shù)據(jù)庫(kù) |
|
|
基于以上提到的問(wèn)題,我們對(duì)所有的解決方案都做了對(duì)比。表格中是對(duì)四種解決方案的關(guān)鍵信息提煉。我們希望能夠選擇一個(gè)比較長(zhǎng)期的方案,可以支撐未來(lái) 3-5 年的需求,既要解決性能問(wèn)題,還要解決容量問(wèn)題,又要比較低的研發(fā)成本。所以最終選擇了引入分布式數(shù)據(jù)庫(kù)的方案。
5.3 數(shù)據(jù)庫(kù)選型
基于目前得物在使用的數(shù)據(jù)庫(kù)進(jìn)行了評(píng)估,主要包含以下三種選擇。
由于得物在 2020 年就引入了 TiDB。雖然沒(méi)有大規(guī)模推廣,但是陸續(xù)也有不少業(yè)務(wù)接入。大部分的業(yè)務(wù)把它作為 MySQL 分庫(kù)分表的聚合庫(kù)使用,有一小部分業(yè)務(wù)是直接接入了讀寫(xiě)需求。基于之前的實(shí)踐經(jīng)驗(yàn)和業(yè)務(wù)需求,經(jīng)過(guò)和研發(fā)團(tuán)隊(duì)的協(xié)商,直接采用的讀寫(xiě)庫(kù)的使用方案。另外一個(gè)方面是從只讀過(guò)渡到全量讀寫(xiě)的周期會(huì)比較長(zhǎng),會(huì)產(chǎn)生不必要的并行成本和延遲項(xiàng)目時(shí)間。
5.4 兼容性&性能測(cè)試
兼容性測(cè)試
SQL 兼容性的問(wèn)題,我們并沒(méi)有完全依賴(lài)后期的業(yè)務(wù)測(cè)試來(lái)驗(yàn)證。而是通過(guò)獲取 MySQL 上的全量 SQL 的方式進(jìn)行驗(yàn)證。由于我們將全量 SQL 存儲(chǔ)在了 Clickhouse,并且存儲(chǔ)前做了SQL 指紋提取。所以很容易可以獲得去重后的業(yè)務(wù) SQL。然后將所有類(lèi)型的 SQL 樣本在 TiDB 中進(jìn)行回放,這里主要針對(duì) Select。最終測(cè)試所有業(yè)務(wù) SQL 100% 兼容。
SQL 指紋?
性能測(cè)試
單量較少的商家場(chǎng)景性能測(cè)試
和預(yù)期的結(jié)果一樣,由于 TiDB 分布式的架構(gòu),數(shù)據(jù)獲取路徑比 MySQL 要長(zhǎng),所以 RT 上相比 MySQL 分別多出 91%、76%、52%。從這里可以看出隨著并發(fā)的上升,TiDB 和 MySQL 之間的 RT 差距也逐步縮短。由于 TiDB 可以通過(guò)擴(kuò)展 DB 和 KV 節(jié)點(diǎn)提升 QPS 能力,我們?cè)趬簻y(cè)中也做了相關(guān)驗(yàn)證,符合預(yù)期。包括現(xiàn)有數(shù)據(jù)量翻一倍的基礎(chǔ)上對(duì)性能的影響也做了驗(yàn)證,結(jié)論是無(wú)影響。為了方便和后面的內(nèi)容對(duì)比,我們這里只提供了 RT 的指標(biāo)。
單量較多的商家場(chǎng)景性能測(cè)試
我們挑了幾個(gè)出現(xiàn)頻率較高且查詢較慢的 SQL進(jìn)行測(cè)試,詳情參照以下內(nèi)容。
SQL1
SQL2
SQL3
SQL4
關(guān)于 xxDB 特別做了處理,大家可以忽略,因?yàn)槲覀冎饕獙?duì)比的是 MySQL 和 TiDB。從測(cè)試結(jié)果來(lái)看效果很好,完全滿足業(yè)務(wù)側(cè)的要求。
5.5 遇到的一些問(wèn)題
SQL 執(zhí)行計(jì)劃
問(wèn)題:
首先說(shuō)明一下,統(tǒng)計(jì)信息健康度是 90 以上。SQL 還是會(huì)選錯(cuò)索引。我們分析了一下,主要是兩個(gè)問(wèn)題:1.查詢條件比較多,索引也比較多;2.優(yōu)化器的能力待提升。
解決方案:
上線前和研發(fā)對(duì)已有 SQL 進(jìn)行了全面的 Review,如果執(zhí)行計(jì)劃不對(duì),就通過(guò) SPM 解決。
Bug
問(wèn)題1:
Update 語(yǔ)句并發(fā)執(zhí)行耗時(shí) 3S,經(jīng)過(guò)排查是由于研發(fā)未使用顯示事務(wù),所以第一次執(zhí)行是樂(lè)觀事務(wù),第二次重試才是悲觀事務(wù)。調(diào)整以后遇到了悲觀事務(wù)下,偶發(fā)性的寫(xiě)寫(xiě)沖突的問(wèn)題。經(jīng)排查是由于悲觀鎖未獲取到導(dǎo)致的寫(xiě)寫(xiě)沖突,需要升級(jí)到 5.3.2 才能解決。
解決方案:
升級(jí)版本到 5.3.2 解決
問(wèn)題 2:
TiDB出現(xiàn)部分節(jié)點(diǎn)不可用,SQL執(zhí)行報(bào) Region is unavailable 錯(cuò)誤。經(jīng)排查是 5.3.2 引入的 TiKV bug。
PD leader 發(fā)生切換后,TiKV 向 PD client 發(fā)送心跳請(qǐng)求失敗后不會(huì)重試,只能等待與 PD client 重連。
這樣,故障 TiKV 節(jié)點(diǎn)上的 Region 的信息會(huì)逐步變舊,使得 TiDB 無(wú)法獲取最新的 Region 信息,導(dǎo)致 SQL 執(zhí)行出錯(cuò)。
解決方案:
這是一個(gè)讓人后背發(fā)涼的 bug。當(dāng)時(shí)的判斷是由于 PD 切換導(dǎo)致的,但是不清楚是 bug。我們采用了影響最小的故障恢復(fù)方案(把 PD leader 切回去,因?yàn)樵?PD Leader 沒(méi)有掛,只是發(fā)生了切換)。問(wèn)題解決后在官方發(fā)現(xiàn)了這個(gè)bug fix。所以又安排了升級(jí)。
這是我們上線過(guò)程中遇到的幾個(gè)典型問(wèn)題。總體來(lái)說(shuō)引入一個(gè)新數(shù)據(jù)庫(kù)就會(huì)帶來(lái)一定的試錯(cuò)成本,所以我們依然處于謹(jǐn)慎選型的狀態(tài)。另外就是吐槽一下,就上面的問(wèn)題 2,建議官方要加強(qiáng) Code Review 和混沌工程演練。
5.6 上線效果
性能收益
為了確保上線穩(wěn)定性,我們通過(guò)灰度切流的方式逐步放量。完全切流后成果顯著,慢 SQL 幾乎全部消失,如下圖所示。
成本收益
由于 MySQL 的分庫(kù)分表集群由 10個(gè)寫(xiě)實(shí)例、10個(gè)讀實(shí)例構(gòu)成,遷移至 TiDB 后的集群規(guī)模為 TiDB*6、TiKV*12。成本下降了58%。所以再重復(fù)說(shuō)一下選對(duì)了場(chǎng)景,TiDB 也能順帶節(jié)省成本。
大促考驗(yàn)
項(xiàng)目上線后輕松應(yīng)對(duì)了今年的雙 11、雙 12,大促中的系統(tǒng) RT表現(xiàn)穩(wěn)定。
6、總結(jié)
最后特別說(shuō)明下,文章中涉及一些產(chǎn)品的對(duì)比只是基于我們當(dāng)時(shí)的場(chǎng)景和需求進(jìn)行的分析,并不代表某個(gè)數(shù)據(jù)庫(kù)產(chǎn)品的好壞。寫(xiě)這篇文章的目的是想把我們 TiDB 落地經(jīng)驗(yàn)做個(gè)階段性總結(jié),順便也能給同行們做個(gè)大方向上的參考。我們的這套方法論,理論上適用于任何一個(gè)需要再企業(yè)內(nèi)部引入新型數(shù)據(jù),并且推廣的場(chǎng)景。本文涉及的內(nèi)容和方向比較多,無(wú)法每個(gè)模塊都做深入的探討。后面我們也會(huì)把大家感興趣的模塊單獨(dú)拆分出來(lái)做幾期深入分享。