從單機到分布式:拆解高并發(fā)數(shù)據(jù)庫架構(gòu)的六大生死決策
一、數(shù)據(jù)庫讀寫分離
核心原理
- 主從集群搭建:一主一從/一主多從,主機負責(zé)讀寫,從機只讀。
- 數(shù)據(jù)同步:主機通過復(fù)制同步數(shù)據(jù)到從機,所有節(jié)點存儲全量數(shù)據(jù)。
- 流量分發(fā):業(yè)務(wù)層將寫操作指向主機,讀操作分發(fā)至從機。
適用場景
- 業(yè)務(wù)量持續(xù)增長,且已優(yōu)化索引、引入緩存后仍性能不足。
常見問題與解法
- 問題:寫后讀數(shù)據(jù)不一致(如剛寫入主機,從機未同步)。
- 解法:
- 讀寫綁定:寫后讀強制走主機(侵入性強,易留坑)。
- 二次讀取:從機讀失敗后重試主機(增加主機壓力)。
- 業(yè)務(wù)分級:核心業(yè)務(wù)讀寫均走主機,非核心業(yè)務(wù)讀寫分離(需嚴格編碼規(guī)范)。
實現(xiàn)方式對比
方式 | 中間件代理 | 客戶端分庫 |
復(fù)雜度 | 高(需獨立部署、集群管理) | 低(基于JDBC封裝) |
維護成本 | 高(需高可用設(shè)計) | 低(無額外部署) |
語言支持 | 跨語言 | 需各語言單獨實現(xiàn) |
二、數(shù)據(jù)庫分庫分表
拆分策略
- 垂直拆分:按列拆分,解決單表字段過多問題(常見于2B場景)。
- 水平拆分:按行拆分,分散數(shù)據(jù)壓力(常見于2C海量數(shù)據(jù)場景)。
拆分時機
- B+樹層數(shù)超過3層(約2000萬數(shù)據(jù))。
- 單表數(shù)據(jù)占滿Innodb Buffer Pool(如2G數(shù)據(jù))。
- 數(shù)據(jù)持續(xù)增長且性能瓶頸明顯。
核心問題與解法
- Join失效:
a.冗余小表(如字典表)。
b.代碼層手動Join。
c.字段冗余(如訂單表直接存商品類型)。
- 事務(wù)一致性:
- 引入分布式事務(wù)(如2PC、3PC)。
- 路由與聚合:
- 路由算法(如Hash、范圍分片)。
- 分片后Count/Order by需中間件或應(yīng)用層聚合。
- 擴展限制
- 數(shù)據(jù)庫連接數(shù)瓶頸(如MySQL默認100連接)。
- 中間件聚合操作性能受限,需權(quán)衡分片數(shù)量。
三、數(shù)據(jù)庫分布式事務(wù)算法
主流方案對比
算法 | 2PC(兩階段提交) | 3PC(三階段提交) |
流程 | 1. 準備階段 | 1. CanCommit |
優(yōu)點 | 強一致性,實現(xiàn)簡單 | 減少阻塞,降低超時風(fēng)險 |
缺點 | 協(xié)調(diào)者單點故障、同步阻塞 | 存在腦裂風(fēng)險(部分提交、部分回滾) |
XA事務(wù)實踐
- 外部XA:跨多數(shù)據(jù)庫實例,由應(yīng)用代碼協(xié)調(diào)(如PHP示例中的多庫事務(wù))。
- 內(nèi)部XA:單實例多存儲引擎事務(wù),由Binlog協(xié)調(diào)(如MySQL內(nèi)部機制)。
隨堂測驗
- **?** 讀寫分離僅提升讀性能,寫仍由主機處理。
- **?** 分庫分表分散寫壓力,提升寫性能。
- **?** 中間件可能成性能瓶頸,需謹慎設(shè)計 ? 中間件性能:取決于架構(gòu)設(shè)計(如集群化),不可一概而論 。
- **?** 3PC存在腦裂風(fēng)險,不優(yōu)先于2PC ? 3PC與2PC選擇:需權(quán)衡「一致性要求」與「系統(tǒng)可用性」,無絕對優(yōu)先級。
- **?** 協(xié)調(diào)者可為代碼(外部XA)或獨立系統(tǒng)(如Binlog)。
思考題解析
- 為何傳統(tǒng)數(shù)據(jù)庫不自帶分庫分表?
關(guān)系型數(shù)據(jù)庫(如MySQL)設(shè)計側(cè)重ACID,分片會破壞事務(wù)和Join,需業(yè)務(wù)層權(quán)衡;而Redis/MongoDB等為高擴展設(shè)計,犧牲部分特性(如強一致性)內(nèi)置Sharding支持。
站在巨人的肩膀上,架構(gòu)之路更從容!
圖片