➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
Java collections 進階 - generic type 同 covariance進階 JavaScript

低級 task scheduling 錯誤

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)
  • 例如:db3table1_30table1_39 以及 table2_30table2_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 收到 3039 既 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:03HH:13HH:23HH:33HH:43HH:53
      • api-5 既執行時間係 HH:05HH:15HH:25HH:35HH:45HH:55
      • 如此類推
  • 處理 task
    • 1 分鐘執行一次
    • 只要 task 到左預定執行時間,就會處理
    • 目前既設定 hardcode 左係只拎最新創建既 5 筆 task records(每個 partition 都係咁)
Scheduler server 每分鐘都會 send messages 去負責 split 既機器度 trigger 呢 2producer & 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-36 個店舖,而因為我地 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 個店舖(如果以用戶數量黎計就更少)。