狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

如何使用分庫分表支持海量數據的寫入

admin
2024年1月24日 23:1 本文熱度 700

本講將要介紹如何存儲這些海量數據,同時保證相對應的寫入和查詢的性能,以及業務流程不發生太大變化。

不管是打車的訂單、電商里的支付訂單,還是外賣或團購的支付訂單,都是后臺服務中最重要的一環,關乎公司的營收。因此,本講及本模塊都將以 訂單業務 作為案例進行分析。

是否真的要分庫?

分庫當然能夠解決存儲的問題,假設原先單庫只能最多存儲 2 千萬的數據量。采用分庫之后,存儲架構變成下圖 1 所示的分庫架構,每個分庫都可以存儲 2 千萬數據量,容量的上限一下提升了。


圖 1:分庫架構圖

容量提升了,但也帶來了很多其他問題。比如:

  1. 1. 分庫數據間的數據無法再通過數據庫直接查詢了。比如跨多個分庫的數據需要多次查詢或借助其他存儲進行聚合再查詢。

  2. 2. 分庫越多,出現問題的可能性越大,維護成本也變得更高。

  3. 3. 無法保障跨庫間事務,只能借助其他中間件實現最終一致性。

所以在解決容量問題上,可以根據業務場景選擇,不要一上來就要考慮分庫,分表也是一種選擇。

分表是指所有的數據均存在同一個數據庫實例中,只是將原先的一張大表按一定規則,劃分成多張行數較少的表。它與分庫的區別是,分表后的子表仍在原有庫中,而分庫則是子表移動到新的數據庫實例里并在物理上單獨部署。分表的拆分架構如下圖 2 所示:


圖 2:分表架構圖

以本模塊的訂單案例來說,假設訂單只是 單量多而每一單的數據量較小,這就適合采用分表。單條數據量小但行數多,會導致寫入(因為要構建索引)和查詢非常慢,但整體對于容量的占用是可控的。采用分表后,大表變成小表,寫入時構建索引的性能消耗會變小,其次小表的查詢性能也更好。如果采用了分庫,雖然解決了寫入和查詢的問題,但每張表所占有的磁盤空間很少,也會產生資源浪費。兩種方案的對比如下圖 3 所示:

圖 3:單表行數多單數據量小的對比圖

在實際場景里,因為要詳細記錄用戶的提單信息,單個訂單記錄的數據量均較多,所以不存在行數多但單條數據量小的情況。但在其他寫入服務里,經常會出現上述場景,你可以優先采用分表的方案。因為 分表除了能解決容量問題,還能在一定程度上解決分庫所帶來的三個問題。

  1. 1. 分表后可以通過 join 等完成一些富查詢,相比分庫簡單得多。

  2. 2. 分表的數據仍存儲在一個數據庫里,不會出現很多分庫。無須引入一些分庫中間件,因此維護成本和開發成本均較低。

  3. 3. 因為在同一個數據庫里,也可以很好地解決事務問題。

接下來將介紹如何應對行數多且單行數據量較大的場景。通過我們前面的分析,我想你已經知道答案了——采用分庫的方案。

如何實現分庫?

在決定對數據庫進行分庫后,首先要解決的問題便是 如何選擇分庫維度。不同的分庫維度 決定了部分查詢是否能直接使用數據庫,以及是否存在數據傾斜的問題。

分庫維度選擇

下面以訂單為案例,介紹兩種常見不同維度的分庫方式:按 直接滿足最重要的業務場景劃分和最細粒度隨機分。

首先我們來看按 直接滿足最重要的業務場景劃分。在業務上,所有的訂單數據都是隸屬于某一個用戶的。在選擇分庫維度時,可以按訂單歸屬的用戶 這個字段進行分庫。按此維度分庫后,同一個用戶的訂單都在某一個分庫里。分庫后的場景如下圖 4 所示:


圖 4:按購買用戶進行分庫的架構圖

訂單模塊除了提供提交訂單接口外,還會提供給售賣商家對自己店鋪的訂單進行查詢及修改等功能。這些維度的查詢和修改需求,在采用了按購買用戶進行分庫之后,均無法直接滿足了。

這里請你思考一個問題, 訂單模塊最重要的功能是什么?

