- 從程序員到架構師:大數據量、緩存、高并發、微服務、多團隊協同等核心場景實戰
- 王偉杰編著
- 1844字
- 2022-06-17 17:04:20
3.2 拆分存儲的技術選型
拆分存儲常用的技術解決方案目前主要分為4種:MySQL的分區技術、NoSQL、NewSQL、基于MySQL的分表分庫。
3.2.1 MySQL的分區技術
圖3-1所示為MySQL官方文檔中的架構圖。MySQL的分區技術主要體現在圖3-1中的文件存儲層File System,它可以將一張表的不同行存放在不同的存儲文件中,這對使用者來說比較透明。
在以往的項目中,項目組不使用它的原因主要有3點。
1)MySQL的實例只有一個,它僅僅分攤了存儲,無法分攤請求負載。
2)正是因為MySQL的分區對用戶透明,所以用戶在實際操作時往往不太注意,如果SQL跨了分區,那么操作就會嚴重影響系統性能。
3)MySQL還有一些其他限制,比如不支持query cache、位操作表達式等。感興趣的讀者可以查看官方文檔中的相關內容https://dev.mysql.com/doc/refman/5.7/en/partitioning-limitations.html。

? 圖3-1 MySQL架構圖
3.2.2 NoSQL
比較典型的NoSQL數據庫就是MongoDB。MongoDB的分片功能從并發性和數據量這兩個角度已經能滿足一般大數據量的需求,但是還需要注意下面3點。
1)約束考量:MongoDB不是關系型數據庫而是文檔型數據庫,它的每一行記錄都是一個結構靈活可變的JSON,比如存儲非常重要的訂單數據時,就不能使用MongoDB,因為訂單數據必須使用強約束的關系型數據庫進行存儲。舉個例子,訂單里面有金額相關的字段,這是系統里面的核心數據,所以必須保證每個訂單數據都有這些金額相關的字段,并且不管是怎樣的業務邏輯修改,這些字段都要保存好,這時可以通過數據庫的能力加一層校驗,這樣即使業務代碼出了問題,導致這些字段存儲不正確,也可以在數據庫這一層面阻隔問題。
當然,MongoDB 3.2版以后也支持Schema Validation(模式驗證),可以制訂一些約束規則。不過項目組使用MongoDB的原因之一就是看重它靈活的Schema(模式)。
2)業務功能考量:訂單這種跟交易相關的數據肯定要支持事務和并發控制,而這些并不是MongoDB的強項。而且除了這些功能以外,多年來,事務、鎖、SQL、表達式等各種各樣的操作都在MySQL身上一一實踐過,MySQL可以說是久經考驗,因此在功能上MySQL能滿足項目所有的業務需求,MongoDB卻不一定能,且大部分的NoSQL也存在類似復雜功能支持的問題。
3)穩定性考量:人們對MySQL的運維已經很熟悉了,它的穩定性沒有問題,然而MongoDB的穩定性無法保證,畢竟很多人不熟悉。
基于以上的原因,當時項目組排除了MongoDB。
3.2.3 NewSQL
NewSQL技術還比較新,筆者曾經想在一些不重要的數據中使用NewSQL(比如TiDB),但從穩定性和功能擴展性兩方面考量后,最終沒有使用,具體原因與MongoDB類似。
3.2.4 基于MySQL的分表分庫
最后說一下基于MySQL的分表分庫:分表是將一份大的表數據進行拆分后存放至多個結構一樣的拆分表中;分庫就是將一個大的數據庫拆分成類似于多個結構的小數據庫。場景介紹里就舉了個簡單的例子,這里不再贅述。
項目組沒有選用前面介紹的3種拆分存儲技術,而是選擇了基于MySQL的分表分庫,其中有一個重要考量:分表分庫對于第三方依賴較少,業務邏輯靈活可控,它本身并不需要非常復雜的底層處理,也不需要重新做數據庫,只是根據不同邏輯使用不同SQL語句和數據源而已,因此,之后出問題的時候也能夠較快地找出根源。
如果使用分表分庫,有3個通用技術需求需要實現。
1)SQL組合:因為關聯的表名是動態的,所以需要根據邏輯組裝動態的SQL。比如,要根據一個訂單的ID獲取訂單的相關數據,Select語句應該針對(From)哪一張表?
2)數據庫路由:因為數據庫名也是動態的,所以需要通過不同的邏輯使用不同的數據庫。比如,如果要根據訂單ID獲取數據,怎么知道要連接哪一個數據庫?
3)執行結果合并:有些需求需要通過多個分庫執行后再合并歸集起來。假設需要查詢的數據分布在多個數據庫的多個表中(比如在order1里面的t_order_1,order2里面的t_order_9中),那么需要將針對這些表的查詢結果合并成一個數據集。
而目前能解決以上問題的中間件分為兩類:Proxy模式、Client模式。
1)Proxy模式:圖3-2所示為ShardingSphere官方文檔中的Proxy模式圖,重點看中間的Sharding-Proxy層。
這種設計模式將SQL組合、數據庫路由、執行結果合并等功能全部放在了一個代理服務中,而與分表分庫相關的處理邏輯全部放在了其他服務中,其優點是對業務代碼無侵入,業務只需要關注自身業務邏輯即可。
2)Client模式:ShardingSphere官方文檔中的Client模式如圖3-3所示。這種設計模式將分表分庫相關邏輯放在客戶端,一般客戶端的應用會引用一個jar,然后在jar中處理SQL組合、數據庫路由、執行結果合并等相關功能。

? 圖3-2 Proxy模式圖

? 圖3-3 Client模式圖
這兩種模式的中間件見表3-2。
表3-2 常見分表分庫中間件

這兩種開源中間件的設計模式該如何選擇呢?先簡單對比一下它們的優缺點,見表3-3。
表3-3 Client模式與Proxy模式的優缺點

因為看重“代碼靈活可控”這個優勢,項目組最終選擇了Client模式里的Sharding-JDBC來實現分表分庫,如圖3-3所示。
當然,關于拆分存儲選擇哪種技術合適,在實際工作中需要根據具體情況來定。
- Vue 3移動Web開發與性能調優實戰
- 自然語言處理實戰:預訓練模型應用及其產品化
- LabVIEW入門與實戰開發100例
- ASP.NET Core 5.0開發入門與實戰
- 精通軟件性能測試與LoadRunner實戰(第2版)
- VSTO開發入門教程
- Mastering Rust
- JavaScript:Moving to ES2015
- Hands-On Automation Testing with Java for Beginners
- Scratch趣味編程:陪孩子像搭積木一樣學編程
- Red Hat Enterprise Linux Troubleshooting Guide
- SEO教程:搜索引擎優化入門與進階(第3版)
- 零基礎學SQL(升級版)
- Getting Started with JUCE
- Mapping with ArcGIS Pro