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