這7個(gè)問(wèn)題難以解決!分庫(kù)分表也沒(méi)吹的那么神……
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
為什么需要分庫(kù)分表?是因?yàn)镸ySQL等數(shù)據(jù)庫(kù)單庫(kù)單表能支撐的系統(tǒng)并發(fā)量和數(shù)據(jù)存儲(chǔ)量存在瓶頸。 中國(guó)有超過(guò) 10 億的網(wǎng)民,單日交易量超過(guò)百萬(wàn)、千萬(wàn)單的交易場(chǎng)景越來(lái)越多。按照一行數(shù)據(jù) 1K ,每日訂單量 500 萬(wàn)計(jì)算,一年需要的數(shù)據(jù)存儲(chǔ)為 1700G,行數(shù)1.7億。 顯然此種情況MySQL 單庫(kù)單表難以保證查詢(xún)寫(xiě)入性能。一張表一年的數(shù)據(jù)量恐怖如斯,交易場(chǎng)景成百上千張表,年復(fù)一年,所帶來(lái)的存儲(chǔ)和并發(fā)量壓力何其巨大呢?業(yè)務(wù)牽引技術(shù)的發(fā)展,分庫(kù)分表技術(shù)應(yīng)運(yùn)而生。 目前分庫(kù)分表技術(shù)似乎成為行業(yè)標(biāo)準(zhǔn),站在鄙視鏈上游。不分庫(kù)分表的系統(tǒng)似乎都是毫無(wú)亮點(diǎn)的垃圾系統(tǒng),然而真的如此嗎?
接下來(lái)我將分享自己在電商交易場(chǎng)景實(shí)際遇到的痛點(diǎn): 一、分庫(kù)分表難以解決分布式事務(wù)問(wèn)題 一般情況下通過(guò)選擇合適的分片屬性,可以保證業(yè)務(wù)在一個(gè)數(shù)據(jù)庫(kù)內(nèi)完成事務(wù)操作。 如用戶(hù)領(lǐng)券場(chǎng)景,用戶(hù)一次領(lǐng)取 3 張優(yōu)惠券,系統(tǒng)寫(xiě)入 3 條優(yōu)惠券記錄和一條領(lǐng)券流水,使用 UserId 進(jìn)行分庫(kù)分表,可以保證同一個(gè)用戶(hù)的 4 條記錄路由到同一數(shù)據(jù)庫(kù),可使用 MySQL 本地事務(wù)即可保證數(shù)據(jù)一致性。 然而**當(dāng)同一個(gè)事務(wù)中多張表的分片屬性不同時(shí),難以保證這些表在同一個(gè)數(shù)據(jù)庫(kù)內(nèi)完成事務(wù)操作,勢(shì)必會(huì)出現(xiàn)難以解決的分布式事務(wù)難題**。 如優(yōu)惠券存在庫(kù)存,在發(fā)券時(shí)需同時(shí)扣減券庫(kù)存,庫(kù)存粒度為券模版ID,用戶(hù)可同時(shí)領(lǐng)取多個(gè)券模版的券。如何保證庫(kù)存扣減、用戶(hù)發(fā)券、領(lǐng)取流水等在同一個(gè)數(shù)據(jù)庫(kù)內(nèi)完成呢?難以實(shí)現(xiàn) 優(yōu)惠券和領(lǐng)券流水,基于 UserId 拆分?jǐn)?shù)據(jù)庫(kù),但庫(kù)存表無(wú)用戶(hù)屬性,只能使用券模版 ID分庫(kù)。然而不同的分片屬性,無(wú)法保證在同一個(gè)數(shù)據(jù)庫(kù)完成事務(wù)操作,難以保證數(shù)據(jù)強(qiáng)一致性。 因此 當(dāng)同一個(gè)事務(wù)中多張表的分片屬性不同時(shí),難以保證這些表在同一個(gè)數(shù)據(jù)庫(kù)內(nèi)完成事務(wù)操作,勢(shì)必會(huì)出現(xiàn)難以解決的分布式事務(wù)難題。即便業(yè)務(wù)側(cè)使用復(fù)雜的業(yè)務(wù)架構(gòu)也難以實(shí)現(xiàn)強(qiáng)一致性,作出妥協(xié)后,可實(shí)現(xiàn)最終一致性。 分庫(kù)分表技術(shù)把數(shù)據(jù)庫(kù)解決不了的問(wèn)題推到業(yè)務(wù)側(cè),“脅迫” 業(yè)務(wù)側(cè)使用復(fù)雜方案參與解決,要求業(yè)務(wù)側(cè)在數(shù)據(jù)一致性上作出妥協(xié) 二、分庫(kù)分表難以實(shí)現(xiàn)非分片屬性的索引查詢(xún)能力 電商交易場(chǎng)景一般使用 UserId 作為分片屬性,聯(lián)合索引的前綴都是UserId,但這并不絕對(duì),交易場(chǎng)景中存在品牌、門(mén)店、司機(jī)、配送等其他維度。 如訂單表使用UserId 作為分片屬性進(jìn)行分庫(kù)分表,查詢(xún)商家在最近 1 小時(shí)的訂單如何實(shí)現(xiàn)呢?由于使用 UserId 分庫(kù)分表,當(dāng)使用商家 ID 查詢(xún)時(shí),需要查詢(xún)所有的分庫(kù)分表,這顯然不現(xiàn)實(shí)。 業(yè)務(wù)側(cè)有幾種實(shí)現(xiàn)方案,1)使用商家 ID分庫(kù)分表,異構(gòu)另一份 MySQL存儲(chǔ) 2)基于 ElasticSearch,異構(gòu)另一種存儲(chǔ)支撐其他維度的檢索場(chǎng)景。 無(wú)論哪一種方案都會(huì)導(dǎo)致,數(shù)據(jù)一致性降低,但系統(tǒng)復(fù)雜度增加。 查詢(xún)商家最近1 小時(shí)的訂單,業(yè)務(wù)上如此簡(jiǎn)單清晰的需求,在分庫(kù)分表后,實(shí)現(xiàn)方案竟如此復(fù)雜。此外還要求業(yè)務(wù)在數(shù)據(jù)準(zhǔn)確性上作出妥協(xié)。 正是因?yàn)榉謳?kù)分表技術(shù)的先天不足,所以極大地增加了業(yè)務(wù)系統(tǒng)架構(gòu)的復(fù)雜性。(甚至很多人以架構(gòu)復(fù)雜為榮,錯(cuò)誤的認(rèn)為系統(tǒng)越復(fù)雜越能體現(xiàn)架構(gòu)能力) 此外還有其他更加 tricky的方案,如為了實(shí)現(xiàn)訂單 Id 查詢(xún),在生成的訂單Id中存放UserId后四位(大概意思),用于定位訂單在哪個(gè)分片。 三、分庫(kù)分表導(dǎo)致的全局主鍵問(wèn)題 MySQL 主鍵支持自增 ID,但是這一特性在分庫(kù)分表后淪為雞肋功能,系統(tǒng)需要分布式方式的 ID 生成器。 如優(yōu)惠券系統(tǒng)在分庫(kù)分表后,優(yōu)惠券 ID 需要借助分布式ID生成器生成全局唯一 ID。常見(jiàn)的實(shí)現(xiàn)方式包括 UUID、雪花算法、美團(tuán) Leaf、百度 UidGenerator等。除維護(hù)業(yè)務(wù)系統(tǒng)外,還需要維護(hù)其他純技術(shù)類(lèi)系統(tǒng)。 毫無(wú)疑問(wèn),這再次增加架構(gòu)的復(fù)雜性。 四、分庫(kù)分表難以建立全局唯一鍵約束 除全局主鍵問(wèn)題,全局唯一鍵也難以實(shí)現(xiàn)。當(dāng)全局唯一鍵的前綴是非分片屬性時(shí),難以實(shí)現(xiàn)全局唯一鍵。 例如訂單在履約完成后,會(huì)生成一筆履約單。系統(tǒng)明確一筆訂單只能有一筆履約單,因此履約單上的訂單 ID 字段應(yīng)該增加唯一鍵約束。然而履約單在基于 UserID 分庫(kù)分表后,OrderId建立的唯一鍵約束只在本表內(nèi)唯一,不能保證在所有的分片內(nèi)實(shí)現(xiàn)全局唯一。 因此 分庫(kù)分表后,數(shù)據(jù)庫(kù)無(wú)法對(duì) OrderId等非分片屬性建立全局的唯一性約束。 除以上具體場(chǎng)景外,分庫(kù)分表面臨的難題依然有很多,如擴(kuò)容難問(wèn)題、存儲(chǔ)成本高、運(yùn)維成本高、高可用難等等問(wèn)題。 五、分庫(kù)分表需要持續(xù)造輪子 選擇分庫(kù)分表后,需要業(yè)務(wù)系統(tǒng)開(kāi)發(fā)和接入很多輪子,包括 ShardingSphere、mycat等方便客戶(hù)端接入分庫(kù)分表。如果使用 ShardingSphere需考慮多種語(yǔ)言多套輪子,使用 Mycat代理層方案又會(huì)面臨性能風(fēng)險(xiǎn)。 分布式 ID 生成器生成全局 ID 為了支持非分片查詢(xún),需要 DTS 消費(fèi)binlog,異構(gòu)存儲(chǔ)For 查詢(xún)。 使用 ElasticSearch用于其他維度檢索。 分庫(kù)分表管理后臺(tái)支持查詢(xún)數(shù)據(jù)、修改數(shù)據(jù) 分庫(kù)分表管理工具支持高效建表、修改表、加索引等 DDL 操作。(1000 張表后,手動(dòng)建表不現(xiàn)實(shí)) …… 層出不窮的問(wèn)題,需要層出不窮的輪子,有些輪子需要自己造,如分庫(kù)分表管理工具等。 不禁要問(wèn),互聯(lián)網(wǎng)大廠能承受如此復(fù)雜架構(gòu)方案,所有的公司都能承受嗎?導(dǎo)致架構(gòu)如此復(fù)雜的根源是什么呢?分庫(kù)分表方案上的先天不足 六、分庫(kù)分表后面臨老大難的擴(kuò)容問(wèn)題 在系統(tǒng)建設(shè)之初,一個(gè)合格的架構(gòu)師必須考慮到:未來(lái)數(shù)據(jù)量龐大后的存儲(chǔ)擴(kuò)容問(wèn)題。這往往讓人很難抉擇,因?yàn)橐獧?quán)衡當(dāng)下的硬件成本和未來(lái)擴(kuò)容成本。 使用分庫(kù)分表后,擴(kuò)容非常困難。如8 個(gè)數(shù)據(jù)庫(kù),想繼續(xù)拆分為 16 個(gè)數(shù)據(jù)庫(kù),一定會(huì)對(duì)業(yè)務(wù)造成影響,停機(jī)遷移是難以避免的問(wèn)題,需要極多的運(yùn)維工具保障擴(kuò)容過(guò)程的安全性和快速性,做到對(duì)業(yè)務(wù)影響程度最低。因此擴(kuò)容成本和風(fēng)險(xiǎn)都極高。 如果在系統(tǒng)建設(shè)初期就拆分為 16 個(gè)庫(kù),又會(huì)面臨硬件和運(yùn)維成本過(guò)高的問(wèn)題。如果每一個(gè)業(yè)務(wù)在系統(tǒng)建設(shè)初期都如此鋪張浪費(fèi),那么公司的硬件成本將極高。 七、大量分庫(kù)分表導(dǎo)致運(yùn)維成本激增 僅一個(gè)業(yè)務(wù)團(tuán)隊(duì)就16 個(gè)數(shù)據(jù)庫(kù),公司那么多業(yè)務(wù)將會(huì)有多么龐大規(guī)模的數(shù)據(jù)庫(kù)實(shí)例。有 DBA 曾分享經(jīng)歷,他一天新部署了120 套 mysql實(shí)例,可想而知,DBA 們面臨了多么龐大的運(yùn)維壓力。 研發(fā)視角和 DBA視角不同,結(jié)論不同。業(yè)務(wù)研發(fā)更多考慮容量不足和并發(fā)度不足風(fēng)險(xiǎn),會(huì)傾向于設(shè)置較大的分庫(kù)分表規(guī)模,而 DBA 會(huì)考慮運(yùn)維成本、硬件成本,希望數(shù)據(jù)庫(kù)規(guī)模在可控范圍內(nèi)。兩者站在不同的視角,各有理由,這是一個(gè)矛盾。 我相信大多數(shù)業(yè)務(wù)研發(fā)不清楚,自家公司MySQL單庫(kù)單實(shí)例的最高并發(fā)度,最高容量,在設(shè)置分片規(guī)模時(shí)往往是拍腦袋決定。只要研發(fā)定的分片方案不離譜,往往 DBA也就接受了。 這些決策中,往往還摻雜歷史問(wèn)題。如團(tuán)隊(duì)已經(jīng)有了 10 個(gè)庫(kù),無(wú)論業(yè)務(wù)規(guī)模如何,新表默認(rèn)拆分10 個(gè)庫(kù),而不會(huì)考慮是否真的需要 10 個(gè)庫(kù)。 八、為什么業(yè)務(wù)系統(tǒng)要替數(shù)據(jù)庫(kù)負(fù)重前行? 分庫(kù)分表技術(shù)把數(shù)據(jù)庫(kù)解決不了的問(wèn)題推到業(yè)務(wù)側(cè),“脅迫” 業(yè)務(wù)側(cè)使用復(fù)雜方案參與解決,要求業(yè)務(wù)側(cè)在數(shù)據(jù)一致性上作出妥協(xié)。 為什么單庫(kù)單表存在系統(tǒng)瓶頸,就選擇分庫(kù)分表呢?有其他更好的方案嗎?分布式數(shù)據(jù)庫(kù)。 分布式數(shù)據(jù)庫(kù)繼承了傳統(tǒng)單機(jī)數(shù)據(jù)庫(kù)的核心特性,同時(shí)還擁有分布式系統(tǒng)的處理能力。雖然起步較晚,可以預(yù)見(jiàn)的是它將是數(shù)據(jù)庫(kù)下一個(gè)發(fā)展方向。 如阿里的 OceanBase基于兩階段提交協(xié)議解決了分布式事務(wù)問(wèn)題,提供了比肩本地事務(wù)的強(qiáng)一致性,此外還提供以下能力解決了分庫(kù)分表技術(shù)難以解決的問(wèn)題 1、2、3、4。相比分庫(kù)分表,業(yè)務(wù)側(cè)使用分布式數(shù)據(jù)庫(kù)的門(mén)檻更低。 提供了全局索引,可以為非分片屬性提供全局的索引和唯一性約束 提供了全局自增主鍵,無(wú)需分布式 ID 生成器。 OceanBase 在性能、擴(kuò)容能力、運(yùn)維和硬件成本上,相比分庫(kù)分表有更優(yōu)的表現(xiàn) 單機(jī)數(shù)據(jù)庫(kù)能支撐的并發(fā)量和存儲(chǔ)量的天花板很低,分庫(kù)分表和分布式數(shù)據(jù)庫(kù)是解決此類(lèi)問(wèn)題的兩種方案。分庫(kù)分表通過(guò)分庫(kù)分表中間件及一系列輪子整合了獨(dú)立的數(shù)據(jù)庫(kù)實(shí)例,可解決并發(fā)量和存儲(chǔ)量的難題,但是犧牲了一致性,增加了使用門(mén)檻。而分布式數(shù)據(jù)庫(kù)則直面困難,使用分布式集群架構(gòu)在解決并發(fā)量和存儲(chǔ)量挑戰(zhàn)的同時(shí),也提供了類(lèi)比單機(jī)數(shù)據(jù)庫(kù)的使用門(mén)檻和強(qiáng)一致性事務(wù)能力。 就像 ElaticSearch 替代 Lucene ,RedisCluster 替代單機(jī)Redis一樣,低門(mén)檻、強(qiáng)一致性、支持高并發(fā)大數(shù)據(jù)量存儲(chǔ)的分布式數(shù)據(jù)庫(kù)一定是數(shù)據(jù)庫(kù)的主流發(fā)展方向。 分庫(kù)分表更像是開(kāi)源數(shù)據(jù)庫(kù)技術(shù)落后互聯(lián)網(wǎng)業(yè)務(wù)發(fā)展時(shí),不得已的臨時(shí)過(guò)渡方案。 該文章在 2024/11/8 14:32:05 編輯過(guò) |
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)... |