最近我們有一個數據注入任務。這意味著從 S3 載入大量源檔,讀取資訊,並將其寫入 Amazon DynamoDB。以下是我們在提出解決方案時考慮的一些事項。
- S3 源檔的總數約為 1500 個,每個檔包含 400 萬行,我們必須寫入 DynamoDB 60 億次。
- 亞馬遜迪納莫DB的寫入費用昂貴。定價(100 寫/秒是 $3000/月),因此我們必須控制寫入率,因為任何超過容量都會丟失。
- 我們的應用程式將在 Kubernets 管理的吊艙中運行。我們希望確保每個吊艙得到充分利用。
- 每個應用程式將是一個多線程JAVA程式,這將使事情更加複雜,但也幫助任務儘快完成。
以下是 DynamoDB 寫入容量、pod 數和緒數之間的關係:
Writing Capacity(writes/second) = (number of threads) * (number of pods) * (number of rows each thread can handle per second)
這是非常直截了當的,我們需要一種方法來確保這個方程是滿意的。瓜瓦圖書館 (https://github.com/google/guava)首先想到的。它有一個設計良好的速率限制器,可以在每次寫入 DynamoDB 之前調用。例如:
int 編號 寫入數秒 = 100;
速率限制器限制器 = 速率限制器.create(寫入數每秒數);
限制器.取得()
更新迪納莫DB();
現在方程變得更簡單:
Writing Capacity(writes/second) = (number of writes on Rate limiter)* (number of pods)
看起來不錯,但當我們測試它時,它有問題:
- 如果我們在亞馬遜上設置 3000 個寫入容量,在 Kubernetes 中設置 5 個 pod,並給每個 pod 5 線程,則單個線程將具有:3000 / 5 / 5 = 120(每秒寫入),一個源檔只能由一個線程處理,我們有 400 萬條記錄,因此完成一個檔需要 400 萬 /240 = 33333 秒或 9 小時。
- 它實際上甚至超過 9 小時,因為對於檔中的一行,有 2 個操作:從 S3 讀取數據並將數據寫入 Dynamo。操作速度較慢會限制實際時間。
- 處理時間過長,S3 連接可能會超時,線程池可能會超時,和/或庫伯奈斯可能會重新啟動。太多事情都會導致工作失敗。
- 提高寫作能力甚至不起作用。單線程容量受檔案讀取和 Dynamo 寫入速度的限制。每個檔仍然具有很高的失敗可能性。
以下是解決問題的方式:
- 仔細觀察了該檔后,我們發現我們可以對它進行一個小聚合。每 4 行可以合併成一行,並一起寫入 DynamoDB。400萬寫突然變成了100萬。
- 我們改為異步發電機操作,以克服發電機寫入限制。現在唯一的限制是在檔讀取。我們調整了窗格中的線程數,以獲得最佳的 CPU 實用程式。
- 我們使用多線程讀取一個檔。
在我們進行了前3個更改後,一個檔可以在2小時內完成。
結論
通過此任務,我們深入瞭解了如何控制容器群集的應用程式輸送量。Kubernetes 使容器編排更容易,但同時也給應用程序帶來了更複雜的問題。基於雲的資料庫 (Dynamo) 降低了維護成本,但它需要額外的工作,以確保應用在其約束下正常工作。