答案是保證客戶(即買家)的各項訂單功能能夠正常使用,比如下單、下單后立刻(無延遲)查看已購的訂單信息、待支付、待發貨、待配送的訂單列表等。相對來說,訂單里的商品售賣方(即賣家)所使用的功能并不是優先級最高的。因為當我們要對賣家和買家的功能做取舍時,賣家是愿意降低優先級的,畢竟賣家是買賣的受益方。

按購買用戶劃分后,用戶的使用場景都可以直接通過分庫支持,而不需要通過異構數據(存在數據延遲)等手段解決,對用戶來說體驗較好。其次,在同一個分庫中,便于修改同一用戶的多條數據,因此也不存在分布式事務問題。

我們可以通過上述訂單案例抽象出一個分庫準則,即 在確定分庫字段時應該以直接滿足最重要的業務場景為準。很多其他的業務都參考了這一準則,比如:

  1. 1. 對于微博和知乎等用戶生產內容(UGC)的業務,均會按用戶進行分庫。因為用戶新發布文章后就會去查看列表。

  2. 2. 支付系統里,也會按用戶的支付記錄進行分庫。

  3. 3. 在技術上,比如一個微服務下的監控數據,同樣會按微服務進行劃分。同一個微服務的監控數據均存儲在一個分庫里,你可以直接在一個分庫里查看微服務下的所有監控數據。

上述劃分方法雖然直接滿足了最重要的場景,但可能會出現數據傾斜的問題,比如出現一個超級客戶(如企業客戶),購買的訂單量非常大,導致某一個分庫數據量巨多,就會重現分庫前的場景。這屬于最極端的情況之一。

對于傾斜的問題,可以采用 最細粒度的拆分,即按數據的唯一標示進行拆分,對于訂單來說唯一標示即為訂單號。采用訂單號進行分庫之后,用戶的訂單會按 Hash 隨機均勻地分散到某一個分庫里。這樣就解決了某一個分庫數據不均勻的問題。

對于上個小節里的案例,也可以用此手段進行處理。比如:

  1. 1. 按用戶的每一條微博隨機分庫;

  2. 2. 按用戶的每一筆支付記錄隨機分庫;

  3. 3. 同一個微服務里的每一個監控點的數據隨機分庫。

采用最細粒度分庫后,雖然解決了數據均衡的問題,但又帶來了其他問題。

  1. 1. 首先便是除了細粒度查詢外,其他任何維度的查詢均不支持。這就需要通過異構等方式解決,但異構有延遲、對業務是有損的。

  2. 2. 其次采用最細粒度后,對于防重邏輯在數據庫層面已經無法支持。比如用戶對同一個訂單在業務上只能支付一次這一訴求,在支付系統按支付號進行分庫后便不能直接滿足了。因為上述分庫方式會導致不同支付單分散在不同的分庫里,此時,期望在數據庫中通過訂單號的唯一索引進行支付防重就不可實施了。

上述兩種分庫的方式,在解決問題的同時又帶來一些新的問題。在架構中,沒有一種方案可以解決所有問題的,更多的是根據場景去選擇更適合自己的方案。

全局唯一標示

不管采用何種維度的分庫方式,使用原有單庫的數據庫自增主鍵生產數據標示的方案已經不可以使用了。對于全局的數據唯一標示,有兩種常見的生成方式。

1. 使用算法隨機生成。

比如使用機器 IP、時間戳、隨機數等進行組合,生成一個唯一編號。業界成熟的有 Twitter 推出的雪花算法。需要注意的是,為了保證唯一性,雪花算法增加了很多隨機因子,導致計算出來的唯一標示特別長,達到 19 位。

在 JavaScript 里,數據精度和 Java 等語言不完全一致,太長的雪花 ID 在前端存在溢出的問題。因為雪花算法生成的 ID 為 Long 類型,可以采用類似 Base64 等算法,對原始 ID 進行壓縮轉換為 String 類型,降低長度并避免和 JavaScript 精度不統一導致的問題。

2. 基于數據庫主鍵構建一個 ID 生成服務。

雖然不能在插入的時候使用數據庫唯一主鍵,但可以在插入前通過一個服務獲取全局唯一的 ID。ID 生產服務可以基于一張單表實現,每一次外部請求時,均生產一個新的 ID。通過此方式,可以獲得長度較短且為數值類型的全局唯一編號。

