┊文章閱讀:次
原標(biāo)題:我們?yōu)槭裁捶艞壛薚iDB,選擇自研NewSQL
作者介紹
李鑫,滴滴資深軟件開發(fā)工程師,多年分布式存儲領(lǐng)域設(shè)計及開發(fā)經(jīng)驗。曾參與NoSQL/NewSQL數(shù)據(jù)庫Fusion、分布式時序數(shù)據(jù)庫sentry、NewSQL數(shù)據(jù)庫SDB等系統(tǒng)的設(shè)計開發(fā)工作。
Fusion-NewSQL是由滴滴自研的在分布式KV存儲基礎(chǔ)上構(gòu)建的NewSQL存儲系統(tǒng)。Fusion-NewSQ兼容了MySQL協(xié)議,支持二級索引功能,提供超大規(guī)模數(shù)據(jù)持久化存儲和高性能讀寫。
我們的問題
滴滴的業(yè)務(wù)快速持續(xù)發(fā)展,數(shù)據(jù)量和請求量急劇增長,對存儲系統(tǒng)等壓力與日俱增。雖然分庫分表在一定程度上可以解決數(shù)據(jù)量和請求增加的需求,但是由于滴滴多條業(yè)務(wù)線(快車、專車、兩輪車等)的業(yè)務(wù)快速變化,數(shù)據(jù)庫加字段加索引的需求非常頻繁,分庫分表方案對于頻繁的Schema變更操作并不友好,會導(dǎo)致DBA任務(wù)繁重,變更周期長,并且對巨大的表操作還會對線上有一定影響。同時,分庫分表方案對二級索引支持不友好或者根本不支持。鑒于上述情況,NewSQL數(shù)據(jù)庫方案就成為我們解決業(yè)務(wù)問題的一個方向。
開源產(chǎn)品調(diào)研
最開始,我們調(diào)研了開源的分布式NewSQL方案TiDB。雖然TiDB是非常優(yōu)秀的NewSQL產(chǎn)品,但是對于我們的業(yè)務(wù)場景來說,TiDB并不是非常適合,原因如下:
基于以上原因,我們開啟了自研符合自己業(yè)務(wù)需求的NewSQL之路。
我們的基礎(chǔ)
我們并沒有打算從0開發(fā)一個完備的NewSQL系統(tǒng),而是在自研的分布式KV存儲Fusion的基礎(chǔ)上構(gòu)建一個能滿足我們業(yè)務(wù)場景的NewSQL。Fusion是采用了Codis架構(gòu),兼容Redis協(xié)議和數(shù)據(jù)結(jié)構(gòu),使用RocksDB作為存儲引擎的NoSQL數(shù)據(jù)庫。Fusion在滴滴內(nèi)部已經(jīng)有幾百個業(yè)務(wù)在使用,是滴滴主要的在線存儲之一。
Fusion的架構(gòu)圖如下:
我們采用hash分片的方式來做數(shù)據(jù)sharding。從上往下看,用戶通過Redis協(xié)議的客戶端就可以訪問Fusion,用戶的訪問請求發(fā)到proxy,再由proxy轉(zhuǎn)發(fā)數(shù)據(jù)到后端Fusion的數(shù)據(jù)節(jié)點。proxy到后端數(shù)據(jù)節(jié)點的轉(zhuǎn)發(fā),是根據(jù)請求的key計算hash值,然后對slot分片數(shù)取余,得到一個固定的slotid,每個slotid會固定的映射到一個存儲節(jié)點,以此解決數(shù)據(jù)路由問題。
有了一個高并發(fā),低延遲,大容量的存儲層后,我們要做的就是在之上構(gòu)建MySQL協(xié)議以及二級索引。那么如何將MySQL的數(shù)據(jù)格式轉(zhuǎn)成Redis的數(shù)據(jù)結(jié)構(gòu)存儲就是我們必須面臨的問題,后面會詳細(xì)說。
綜合考慮大多數(shù)用戶對需求,我們整理了我們的NewSQL需要提供的幾個核心能力:
Fusion-NewSQL由下面幾個部分組成:
架構(gòu)圖如下:
存儲結(jié)構(gòu)
MySQL的表結(jié)構(gòu)數(shù)據(jù)如何轉(zhuǎn)成Redis的數(shù)據(jù)結(jié)構(gòu)是我們面臨的第一個問題。
如下圖:
我們將MySQL表的一行記錄轉(zhuǎn)成Redis的一個Hashmap結(jié)構(gòu)。Hashmap的key由表名+主鍵值組成,滿足了全局唯一的特性。下圖展示了MySQL通過主鍵查詢轉(zhuǎn)換為Redis協(xié)議的方式:
除了數(shù)據(jù),索引也需要存儲在Fusion-NewSQL中,和數(shù)據(jù)存成hashmap不同,索引存儲成key-value結(jié)構(gòu)。根據(jù)索引類型不同,組成key-value的格式還有一點細(xì)微的差別(下面的格式為了看起來直觀,實際上分隔符,indexname都是做過編碼的):
唯一索引:
Key:
table_indexname_indexColumnsValue
Value:Rowkey
非唯一索引:
Key:
table_indexname_indexColumnsValue_Rowkey
Value:null
造成這種差異的原因就是非唯一索引在加入Rowkey之前的部分是有可能重復(fù)的,無法全局唯一。另外,唯一索引不將Rowkey編碼在key中,是因為在查詢語句是單純的“=”查詢的時候直接get操作就可以找到對應(yīng)的Rowkey內(nèi)容,而不需要通過scan,這樣的效率更高。
后面會在查詢流程中重點講述如何通過二級索引查詢到數(shù)據(jù)。
數(shù)據(jù)讀寫流程
1)數(shù)據(jù)寫入
通過上面的鏈路,用戶的一條MySQL寫操作就完成了數(shù)據(jù)存儲和索引構(gòu)建。由于通過數(shù)據(jù)構(gòu)建索引這一步是通過MQ異步完成,所以會存在數(shù)據(jù)和索引有一定的時間差的情況。
2)查詢
下面是一個使用二級索引查詢數(shù)據(jù)的案例:
根據(jù)上面索引數(shù)據(jù)的格式可以看到,scan范圍的時候,前綴必須固定,映射到SQL語句到時候,意味著where到條件中,范圍查詢只能有一個字段,而不能多個字段。比如:
索引是age和name兩個字段的聯(lián)合索引。如果查詢語句如下:
select*fromstudentwhereage>20andname>‘W’;
scan就沒有辦法確定前綴,也就無法通過index_age_name這個索引查詢到滿足條件的數(shù)據(jù),所以使用KV形式存儲到索引只能滿足where條件中有一個字段是范圍查詢。當(dāng)然可以通過將聯(lián)合索引分開存放,多次交互搜索取交集的方式解決,但是這就和我們降低RPC次數(shù),降低延遲的設(shè)計初衷相違背了。為了解決這個問題,我們引入了ElasticSearch搜索引擎,這部分后面會詳細(xì)說明。
Schema變更
用戶涉及Schema變更時,會以工單形式發(fā)給管控系統(tǒng)。管控系統(tǒng)審批過后,會將變更請求推給配置中心,配置中心進(jìn)行安全性檢查后,將新的Schema寫入到存儲中,并給各個節(jié)點推送變更。
字段變更:
節(jié)點接收到推送,更新本地的Schema。對于歷史數(shù)據(jù),并不真正去修改數(shù)據(jù),而是在查詢的時候,根據(jù)Schema信息匹配字段,如果數(shù)據(jù)比Schema缺失某些字段,就使用默認(rèn)值代替;如果數(shù)據(jù)比Schema多了字段,就隱藏掉多余字段不展示。
新增索引分為兩步處理:
一個單獨的存儲產(chǎn)品解決所有問題的時代早已經(jīng)過去,數(shù)據(jù)孤島是沒有辦法很好服務(wù)業(yè)務(wù)的,F(xiàn)usion-NewSQL從設(shè)計的那天起就考慮了和其他存儲系統(tǒng)的打通。
Fusion-NewSQL到其他存儲系統(tǒng)
Fusion-NewSQL通過兼容MySQL的Binlog格式,將數(shù)據(jù)發(fā)到MQ中。下游各個系統(tǒng)凡是能接入MySQL數(shù)據(jù)的,都可以通過消費MQ中相同格式的Fusion-NewSQL數(shù)據(jù),將數(shù)據(jù)存到其他系統(tǒng)中。這樣的方式用最小的工作量最大程度做到了兼容。
Hive到Fusion-NewSQL
Fusion-NewSQL還支持將離線的Hive表中的數(shù)據(jù)通過Fusion-NewSQL提供的FastLoad(DTS)工具,將Hive表數(shù)據(jù)轉(zhuǎn)入到Fusion-NewSQL,滿足離線數(shù)據(jù)到在線的數(shù)據(jù)流動。
如果用戶自己完成數(shù)據(jù)流轉(zhuǎn),一般會掃描Hive表,然后構(gòu)建MySQL的寫入語句,一條條將數(shù)據(jù)寫入到Fusion-NewSQL,流程如下面這樣:
從上面的流程可以看出這種遷移方式有幾個痛點:
基于上述的痛點,我們設(shè)計了Fastload數(shù)據(jù)導(dǎo)入平臺,通過約定Hive到Fusion-NewSQL的表格式,使用Hadoop并發(fā)處理數(shù)據(jù),并構(gòu)建RocksDB能識別的sst存儲文件,繞過復(fù)雜的DISE寫鏈路,直接將數(shù)據(jù)導(dǎo)入到Fusion-NewSQL中,流程如下:
這個方案避免了冗長復(fù)雜的寫鏈路,同時不會增加系統(tǒng)的QPS,在磁盤和網(wǎng)絡(luò)IO沒有達(dá)到瓶頸的情況下對線上訪問幾乎是沒有任何影響;同時,用戶只需要填寫Hive到Fusion-NewSQL的Schema映射關(guān)系即可,不必再關(guān)心實現(xiàn)。
通過ElasticSearch實現(xiàn)復(fù)雜查詢
在業(yè)務(wù)使用MySQL或Fusion-NewSQL的過程中,我們發(fā)現(xiàn)有這樣一種場景:業(yè)務(wù)的查詢條件很復(fù)雜,涉及的字段數(shù),條件,聚合都比較多,這種場景下,業(yè)務(wù)會選擇將ElasticSearch作為MySQL或Fusion-NewSQL的下游,將數(shù)據(jù)導(dǎo)入ElasticSearch,然后通過ElasticSearch豐富的搜索能力,先從ElasticSearch中獲取數(shù)據(jù)在MySQL或Fusion-NewSQL的主鍵,然后再根據(jù)主鍵獲取全部數(shù)據(jù)。
根據(jù)上面的場景,F(xiàn)usion-NewSQL提供一個特殊的索引類型:ES。用戶在創(chuàng)建索引的時候,可以將需要做復(fù)雜查詢的字段勾選出來,共同構(gòu)建成一個ES索引,這樣既滿足了業(yè)務(wù)需求,避免了每個業(yè)務(wù)都需要開發(fā)一套和ElasticSearch交互的復(fù)雜邏輯,又統(tǒng)一了數(shù)據(jù)庫使用接口都為MySQL。同時,還彌補了前面提到的Fusion-NewSQL的KV二級索引不能支持多個字段范圍檢索的能力。
架構(gòu)圖如下:
ES索引只是在上圖紅4處,將ES索引中包含的字段信息和主鍵寫入到ElasticSearch中。在查詢時綠1如果選中了ES類型的索引,就根據(jù)where條件中涉及的字段,組裝成ElasticSearch的DSL語句,從ElasticSearch獲取主鍵,再從Data集群獲取。由于ElasticSearch查詢的延遲比較慢,F(xiàn)usion-NewSQL可以支持一張表的多個索引采用KV索引和ES索引并存,對于延遲要求高,查詢條件相對簡單的使用KV索引;對于查詢條件復(fù)雜,延遲要求不高的使用ES索引。
Fusion-NewSQL當(dāng)前已經(jīng)接入訂單、預(yù)估、賬單、用戶中心、交易引擎等70個核心業(yè)務(wù),總QPS超過200W,總數(shù)據(jù)超過600TB。
當(dāng)然,F(xiàn)usion-New不是一個通用完備的NewSQL方案,而是在已有的NoSQL數(shù)據(jù)庫基礎(chǔ)上,通過對SQL協(xié)議的支持以及組合各種組件,構(gòu)建一個對外表達(dá)的數(shù)據(jù)庫,但是這種方式,可以以最小的開發(fā)代價,滿足大多數(shù)的業(yè)務(wù)場景,具備較高的投入產(chǎn)出比。
作者丨李鑫
來源丨滴滴技術(shù)(ID:didi_tech)
dbaplus社群歡迎廣大技術(shù)人員投稿,投稿郵箱:editor@dbaplus.cn
>>>>活動推薦
2020年4月17日,北京,Gdevops全球敏捷運維峰會將開啟年度首站!重點圍繞數(shù)據(jù)庫、智慧運維、Fintech金融科技領(lǐng)域,攜手阿里、中國銀行、平安銀行、中郵消費金融、中國聯(lián)通大數(shù)據(jù)、新炬網(wǎng)絡(luò)等技術(shù)代表,展望云時代下數(shù)據(jù)庫發(fā)展趨勢、破解運維轉(zhuǎn)型困局。
今晚8點,58到家運維專家楊經(jīng)營,將帶來《業(yè)務(wù)上云后,58到家運維平臺的演進(jìn)之路》的主題分享,解答全業(yè)務(wù)托管公有云如何進(jìn)行高效的運維工作?運維平臺基于公有云與IDC有什么區(qū)別?運維自動化在公有云上應(yīng)該如何建設(shè)?獲取直播地址,添加vx:dbafeifei
Copyright @ 2013-2020 中國福建網(wǎng) 版權(quán)所有
聯(lián)系我們
免責(zé)聲明:本站為非營利性網(wǎng)站,部分圖片或文章來源于互聯(lián)網(wǎng)如果無意中對您的權(quán)益構(gòu)成了侵犯,我們深表歉意,請您聯(lián)系,我們立即刪除。