幕思城>電商百科>通用知識>淘寶知識>Shopee的數(shù)據(jù)庫是如何做選型的-Shopee問答電商問答

    Shopee的數(shù)據(jù)庫是如何做選型的-Shopee問答電商問答

    2023-01-17| 21:37|發(fā)布在分類/淘寶知識|閱讀:44

    本文主題Shopee,Shopee集群,Shopee問答。

    Shopee的數(shù)據(jù)庫是如何做選型的

    Shopee在上線了5年后,已經(jīng)成為了東南亞跨境電商的領(lǐng)頭羊,該平臺的數(shù)據(jù)庫,值得不少的跨境電商平臺方學(xué)習(xí),他們是如何做選型的?幕思城電商在這里跟大家來講解一下吧。

    Shopee于2015年底上線,是東南亞地區(qū)領(lǐng)先的電子商務(wù)平臺,覆蓋東南亞和臺灣等多個市場,在深圳和新加坡分別設(shè)有研發(fā)中心。本文系Shopee的分布式數(shù)據(jù)庫選型思路漫談。因為是『漫談』,可能不成體系,但會著重介紹一些經(jīng)驗以及踩過的坑,提供給大家參考。

    1Shopee的數(shù)據(jù)庫使用情況

    Shopee在用哪些數(shù)據(jù)庫?

    先說一下當(dāng)前Shopee線上在用的幾種數(shù)據(jù)庫:

    在Shopee,我們只有兩種關(guān)系數(shù)據(jù)庫:MySQL和TiDB。目前大部分業(yè)務(wù)數(shù)據(jù)運行在MySQL上,TiDB集群的比重過去一年來快速增長中。

    Redis在Shopee各個產(chǎn)品線使用廣泛。從DBA的角度看,Redis是關(guān)系數(shù)據(jù)庫的一種重要補充。

    內(nèi)部也在使用諸如HBase和Pika等多種NoSQL數(shù)據(jù)庫,使用范圍多限于特定業(yè)務(wù)和團(tuán)隊。不在本次討論范圍內(nèi)。

    數(shù)據(jù)庫選型策略

    過去的一年里,我們明顯感覺到數(shù)據(jù)庫選型在DBA日常工作中的占比越來越重了。隨著業(yè)務(wù)快速成長,DBA每周需要創(chuàng)建的新數(shù)據(jù)庫較之一兩年前可能增加了十倍不止。我們每年都會統(tǒng)計幾次線上邏輯數(shù)據(jù)庫個數(shù)。上圖展示了過去幾年間這個數(shù)字的增長趨勢(縱軸表示邏輯數(shù)據(jù)庫個數(shù),我們把具體數(shù)字隱去了)。

    歷史數(shù)據(jù)顯示,邏輯數(shù)據(jù)庫個數(shù)每年都有三到五倍的增長,過去的2023年增長倍數(shù)甚至更高。每個新數(shù)據(jù)庫上線前,DBA和開發(fā)團(tuán)隊都需要做一些評估以快速決定物理設(shè)計和邏輯設(shè)計。經(jīng)驗表明,一旦在設(shè)計階段做出了不當(dāng)決定,后期需要付出較多時間和人力成本來補救。因此,我們需要制定一些簡潔高效的數(shù)據(jù)庫選型策略,確保我們大多數(shù)時候都能做出正確選擇。

    我們的數(shù)據(jù)庫選型策略可以概括為三點:

    默認(rèn)使用MySQL。

    積極嘗試TiDB。

    在必要的時候引入Redis用于消解部分關(guān)系數(shù)據(jù)庫高并發(fā)讀寫流量。

    在使用MySQL的過程中我們發(fā)現(xiàn),當(dāng)單數(shù)據(jù)庫體量達(dá)到TB級別,開發(fā)和運維的復(fù)雜度會被指數(shù)級推高。DBA日常工作會把消除TB級MySQL數(shù)據(jù)庫實例排在高優(yōu)先級。

    積極嘗試TiDB”不是一句空話。2023年初開始,我們把TiDB引入了到Shopee。過去兩年間TiDB在Shopee從無到有,集群節(jié)點數(shù)和數(shù)據(jù)體積已經(jīng)達(dá)到了可觀的規(guī)模。對于一些經(jīng)過了驗證的業(yè)務(wù)場景,DBA會積極推動業(yè)務(wù)團(tuán)隊采用TiDB,讓開發(fā)團(tuán)隊有機會獲得第一手經(jīng)驗;目前,內(nèi)部多數(shù)業(yè)務(wù)開發(fā)團(tuán)隊都在線上實際使用過一次或者多次TiDB。

    關(guān)于借助Redis消解關(guān)系數(shù)據(jù)庫高并發(fā)讀寫流量,后面會展開講一下我們的做法。

    分布式數(shù)據(jù)庫選型參考指標(biāo)

    在制定了數(shù)據(jù)庫選型策略之后,我們在選型中還有幾個常用的參考指標(biāo):

    1TB:對于一個新數(shù)據(jù)庫,我們會問:在未來一年到一年半時間里,數(shù)據(jù)庫的體積會不會漲到1TB?如果開發(fā)團(tuán)隊很確信新數(shù)據(jù)庫一定會膨脹到TB級別,應(yīng)該立即考慮MySQL分庫分表方案或TiDB方案。

    1000萬行或10GB:單一MySQL表的記錄條數(shù)不要超過1000萬行,或單表磁盤空間占用不要超過10GB。我們發(fā)現(xiàn),超過這個閾值后,數(shù)據(jù)庫性能和可維護(hù)性上往往也容易出問題(部分SQL難以優(yōu)化,不易做表結(jié)構(gòu)調(diào)整等)。如果確信單表體積會超越該上限,則應(yīng)考慮MySQL分表方案;也可以采用TiDB,TiDB可實現(xiàn)水平彈性擴(kuò)展,多數(shù)場景下可免去分表的煩惱。

    每秒1000次寫入:單個MySQL節(jié)點上的寫入速率不要超過每秒1000次。大家可能覺得這個值太低了;許多開發(fā)同學(xué)也常舉例反駁說,線上MySQL每秒寫入幾千幾萬次的實際案例比比皆是。我們?yōu)槭裁窗阎笜?biāo)定得如此之低呢?首先,上線前做估算往往有較大不確定性,正常狀況下每秒寫入1000次,大促等特殊場景下可能會陡然飆升到每秒10000次,作為設(shè)計指標(biāo)保守一點比較安全。其次,我們允許開發(fā)團(tuán)隊在數(shù)據(jù)庫中使用Text等大字段類型,當(dāng)單行記錄長度增大到一定程度后主庫寫入和從庫復(fù)制性能都可能明顯劣化,這種狀況下對單節(jié)點寫入速率不宜有太高期待。因此,如果一個項目上線前就預(yù)計到每秒寫入速率會達(dá)到上萬次甚至更高,則應(yīng)該考慮MySQL分庫分表方案或TiDB方案;同時,不妨根據(jù)具體業(yè)務(wù)場景看一下能否引入Redis或消息隊列作為寫緩沖,實現(xiàn)數(shù)據(jù)庫寫操作異步化。

    P99響應(yīng)時間要求是1毫秒,10毫秒還是100毫秒?應(yīng)用程序要求99%的數(shù)據(jù)庫查詢都要在1毫秒內(nèi)返回嗎?如果是,則不建議直接讀寫數(shù)據(jù)庫??梢钥紤]引入Redis等內(nèi)存緩沖方案,前端直接面向Redis確保高速讀寫,后端異步寫入數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)持久化。我們的經(jīng)驗是,多數(shù)場景下,MySQL服務(wù)器、表結(jié)構(gòu)設(shè)計、SQL和程序代碼等方面做過細(xì)致優(yōu)化后,MySQL有望做到99%以上查詢都在10毫秒內(nèi)返回。對于TiDB,考慮到其存儲計算分離和多組件協(xié)作實現(xiàn)SQL執(zhí)行過程的特點,我們通常把預(yù)期值調(diào)高一個數(shù)量級到100毫秒級別。以線上某TiDB2.x集群為例,上線半年以來多數(shù)時候P99都維持在20毫秒以內(nèi),偶爾會飆升到200毫秒,大促時抖動則更頻繁一些。TiDB執(zhí)行SQL查詢過程中,不同組件、不同節(jié)點之間的交互會多一些,自然要多花一點時間。

    要不要分庫分表?

    內(nèi)部的數(shù)據(jù)庫設(shè)計評估清單里包含十幾個項目,其中要不要分庫分表”是一個重要議題。在相當(dāng)長時間里,MySQL分庫分表方案是我們實現(xiàn)數(shù)據(jù)庫橫向擴(kuò)展的唯一選項;把TiDB引入Shopee后,我們多了一個不分庫分表”的選項。

    從我們的經(jīng)驗來看,有幾種場景下采用MySQL分庫分表方案的副作用比較大,日常開發(fā)和運維都要付出額外的代價和成本。DBA和開發(fā)團(tuán)隊需要在數(shù)據(jù)庫選型階段甄別出這些場景并對癥下藥。

    難以準(zhǔn)確預(yù)估容量的數(shù)據(jù)庫。舉例來講,線上某日志數(shù)據(jù)庫過去三個月的增量數(shù)據(jù)超過了之前三年多的存量體積。對于這類數(shù)據(jù)庫,采用分庫分表方案需要一次又一次做Re-sharding,每一次都步驟繁瑣,工程浩大。Shopee的實踐證明,TiDB是較為理想的日志存儲方案;當(dāng)前,把日志類數(shù)據(jù)存入TiDB已經(jīng)是內(nèi)部較為普遍的做法了。

    需要做多維度復(fù)雜查詢的數(shù)據(jù)庫。以訂單數(shù)據(jù)庫為例,各子系統(tǒng)都需要按照買家、賣家、訂單狀態(tài)、支付方式等諸多維度篩選數(shù)據(jù)。若以買家維度分庫分表,則賣家維度的查詢會變得困難;反之亦然。一方面,我們?yōu)樽钪匾牟樵兙S度分別建立了異構(gòu)索引數(shù)據(jù)庫;另一方面,我們也在TiDB上實現(xiàn)了訂單匯總表,把散落于各個分片的訂單數(shù)據(jù)匯入一張TiDB表,讓一些需要掃描全量數(shù)據(jù)的復(fù)雜查詢直接運行在TiDB匯總表上。

    數(shù)據(jù)傾斜嚴(yán)重的數(shù)據(jù)庫。諸如點贊和關(guān)注等偏社交類業(yè)務(wù)數(shù)據(jù),按照用戶維度分庫分表后常出現(xiàn)數(shù)據(jù)分布不均勻的現(xiàn)象,少數(shù)分片的數(shù)據(jù)量可能遠(yuǎn)大于其他分片;這些大分片往往也是讀寫的熱點,進(jìn)而容易成為性能瓶頸。一種常用的解法是Re-sharding,把數(shù)據(jù)分成更多片,盡量稀釋每一片上的數(shù)據(jù)量和讀寫流量。最近我們也開始嘗試把部分?jǐn)?shù)據(jù)搬遷到TiDB上;理論上,如果TiDB表主鍵設(shè)計得高度分散,熱點數(shù)據(jù)就有望均勻分布到全體TiKVRegion上。

    總體來說,MySQL分庫分表方案在解決了主要的數(shù)據(jù)庫橫向擴(kuò)展問題的同時,也導(dǎo)致了一些開發(fā)和運維方面的痛點。一方面,我們努力在MySQL分庫分表框架內(nèi)解決和緩解各種問題;另一方面,我們也嘗試基于TiDB構(gòu)建不分庫分表”的新型解決方案,并取得了一些進(jìn)展。

    2MySQL在Shopee的使用情況

    Shopee的母公司SEAGroup成立于2009年。我們從一開始就使用MySQL作為主力數(shù)據(jù)庫,從早期的MySQL5.1逐漸進(jìn)化到現(xiàn)在的MySQL5.7,我們已經(jīng)用了十年MySQL。

    我們使用Percona分支,當(dāng)前存儲引擎以InnoDB為主。

    一主多從是比較常見的部署結(jié)構(gòu)。我們的應(yīng)用程序比較依賴讀寫分離,線上數(shù)據(jù)庫可能會有多達(dá)數(shù)十個從庫。一套典型的數(shù)據(jù)庫部署結(jié)構(gòu)會分布在同城多個機房;其中會有至少一個節(jié)點放在備用機房,主要用于定時全量備份,也會提供給數(shù)據(jù)團(tuán)隊做數(shù)據(jù)拉取等用途。

    如果應(yīng)用程序需要讀取Binlog,從庫上會安裝一個名為GDS(GeneralDBSync)的Agent,實時解析Binlog,并寫入Kafka。

    應(yīng)用程序透過DNS入口連接主庫或從庫。

    我們自研的數(shù)據(jù)庫中間件,支持簡單的分庫分表。何為簡單的分庫分表”?只支持單一分庫分表規(guī)則,可以按日期、Hash或者某個字段的取值范圍來分片;一條SQL最終只會被路由到單一分片上,不支持聚合或Join等操作。

    如何解決TB級MySQL數(shù)據(jù)庫的使用?

    根據(jù)我們的統(tǒng)計,Shopee線上數(shù)據(jù)庫中80%都低于50GB;此外,還有2.5%的數(shù)據(jù)庫體積超過1TB。上圖列出了部分TB級別數(shù)據(jù)庫的一個統(tǒng)計結(jié)果:平均體積是2TB,最大的甚至超過4TB。

    采用MySQL分庫分表方案和遷移到TiDB是我們削減TB級MySQL數(shù)據(jù)庫實例個數(shù)的兩種主要途徑。除此之外,還有一些辦法能幫助我們對抗MySQL數(shù)據(jù)庫體積膨脹帶來的負(fù)面效應(yīng)。

    舊數(shù)據(jù)歸檔。很多舊數(shù)據(jù)庫占據(jù)了大量磁盤空間,讀寫卻不頻繁。換言之,這些舊數(shù)據(jù)很可能不是『熱數(shù)據(jù)』。如果業(yè)務(wù)上許可,我們通常會把舊數(shù)據(jù)歸檔到單獨的MySQL實例上。當(dāng)然,應(yīng)用程序需要把讀寫這些數(shù)據(jù)的流量改到新實例。新實例可以按年或按月把舊數(shù)據(jù)存入不同的表以避免單表體積過大,還可以開啟InnoDB透明頁壓縮以減少磁盤空間占用。TiDB是非常理想的數(shù)據(jù)歸檔選項:理論上,一個TiDB集群的容量可以無限擴(kuò)展,不必?fù)?dān)心磁盤空間不夠用;TiDB在計算層和存儲層皆可水平彈性擴(kuò)展,我們得以根據(jù)數(shù)據(jù)體積和讀寫流量的實際增長循序漸進(jìn)地增加服務(wù)器,使整個集群的硬件使用效率保持在較為理想的水平。

    硬件升級(Scale-up)。如果MySQL數(shù)據(jù)體積漲到了1TB,磁盤空間開始吃緊,是不是可以先把磁盤空間加倍,內(nèi)存也加大一些,為開發(fā)團(tuán)隊爭取多一些時間實現(xiàn)數(shù)據(jù)庫橫向擴(kuò)展方案?有些數(shù)據(jù)庫體積到了TB級別,但業(yè)務(wù)上可能不太容易分庫分表。如果開發(fā)團(tuán)隊能夠通過數(shù)據(jù)歸檔等手段使數(shù)據(jù)體積保持在一個較為穩(wěn)定(但仍然是TB級別)的水準(zhǔn),那么適當(dāng)做一下硬件升級也有助于改善服務(wù)質(zhì)量。

    3Redis和關(guān)系型數(shù)據(jù)庫在Shopee的的配合使用

    前文中我們提到,使用Redis來解決關(guān)系數(shù)據(jù)庫高并發(fā)讀寫流量的問題,下面我們就來講講具體的做法。

    先寫緩存,再寫數(shù)據(jù)庫

    比較常用的一種做法是:先寫緩存,再寫數(shù)據(jù)庫。應(yīng)用程序前端直接讀寫Redis,后端勻速異步地把數(shù)據(jù)持久化到MySQL或TiDB。這種做法一般被稱之為穿透式緩存”,其實是把關(guān)系數(shù)據(jù)庫作為Redis數(shù)據(jù)的持久化存儲層。如果一個系統(tǒng)在設(shè)計階段即判明線上會有較高并發(fā)讀寫流量,把Redis放在數(shù)據(jù)庫前面擋一下往往有效。

    在Shopee,一些偏社交類應(yīng)用在大促時的峰值往往會比平時高出數(shù)十上百倍,是典型的性能優(yōu)先型應(yīng)用”(Performance-criticalApplications)。如果開發(fā)團(tuán)隊事先沒有意識到這一點,按照常規(guī)做法讓程序直接讀寫關(guān)系數(shù)據(jù)庫,大促時不可避免會出現(xiàn)一促就倒”的狀況。其實,這類場景很適合借助Redis平緩后端數(shù)據(jù)庫讀寫峰值。

    如果Redis集群整體掛掉,怎么辦?一般來說,有兩個解決辦法:

    性能降級:應(yīng)用程序改為直接讀寫數(shù)據(jù)庫。性能上可能會打一個大的折扣,但是能保證大部分?jǐn)?shù)據(jù)不丟。一些數(shù)據(jù)較為關(guān)鍵的業(yè)務(wù)可能會更傾向于采用這種方式。

    數(shù)據(jù)降級:切換到一個空的Redis集群上以盡快恢復(fù)服務(wù)。后續(xù)可以選擇從零開始慢慢積累數(shù)據(jù),或者運行另一個程序從數(shù)據(jù)庫加載部分舊數(shù)據(jù)到Redis。一些并發(fā)高但允許數(shù)據(jù)丟失的業(yè)務(wù)可能會采用這種方式。

    先寫數(shù)據(jù)庫,再寫緩存

    還有一種做法也很常見:先寫數(shù)據(jù)庫,再寫緩存。應(yīng)用程序正常讀寫數(shù)據(jù)庫,Shopee內(nèi)部有一個中間件DEC(DataEventCenter)可以持續(xù)解析Binlog,把結(jié)果重新組織后寫入到Redis。這樣,一部分高頻只讀查詢就可以直接打到Redis上,大幅度降低關(guān)系數(shù)據(jù)庫負(fù)載。

    把數(shù)據(jù)寫入Redis的時候,可以為特定的查詢模式定制數(shù)據(jù)結(jié)構(gòu),一些不太適合用SQL實現(xiàn)的查詢改為讀Redis之后反而會更簡潔高效。

    此外,相較于雙寫方式”(業(yè)務(wù)程序同時把數(shù)據(jù)寫入關(guān)系數(shù)據(jù)庫和Redis),通過解析Binlog的方式在Redis上重建數(shù)據(jù)有明顯好處:業(yè)務(wù)程序?qū)崿F(xiàn)上較為簡單,不必分心去關(guān)注數(shù)據(jù)庫和Redis之間的數(shù)據(jù)同步邏輯。Binlog方式的缺點在于寫入延遲:新數(shù)據(jù)先寫入MySQL主庫,待其流入到Redis上,中間可能有大約數(shù)十毫秒延遲。實際使用上要論證業(yè)務(wù)是否能接受這種程度的延遲。

    舉例來講,在新訂單實時查詢等業(yè)務(wù)場景中,我們常采用這種先寫數(shù)據(jù)庫,再寫緩存”的方式來消解MySQL主庫上的高頻度只讀查詢。為規(guī)避從庫延遲帶來的影響,部分關(guān)鍵訂單字段的查詢須打到MySQL主庫上,大促時主庫很可能就不堪重負(fù)。歷次大促的實踐證明,以這種方式引入Redis能有效緩解主庫壓力。

    4TiDB在Shopee的使用情況

    講完MySQL和Redis,我們來接著講講TiDB。

    我們從2023年初開始調(diào)研TiDB,到2023年6月份上線了第一個TiDB集群(風(fēng)控日志集群,版本1.0.8)。2023年10月份,我們把一個核心審計日志庫遷到了TiDB上,目前該集群數(shù)據(jù)量約7TB,日常QPS約為10K~15K??傮w而言,2023年上線的集群以日志類存儲為主。

    2023年開始我們嘗試把一些較為核心的線上系統(tǒng)遷移到TiDB上。3月份為買家和賣家提供聊天服務(wù)的Chat系統(tǒng)部分?jǐn)?shù)據(jù)從MySQL遷移到了TiDB。最近的大促中,峰值QPS約為30K,運行平穩(wěn)。今年也有一些新功能選擇直接基于TiDB做開發(fā),比如店鋪標(biāo)簽、直播彈幕和選品服務(wù)等。這些新模塊的數(shù)據(jù)量和查詢量都還比較小,有待持續(xù)觀察驗證。

    TiDB3.0GA后,新的Titan(https://github.com/tikv/titan)存儲引擎吸引了我們。在Shopee,我們允許MySQL表設(shè)計中使用Text等大字段類型,通常存儲一些半結(jié)構(gòu)化數(shù)據(jù)。但是,從MySQL遷移到TiDB的過程中,大字段卻可能成為絆腳石。一般而言,TiDB單行數(shù)據(jù)尺寸不宜超過64KB,越小越好;換言之,字段越大,性能越差。Titan存儲引擎有望提高大字段的讀寫性能。目前,我們已經(jīng)著手把一些數(shù)據(jù)遷移到TiKV上,并打開了Titan,希望能探索出更多應(yīng)用場景。

    集群概況

    目前Shopee線上部署了二十多個TiDB集群,約有400多個節(jié)點。版本以TiDB2.1為主,部分集群已經(jīng)開始試水TiDB3.0。我們最大的一個集群數(shù)據(jù)量約有30TB,超過40個節(jié)點。到目前為止,用戶、商品和訂單等電商核心子系統(tǒng)都或多或少把一部分?jǐn)?shù)據(jù)和流量放在了TiDB上。

    TiDB在Shopee的使用場景

    我們把TiDB在Shopee的使用場景歸納為三類:

    日志存儲場景

    MySQL分庫分表數(shù)據(jù)聚合場景

    程序直接讀寫TiDB的場景

    第一種使用場景是日志存儲。前面講到過,我們接觸TiDB的第一年里上線的集群以日志類存儲為主。通常的做法是:前端先把日志數(shù)據(jù)寫入到Kafka,后端另一個程序負(fù)責(zé)把Kafka里的數(shù)據(jù)異步寫入TiDB。由于不用考慮分庫分表,運營后臺類業(yè)務(wù)可以方便地讀取TiDB里的日志數(shù)據(jù)。對于DBA而言,可以根據(jù)需要線性增加存儲節(jié)點和計算節(jié)點,運維起來也較MySQL分庫分表簡單。

    第二種使用場景是MySQL分庫分表數(shù)據(jù)聚合。Shopee的訂單表和商品表存在MySQL上,并做了細(xì)致的數(shù)據(jù)分片。為了方便其他子系統(tǒng)讀取訂單和商品數(shù)據(jù),我們做了一層數(shù)據(jù)聚合:借助前面提到的DEC解析MySQLBinlog,把多個MySQL分片的數(shù)據(jù)聚合到單一TiDB匯總表。這樣,類似BI系統(tǒng)這樣的旁路系統(tǒng)就不必關(guān)注分庫分表規(guī)則,直接讀取TiDB數(shù)據(jù)即可。除此之外,訂單和商品子系統(tǒng)也可以在TiDB匯總表上運行一些復(fù)雜的SQL查詢,省去了先在每個MySQL分片上查一次最后再匯總一次的麻煩。

    第三種就是程序直接讀寫TiDB。像前面提到的Chat系統(tǒng),舍棄了MySQL,改為直接讀寫TiDB。優(yōu)勢體現(xiàn)在兩個方面:不必做分庫分表,應(yīng)用程序的實現(xiàn)相對簡單、直接;TiDB理論上容量無限大,且方便線性擴(kuò)展,運維起來更容易。

    前面提到過,在Shopee內(nèi)部使用GDS(GeneralDBSync)實時解析MySQLBinlog,并寫入Kafka提供給有需要的客戶端消費。TiDB上也可以接一個Binlog組件,把數(shù)據(jù)變化持續(xù)同步到Kafka上。需要讀取Binlog的應(yīng)用程序只要適配了TiDBBinlog數(shù)據(jù)格式,就可以像消費MySQLBinlog一樣消費TiDBBinlog了。

    從MySQL遷移到TiDB:要適配,不要平移

    把數(shù)據(jù)庫從MySQL搬到TiDB的過程中,DBA經(jīng)常提醒開發(fā)同學(xué):要適配,不要平移。關(guān)于這點,我們可以舉一個案例來說明一下。

    線上某系統(tǒng)最初采用MySQL分表方案,全量數(shù)據(jù)均分到1000張表;遷移到TiDB后我們?nèi)サ袅朔直恚?000張表合為了一張。應(yīng)用程序上線后,發(fā)現(xiàn)某個SQL的性能抖動比較嚴(yán)重,并發(fā)高的時候甚至?xí)?dǎo)致整個TiDB集群卡住。分析后發(fā)現(xiàn)該SQL有兩個特點:

    該SQL查詢頻度極高,占了查詢高峰時全部只讀查詢的90%。

    該SQL是一個較為復(fù)雜的掃表查詢,不易通過添加索引方式優(yōu)化。遷移到TiDB之前,MySQL數(shù)據(jù)庫分為1000張表,該SQL執(zhí)行過程中只會掃描其中一張表,并且查詢被分散到了多達(dá)二十幾個從庫上;即便如此,隨著數(shù)據(jù)體積增長,當(dāng)熱數(shù)據(jù)明顯超出內(nèi)存尺寸后,MySQL從庫也變得不堪重負(fù)了。遷移到TiDB并把1000張表合為一張之后,該SQL被迫掃描全量數(shù)據(jù),在TiKV和SQL節(jié)點之間會有大量中間結(jié)果集傳送流量,性能自然不會好。

    判明原因后,開發(fā)團(tuán)隊為應(yīng)用程序引入了Redis,把Binlog解析結(jié)果寫入Redis,并針對上述SQL查詢定制了適當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)。這些優(yōu)化措施上線后,90%只讀查詢從TiDB轉(zhuǎn)移到了Redis上,查詢變得更快、更穩(wěn)定;TiDB集群也得以削減數(shù)量可觀的存儲和計算節(jié)點。

    TiDB高度兼容MySQL語法的特點有助于降低數(shù)據(jù)庫遷移的難度;但是,不要忘記它在實現(xiàn)上完全不同于MySQL,很多時候我們需要根據(jù)TiDB的特質(zhì)和具體業(yè)務(wù)場景定制出適配的方案。

    5總結(jié)

    本文回顧了Shopee在關(guān)系數(shù)據(jù)庫選型方面的思路,也附帶簡單介紹了一些我們在MySQL、TiDB和Redis使用方面的心得,希望能為大家提供一點借鑒。

    簡單來說,如果數(shù)據(jù)量比較小,業(yè)務(wù)處于早期探索階段,使用MySQL仍然是一個很好的選擇。Shopee的經(jīng)驗是不用過早的為分庫分表妥協(xié)設(shè)計,因為當(dāng)業(yè)務(wù)開始增長,數(shù)據(jù)量開始變大的時候,可以從MySQL平滑遷移到TiDB,獲得擴(kuò)展性的同時也不用犧牲業(yè)務(wù)開發(fā)的靈活性。另一方面,Redis可以作為關(guān)系型數(shù)據(jù)庫的很好的補充,用來加速查詢,緩解數(shù)據(jù)庫壓力,使得數(shù)據(jù)庫能夠更關(guān)注吞吐以及強一致場景。

    幕思城為您更新最近最有用的電商資訊、電商規(guī)則Shopee,Shopee集群Shopee問答。了解更多電商資訊、行業(yè)動向,記得關(guān)注幕思城!

    這個問題還有疑問的話,可以加幕.思.城火星老師免費咨詢,微.信號是為: msc496。

    難題沒解決?加我微信給你講!【僅限淘寶賣家交流運營知識,非賣家不要加我哈】
    >