但如果每次獲取 ID 時,ID 生成服務都需要從數據庫實時獲取,性能會比較差。為了解決性能問題,可以在生成 ID 的數據庫前置一個具備持久化功能的內存緩存,預生成一批 ID。具體架構如下圖 5 所示:

圖 5:預生成 ID 架構圖

分庫中間件選擇

現在開源提供分庫支持的中間件較多,如 MyCat 等, 整體上各類分庫中間件可以分為兩大類:一種是代理式、另外一種是內嵌式。

代理式分庫中間件 對于業務應用無任何侵入,業務應用和未分庫時一樣使用數據庫,分庫的選擇及分庫的維度對業務層完全隱藏,接入和使用成本極低。代理式的架構如下圖 6 所示:

圖 6:代理式分庫架構圖

代理式雖有使用成本低的好處,但也存在其他一些問題。

  1. 1. 代理式在業務應用和數據庫間增加了一層,導致了性能下降。

  2. 2. 代理式需要解析業務應用的 SQL,并根據 SQL 中的分庫字段進行路由。它需要解析和適配所有 SQL 語法,增加了代理模塊復雜度和出錯的可能性。

  3. 3. 代理層是單獨進程,需要部署占用資源,帶來一定的成本。

內嵌式分庫中間件 是將分庫中間件內置在業務應用中,它只負責分庫的選擇,并不會解析用戶的 SQL。在使用時,業務應用需將分庫字段傳遞給內嵌中間件去計算具體對應的分庫。它相比代理式性能更好。內嵌式的架構如下圖 7 所示:


圖 7:內嵌式的分庫架構圖

除了性能優勢外,內嵌式同樣存在問題。

  1. 1. 有一定侵入性,業務應用與原始單庫模式相比,需要進行一定的改造去適配內嵌式的 API。

  2. 2. 分庫在故障轉移、數據遷移等運維工作時,需要業務應用感知。不過現在的一些內嵌式代理,已經具備非常良好的配置功能,在分庫運維時,業務應用需要配合的內容較少。

其他問題

接下來,再來看幾個常見問題的應對策略。

1. 是否一定需要進行分表或者分庫呢?

不一定。雖然很多互聯網公司的體量很大,用戶非常多,但你千萬不要被這些現象迷惑了。實際上,90% 以上的系統能夠發展到上百萬、上千萬數據量已經很不錯了。對于千萬的數據量,開源的 MySQL 都可以很好地應對,更別說一些商業數據庫了。

另外,當數據增長到一定量級后,可以在業務層面做一些處理。比如根據業務特點,對無效數據、軟刪除數據,以及業務上不會再查詢的數據進行統一歸檔,這也是一個成本低、效果明顯的方式了。

2. 使用業務字段分庫后,如何處理數據傾斜?

如果數據量不是特別大,可以在分庫基礎上,再進行分表。針對數據量較大的場景,可以使用二次分庫的方式。對于訂單量較多的用戶,可以在用戶賬號基礎上再增加一個字段,做進一步的分庫,但此用戶的查詢就會有損了。

此外,還有另外兩個問題,由于需要用到暫未講解的知識,所以我將放在后面的章節結合相關知識詳細講解,今天僅做提及。

3. 如何滿足富查詢?

富查詢是一個無法回避的問題,即采用分庫分表之后,如何滿足跨越分庫的查詢?對于此問題,我將在“ 第 11 講”進行詳細講解。

4. 如何解決跨多庫的修改導致的分布式事務?

跨多庫的修改及多個微服務間的寫操作導致的分布式事務問題,我將在“ 第 19 講”里集中講解。

總結

不斷進行分庫分表一定能解決容量問題,但“殺敵一千,自損八百”的事情少做為宜。使用分庫分表會將代碼和架構的復雜度變高,帶來資源成本上升等問題。另外,在使用系統時,用戶(不管是客戶還是管理員)的查詢體驗也存在一定的降級。

在使用分庫分表前,你需要確定這是否是最優選擇,是否能通過其他更簡單的手段處理無效數據清理?架構是通過最小代價解決問題,而不是技術工具的比拼。

最后,我再給你留一道討論題,你知道的分庫分表的問題還有哪些或者上述問題你還有哪些解決方案?


該文章在 2024/1/24 23:01:01 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved