一,為什麼要冗餘數據
互聯網數據量很大的業務場景,往往資料庫需要進行水平切分來降低單庫數據量。
水平切分會有一個patition key,通過patition key的查詢能夠直接定位到庫,但是非patition key上的查詢可能就需要掃描多個庫了。
此時常見的架構設計方案,是使用數據冗餘這種反範式設計來滿足分庫後不同維度的查詢需求。
例如:訂單業務,對用戶和商家都有訂單查詢需求:
Order(oid, info_detail);
T(buyer_id, seller_id, oid);
如果用buyer_id來分庫,seller_id的查詢就需要掃描多庫。
如果用seller_id來分庫,buyer_id的查詢就需要掃描多庫。
此時可以使用數據冗餘來分別滿足buyer_id和seller_id上的查詢需求:
T1(buyer_id, seller_id, oid)
T2(seller_id, buyer_id, oid)
同一個數據,冗餘兩份,一份以buyer_id來分庫,滿足買家的查詢需求;一份以seller_id來分庫,滿足賣家的查詢需求。
如何實施數據的冗餘,是今天將要討論的內容。
二,服務同步雙寫

顧名思義,由服務層同步寫冗餘數據,如上圖1-4流程:
- 業務方調用服務,新增數據
- 服務先插入T1數據
- 服務再插入T2數據
- 服務返回業務方新增數據成功
優點:
- 不複雜,服務層由單次寫,變兩次寫
- 數據一致性相對較高(因為雙寫成功才返回)
缺點:
- 請求的處理時間增加(要插入兩次,時間加倍)
- 數據仍可能不一致,例如第二步寫入T1完成後服務重啟,則數據不會寫入T2
如果系統對處理時間比較敏感,引出常用的第二種方案。
三,服務非同步雙寫

數據的雙寫並不再由服務來完成,服務層非同步發出一個消息,通過消息匯流排發送給一個專門的數據複製服務來寫入冗餘數據,如上圖1-6流程:
- 業務方調用服務,新增數據
- 服務先插入T1數據
- 服務向消息匯流排發送一個非同步消息(發出即可,不用等返回,通常很快就能完成)
- 服務返回業務方新增數據成功
- 消息匯流排將消息投遞給數據同步中心
- 數據同步中心插入T2數據
優點:
- 請求處理時間短(只插入1次)
缺點:
- 系統的複雜性增加了,多引入了一個組件(消息匯流排)和一個服務(專用的數據複製服務)
- 因為返回業務線數據插入成功時,數據還不一定插入到T2中,因此數據有一個不一致時間窗口(這個窗口很短,最終是一致的)
- 在消息匯流排丟失消息時,冗餘表數據會不一致
不管是服務同步雙寫,還是服務非同步雙寫,服務都需要關注「冗餘數據」帶來的複雜性。如果想解除「數據冗餘」對系統的耦合,引出常用的第三種方案。
四,線下非同步雙寫

為了屏蔽「冗餘數據」對服務帶來的複雜性,數據的雙寫不再由服務層來完成,而是由線下的一個服務或者任務來完成,如上圖1-6流程:
- 業務方調用服務,新增數據
- 服務先插入T1數據
- 服務返回業務方新增數據成功
- 數據會被寫入到資料庫的log中
- 線下服務或者任務讀取資料庫的log
- 線下服務或者任務插入T2數據
優點:
- 數據雙寫與業務完全解耦
- 請求處理時間短(只插入1次)
缺點:
- 返回業務線數據插入成功時,數據還不一定插入到T2中,因此數據有一個不一致時間窗口(這個窗口很短,最終是一致的)
- 數據的一致性依賴於線下服務或者任務的可靠性
五,總結
互聯網數據量大的業務場景,常常:
- 使用水平切分來降低單庫數據量
- 使用數據冗餘的反範式設計來滿足不同維度的查詢需求
- 使用服務同步雙寫法能夠很容易的實現數據冗餘
- 為了降低時延,可以優化為服務非同步雙寫法
- 為了屏蔽「冗餘數據」對服務帶來的複雜性,可以優化為線下非同步雙寫法
- 文章自:58沈劍架構師之路
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/287754.html