Table of contents
1 背景
1.1 項目
話說我寫呢篇文章果陣做緊既公司畀某昆蟲公司收購左之後,就要做大量 revamp 工作,亦包括滿足新既業務需求。眾多個系統當中,有一個負責定時定候 call Amazon、ebay 等等既平台既 back-end application,今年加入左 pull Amazon MWS data 既 task scheduling,主要為每一個商戶客既每一個店舖 pull Amazon MWS data。
呢個項目要 call 10
個 Amazon MWS 既 API。
1.2 資料庫設計
DB 設計上做左 partition,分庫分表(for horizontal scaling):
- Sharing rule:所有 DB tables 根據 user ID 既 value 做 sharding——某兩個位既數字會用黎對應 partition index
- 一共分成
100
個 partitions
- 所有 table 資料都由
10
個 physical DB、每個 physical DB 各自有 10
個 physical tables 組成(10
DB 乘 10
tables = 100
partitions)
- 例如:
db3
有 table1_30
至 table1_39
以及 table2_30
至 table2_39
Schema 既設計:
- 以 Amazon MWS API 黎分,有
10
個 logical tables,另外有其他 tables 負責 keep track 住 task scheduling
1.3 Task scheduling 機制
Task scheduling 既機制:
- Scheduler server 會根據平台上面 scheduled job 既時間配置,定時定候 send message 去 cluster 裡面其中一機器
而 cluster 裡面既每一部機器既系統設計係咁:
- 系統引入「三層分發」機制黎實現 distributed task scheduling
- 第一層:
split
- Cluster 裡面只會有一部機器收到 scheduler server 既指令
- 佢之後會做 split partitions 動作,將
100
個 partition indexes 派畀 cluster 裡面既所有機器
- 每部機器得到既果堆 partition indexes 可以係隨機
- 平均黎講每部機器會收到
10
個 partitions
- 例如:
instance3
收到 30
至 39
既 partition indexes
- 第二層:
load
- 當每部機器收到一堆 partition indexes,就會喺呢堆 partition indexes 指定既 physical DB 度 select task records
- 目前既設定 hardcode 左係只拎最新創建既
5
筆 task records
- 拎到 task records 之後就再派畀 cluster 裡面既所有機器
- 第三層:
execute
- 當每部機器收到 task record,就會加落 thread pool 度,等待處理
1.4 Production 場既配置
Production 場既 cluster 部署左 10
部機器。
1.5 任務配置
呢個項目有 2
個任務:
- 創建 task
- 每
1
分鐘執行一次
- 如果店舖既某個 Amazon MWS API 唔存在執行中既任務(例如已經執行完成),就會創建新 task,即係永無休止咁 pull data
- 每個 Amazon MWS API 都會有一個 task
- 每個 API 都係每隔
10
分鐘 call 一次
- 啲 API 分散喺唔同既分鐘(唔同既個位數),唔會同一分鐘做曬
10
個 API
- 例如:
api-3
既執行時間係 HH:03
、HH:13
、HH:23
、HH:33
、HH:43
、HH:53
api-5
既執行時間係 HH:05
、HH:15
、HH:25
、HH:35
、HH:45
、HH:55
- 如此類推
- 處理 task
- 每
1
分鐘執行一次
- 只要 task 到左預定執行時間,就會處理
- 目前既設定 hardcode 左係只拎最新創建既
5
筆 task records(每個 partition 都係咁)
Scheduler server 每分鐘都會 send messages 去負責 split 既機器度 trigger 呢 2
個 producer & consumer 既任務。
2 上線後出現既問題
呢個 project 最近上左線,onboard 左一部分商戶既店舖 records,但就出現左一個都幾尷尬既問題。
項目群組裡面有人話發現唔同既 Amazon MWS API 既 logical tables 出現既結果不一,某啲店舖喺某啲 tables 有 Amazon data records,但喺某啲 tables 就冇。
查一查 logical DB,睇見啲 task records 既預定執行時間係幾日前,呢啲 task records 明明應該已經執行左但就唔知點解一直冇執行到。
另外,有部分 tasks 執行失敗。
3 原因分析
Logical DB 裡面見到一堆應該已經執行但一直冇執行既 records 係黎自某幾個 partitions,而呢幾個 partitions 都有一個共通點,就係店舖數量大過 5
。
呢個其實係一個數學既問題。
首先,我地先假設 pull data 既 task 都可以喺 1
分鐘之內成功完成。跟住,我地要計下有問題既 partition 創建新 task 既速率。假如有問題既 partition-3
有 6
個店舖,而因為我地 call 每一款 Amazon API 都係每 10
分鐘 call 一次,我地有 10
個 API 要 call,咁即係每個 10
分鐘裡面都要執行 60
個 task records,而每到左下一分鐘都有 6
個 data tasks 到左預定執行時間而要被處理。
正因為每分鐘,系統只會喺每個 partition 拎最新創建既 5
筆 task records,一黎呢個速率慢過有問題既 partitions 創建新 task 既速率,二黎因為只會拎最新創建既 task records,所以有啲舊既 task records(唔知點解會有)就一直沉底,永遠都唔輪到佢地被執行。
理論上,假設所有店舖數據都可以平均咁分散喺各個 partition,咁呢個系統目前只係可以處理到 500
個店舖(如果以用戶數量黎計就更少)。