微博分布式存儲作業實現方法
可能通過「高可用架構」聽說過在微博的系統中,單張 MySQL 在線業務表 60 億條數據的場景。很多關注互聯網架構的工程師也非常關注如何如何設計類似系統。下面是一道微博新兵訓練營的分布式存儲課堂練習,要設計合格才能上崗。

考慮到網上有很多架構師也在討論,補充題目一些說明如下。
1、訪問場景
由于上面題目的應用場景,用戶一般情況下,主要查看用戶查看自己收到的最新的微博,以及某個特定用戶 profile 的所有微博。
- 收到的微博,考慮微博以拉為主的模式,則需要訪問關注用戶最近 n 條最新的微博。
- 用戶 profile,需要訪問用戶歷史上所有發表的微博,而且支持分頁查看,可以直接跳轉到某一頁或者某個時間段, 因此需要適當考慮分頁的效率 (可參考擴展閱讀)。
訪問特征
- 從上面描述以及社交網絡的用戶訪問特點來看,用戶大部分情況( > 90% )是訪問最近 7 天的數據。
不需要考慮的點
- 此題主要是存儲層的設計,因此不需要考慮緩存如何設計。
- 由于微博是 異步寫入 的,在某種程度可以起到錯峰作用,所以作業暫時不需要考慮寫入的峰值。
- 不需要考慮 id 如何產生,假定已經有發號服務。
- 不需要考慮用戶收到的微博怎么聚合,那個是更上層服務層的職責。
2、設計需要考慮的點
Scale-out 擴展性
- 將數據拆分到多個獨立的單元存儲
- 可以在適當時機進一步拆分,拆分時候需要繼續提供在線訪問
- 存儲在廉價硬件上,考慮到數據規模比較大,需要適當考慮方案的整體成本,因此不要假定默認全部使用 SSD 存儲。
Cost 成本
- 不同訪問級別的數據存儲在不同訪問速度(成本)的硬件上。
High availability 高可用,以及 Reliability 可靠性 – 復制
在當前場景下,主要通過 MySQL replication 來解決可用性、以及分擔讀的請求。
3、Sharding 策略
Shard 常用策略
range based:根據用戶 uid 來分布,相鄰 uid 的數據保存在一起。hash based:根據某個 hash 函數,將一個用戶 uid 的數據保存在指定的分片。
Re-Sharding 拆分設計
當數據持續增長,原先存儲的數據(或者訪問量)超過當前節點的容量上限,則需要對節點進行進一步拆分。
如何確定shard數量
db buffer > hot data
容量規劃
- 預規劃: 容納未來一段時間的數據
- 2 的指數倍: shard 數量變更簡單
Tradeoff
- 分片多:影響 IO 效率;
- 分片少:擴容頻繁、復雜
4、擴展閱讀
5、部分投稿案例
案例一:使用 user id range 作為分片
案例二:使用user id hash作為分片
方案三 (via 張亮)
歷史數據:
1. 每半年根據日期分庫,如:2015.01-2015.06為一個庫。每天增加1億數據,半年180億,約為0.72T數據,可以保留在1T的磁盤中。
2. 根據 uid 取模分庫(表),便于查詢和分散數據。
當前 n 日數據:
1. 暫定n為10,存儲10億數據。
2. 根據uid + 權重的hash算法分庫。權重可以根據每個uid的微博id數量,粉絲數等指標離線計算。
hash算法需保證:
1. 同一uid需落在一個庫。
2. 權重接近的用戶盡量均勻的落在不同庫。
3. 為了應對突然發生的事件導致訪問量激增,需要考慮2級甚至3級分片,而不宜直接做re-sharding導致數據遷移。多級分片可考慮讀取一個標記,放在zk中。根據標記確定分片的hash算法加入小時等維度。
查詢索引:
1. 增加發帖索引字段,記錄每個用戶的每個帖子的索引。
2. 增加發帖總數統計表,以用戶為維度,每個用戶發一次貼則發帖總數++。
3. 增加二級索引表,記錄每個用戶,每次分片庫的發帖索引。如:uid 1的用戶,在2015年第一帖是該用戶發帖的總數的第10貼,2015年最后一貼是該用戶發帖總數的第50貼。
4. 分頁查詢使用二級索引表,先查到該查哪個真實庫(可能是多個),再到真實庫中獲取數據。
總結:
1. 通過靈活的運用時間維度分片,免去因uid分片數量不足導致的大規模遷移,使用外部flag靈活的控制分片策略。而且用時間維度分片更易做到冷熱分離。
分片邏輯可以靈活到,zk中記錄時間段,某個時間段內,按月分,某個時間段,按年分,之類。
2. 通過離線計算權重的方式均勻分散數據訪問。權重周期性調整,對于調整權重的用戶,需要重點考慮當前n日數據的數據遷移方案。但由于調整權重的用戶屬于少量,所以遷移應該數據變動較小。歷史數據不需權重概念,無需數據遷移。
3. 查詢使用二級索引。使用修改btree結構去掉二級索引能有效減少數據量,但實現難度較大,可以在之后的局部優化中實現,對總體數據庫結構影響不大。
4. 將前n日數據和當天數據整合在一起,之前對微博的場景理解不深,以為有首屏顯示這樣的概念。