-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BALANCER] Proposing ResourceBalancer
& ResourceUsageHint
#1671
Comments
@garyparrot 感謝提供分析和建議,整體來說我覺得都蠻有道理,以下就幾個點展開一下討論:
@qoo332001 也麻煩看一下喔 |
優化所使用的 CostFunction 要實作
我後面會先把 |
這段時間有修正 ResourceBalancer 內部的實作,現在在在 BackboneImbalanceScenario 測試情境中, ResourceBalancer 在沒有套用 constraint 的情況也能找到和 GreedyBalancer 一樣好的解,詳細圖看更新後的內文。 |
請問這段能給個範例嗎?或是把PR分享一下 |
#1674 有我目前的進度 |
我剛剛思考了一下這個機制很難做到
除了這個限制之外,
這個設計的時間複雜度會不能被接受, 所以我的主張是不要把這個設計貼到 |
這個題目現在是“根據 cost function 給的提示來選擇要優先調整哪幾個 partition/replica",所以或許可以將提示交給 |
我的改法: GreedyBalancer (ResourceUsageHint ver), 有 Constraint一樣優化 Network In/Out, 限制 60 leader 受影響, 180 秒執行 最終 cost 卡在 0.068 那邊,這個結果有符合我前面的想法,GreedyBalancer 不擅長後退。 GreedyBalancer (ResourceUsageHint ver), 無 Constraint一樣優化 Network In/Out, 沒有限制, 180 秒執行 最終 Cost 在 0.011575024015158164,結果和 ResourceBalancer 的優化結果差不多。 |
“後退“這個字很有意思,整個議題描述有兩個很重要的概念:
然後有幾個延伸的問題:
@garyparrot 如今天討論的結果,大幅度調整程式碼永遠是一個方法,但我會希望你能試著分析一下解法,然後看能否在最小的修改下達到最佳的效果,這會是一個很重要的技能,我們一起練習看看 |
這個議題不是透過足夠的線索來後退,他把整個優化問題建立成一顆樹的 traversal,而非現在的 state graph 之上的 hill climbing,這使他可以往不同的區域去做搜尋且保證每次走的都是不同的區域。
是依照重要程度排序 & 挑有潛力的 movement 移動。
這兩個在解不同的問題。
我覺得這兩個問題,一個沒有解,結果都不會好,不會有任何 "明顯“ 的效果顯現
退回起點重新走有很高的機率最後會走到一樣的地方,因為每個 state 都偏好走一樣的路徑,然後到達跟剛剛一樣的 local minimum,透過一些手法可能可以稍微減緩這個問題,但那個要付出複雜度和成效未知。主要還是解的多樣性的問題,如果重新走的話,要如何確保能走到不一樣的地方。
在 State Graph 上解 "走正確的路" 和 "後退" 這兩個機制在既有的解決方法中都很多(Simulated Annleaning & others),如果你想要我嘗試這些方法的話,我可以試試看,但我先前的直覺是能帶來的效果是一個非常大的問號。 |
這部分應該是我沒看懂,不過這樣是暗示說這個手法可以不用 resource hint嗎? |
欸細節是這樣沒錯,但我想表達的是新方法(或是你心裡的打算)哪一個最能幫到最後的結果?也就是在一定限制下找到最好的結果 |
我很喜歡你的直覺。但在工程面上,遇到一個新的需求就打掉重練是一個「最後手段」,所以我才會有前面試著去分析說你帶來的新方法中「有哪些進步」、「這些進步哪個重要」、「重要的進步能否在最小範圍下整合進現在的方法」。如果透過分析討論後確認各種進步的手法都難以改善現有的程式碼,那我們自然可以開始發展一個新的作法。另外我是希望是由你來分析給我看,這樣對你個人才好(一種訓練) 如果我們總是朝打掉重練的方向前進,那很有可能你現在這個新方法在一兩個月後又要打掉了,因為使用者需求來得很快。 最後要記得 greedy 當時也是這樣的思維,基於你當時的手法在最小的改動範圍下帶來一個程度的進步。 |
我想再確認一下,你那隻PR中有多少部分是只屬於新的演算法? 我現在的認知是 RB 需要 resource hint 等機制的幫助才能成行,如果 RB 可以類似 SB or GB 一樣,在一樣的基礎架構下可以完成的話,那就屬於我說在少量改動下完成的改善 所以重點不是要保留 greedy的靈魂! |
PR 裡面剩下 2300 行是我測試用的程式碼。
目前 RB 需要 目前的基礎架構:
我感覺現在的 |
這段我很同意,也如同我們會議上討論過的內容,我們需要一個新的介面來適當的暴露細節幫助Balancer做決定。我們先聚焦在這一塊,可否試著把你說的 這樣可行嗎? |
ok,我接下來會往這個方向執行 |
#1685 有對 POC 版本的框架做一些變動,現在非 Constraint 的情況下可以找到非常接近 cost 0 的解。 ResourceBalancer (POC3) Network Cost, No Constraint, 180smin cost 7.859093057492593E-5 Resource Balancer (POC3) Network Cost, Leader 60, 180s有套用限制的情況下的表現和先前差不多,但圖的波型有比之前的實驗更寛一點,這是因為 min cost = 0.0411147 |
請問一下這個概念是什麼意思?以流量當作成本的話是指每個節點的量都幾乎一樣嗎? |
對,接近 0 基本上代表所有的優化目標都做得很好才會拿到這個分數,比如下面是
|
我嘗試了其他 Balancer 的設計,以 Network Ingress/Egress 為優化目標、限制只能更動 60 Leader、180秒的情境,以下是結果: GreedyRestartBalancer這個是 每次重開基本上也沒辦法到達更好的解,因為隨機的前進的特性,如果有高機率會卡在一個很糟糕的 local minimum,不論怎麽 restart 結局大致上也差不多。 min cost = 0.0729391 GreedyResourceBalancer這個是 Greedy 版本的 ResourceBalancer,他會隨機挑選一個 Replica,把它移動到所有可能的目的地中最好的一個(透過 idealness 比較)。這個版本和原本的 另外由於隨機動有可能把叢集調整得更糟糕,當遇到沒有更好的動作時,會進行 Restart 從起點重新搜尋。 由於沒有 Importance 機制,每個 replica 被更動的機率相同且可以重複動,在 BackboneImbalanceScenario 中真正重要的 replicas 大約在整體的比率大約是 50/10000,要動到他們的機率不高,且即使動到了也要動得好,想要做到動得好這件事情需要其他 9999/10000 個 replicas 的合作,要在有 Restart 機制的情況下,要求 replicas 一起合作,這個情況發生的可能性很低。(合作機制,這點在 min cost = 0.0683978 圖中掉下去的 cost 應該是隨機塞到的。 GreedyResourceBalancer2這個是上者的改良版本,他嘗試在每次 Restart 之間共享一些訊息,這個改進是啟發自 PSO 和 ACO 的演算法。 這個方法的目標是在不使用 importance 機制的情況下,從 idealness 去逆推出每個 replica 的 importance。他逆推的方法是在每次的搬移之後,衡量這個搬移帶來的影響和搬移前差距多大,如果是好的差距,則該 partition 的 weight 會上升,越高的 weight 意味著被挑選到的機率更高。 上圖中可以看到這個改進帶來反效果。 min cost = 0.0733456 GreedyResourceBalancer3上一個版本的問題是每次看的眼界太狹小導致 weight 的更新不準確,這個版本在每次移動的時候把眼界放寬,一次看到所有 180000 種可能的搬移,然後挑最好的那個搬移做,因為這個機制用不上隨機所以連帶 weight 的機制也拿掉了。結果意外的好 min cost = 0.041660666097902546 這個 cost 的值和 這個做法的一個問題是執行的效率,一次檢查 180000 種可能需要一段計算時間,肉眼估計提出一次解的速度要比 因為限制找解的效果好像不錯,所以順手測試看看沒有限制的情況,結果比較遜色一點: min cost = 0.013065321112508865 這個結果比 |
@garyparrot 我覺得這幾個嘗試都蠻有趣的,而且看得出來有收斂問題,期待再看到更多的嘗試 另外這些測試過程是否能方便讓第三方重現?或許跟你之前貢獻的測試工具有關? |
你有嘗試的建議嗎,當初想
看第三方想重現什麼,可能會需要不同的步驟:
如果第三方可以確定 CostFunction 的實作是正確的,不會有誤判的情況,那其實用 CostProfiling 就足以重現驗證負載優化結果這件事情,但驗證 CostFunction 實作正確很困難,之前 NetworkCost 就有出現預估不準的情況 #1641 |
這部分可以嘗試用 protobuf 嗎?
請問一下上面討論中貼出來的圖是在真實叢集上測試,抑或是用
在討論更進一步想法之前,我想先確定“實驗”本身的可複製性,原因是隨著方法越來越複雜,除了程式碼和理論的審查外,我們也需要針對實驗做審查,以免我們在錯誤的結果上做討論 |
這邊有一個 #1704 Bug,所以沒辦法從序列化後的
都是 |
ok,那我們先完成實驗的可複製性 #1693 後再回頭討論演算法的部分 |
這邊可複製性也有兩種層面的複製:
之前有討論過要不要把這些情境(Scenario) 的程式碼推入專案,但後來討論是沒有要推入(#1476 (comment) ),其實那些 Scenario 也只有做到建立 Topic 的部分,Producer/Consumer/Broker 的部分是用我自己獨自的腳本去完成。要在專案內做到這種等級的環境重現可能會需要更高級的工具來實踐。我覺得這個實驗的可複製性如果要做到非常有說服力的話可能會有點複雜。 |
ResourceUsageHint 的部分,在 Helix 的 WAGED Rebalancer https://github.com/apache/helix/wiki/Weight-aware-Globally-even-distribute-Rebalancer 有類似的設計。 先前實驗的時候有發現 ResourceBalancer 設計上的問題,Local Search 問題中有一個情況是優化函數本身很平,因此沒有進步的方向感,ResourceBalancer 將負載排序且依照順序下去挑選,可能會遭遇這種很平的現象,在優化目標少的時候這個問題可能還好,但當目標變多的時候會變成一個問題。 |
這個看起來不錯,很值得參考,感謝分享 |
目前既有的 Balancer 如
GreedyBalancer
或SingleStepBalancer
沒辦法在給定的 constraint 下找出好的解。主要原因為現在的優化框架對於限制這件事情沒有太大的支援,這導致現行的 Balancer 實作會在不可行的優化方向打轉無法前進。這個 Issue 嘗試提出新的機制ResourceUsageHint
和ResourceBalancer
來解決這個問題,目前初步的 POC 測試結果顯示這兩個機制合體可以在NetworkIngressCost
和NetworkEgressCost
和修正過的ReplicaLeaderCost
Constranit 下找到比GreedyBalancer
好更多的解,另外在不套用 constraint 的情況下 POC 版本的,在第二版本的 ResourceBalancer POC 中,無 constraint 的找解結果和ResourceBalancer
的表現稍微輸GreedyBalancer
GreedyBalancer
一樣好。ResourceUsageHint
: 提供資源開銷資訊Constraint 的優化問題中,解空間內的解不一定能夠拿來使用,有時候我們找到一個解,他可能可以把叢集的效能調整得很好,但是要做到那樣的調整會帶來非常大幅度的影響,這可能是使用者不能夠接受的。這個過程可以類比成踩地雷,我們可以有很多格子可以踩(每個格子是一個 Solution),但踩下去(實際計算這個解的好壞)之後才發現這個格子的代價太高(地雷),並非使用者可以接受。
目前的框架和 Balancer 缺乏能夠感知 Constraint 的機制,我們只有一個 Predicate 單純用來告知這個解有沒有違反規則,
Balancer
知道規則違反後其實沒有太大的方向去做改進,最後只能繼續在解空間撞牆瞎矇,這可能導致整個找解的效率和收斂速度降低,對此我們需要一個機制能夠得知這些限制的資訊,以利Balancer
可以往正確的方向找解(提升找解效率)。這個框架的設計包含幾個關於目前問題的直覺
對此我們可以說每個 replica 會和一系列的資源開銷關聯,而每個 broker 會有一系列的建議資源使用量,然後我們需要嘗試去找到一個 replica 分配方法能夠去趨近那個資源使用量。當我們如此建模問題的時候,這個問題會變成一種 Number Partition Problem,我們需要有一群集合和一群數字,我們要把數字塞到任一個集合,目標是要讓集合之間滿足某個特性(如大家的流量差不多 500 MB/s,即負載平衡),只是我們的問題比較特殊,並非使用單純的數字,每個 Replica 的資源開銷比較像是一個向量,向量內的元素代表各項不同的資源開銷。
這個負載和限制的關聯方法存在一個問題,他沒辦法提及 RackAwareness 的情境,在 RackAwareness 中我們是要讓 Partition 的 Replica 不要重複出現在某個集合的節點之間,比如 Broker A,B,C 在同一個機架,上述的限制框架沒辦法描述這種限制,因為限制是套用在節點上,而非一群節點上。為了處理這種情境,這邊的資源是定義在整個叢集的 level,而非個別節點2,一個具體的範例如下圖:
上圖有兩個不同的 Partition,其中一個有兩個 Replica,他們要分配給下面的五個節點,其中三個節點是一個機架,另外兩個是另外一個機架。目前還沒有任何負載配放上去,因此 Cluster Resource Usage 沒有條目。
上圖中把第一個 Partition 分配給 broker k0,這個過程中衍生了三個 Cluster Resource Usage,分別是
網路輸入_k0
和網路輸出_k0
還有機架感知_topicA_partition0_rackA
這三個項目,這三個分別代表不同的叢集資源使用。旁邊的 Cluster Resource Usage 可以追蹤目前的分配方法的資源開銷。接下來把有兩個 Replica 的 Partition 的 Leader 放到 k1 節點,這個過程中也衍生另外三個叢集的資源使用,這些資訊也會追蹤在旁邊的 Cluster Resource Usage
接下來把該 Replica 的 Follower 放到 k2 節點,這個時候我們可以提前偵測到一些問題,我們可以看到
機架感知_topicX_parttion0_rackA
的值變成了 2,這個 2 代表著該 topic/partition 在這個 rackA 中放置了兩個 replica,根據機架感知的規則這個是不被允許的,透過這種追蹤方法,我們可以提前得知某些 "資源" 的使用有沒有被違反,這邊的資源並非指物理上看得見的資源,他可以是虛擬的資源(rack awareness check),這個手法能做到一定的靈活度來同時描述我們的限制和優化目標。下面條列一些關於這個資源追蹤手法的細部需求:
ru(replica0, broker0) -> ru(replica1, broker1) == ru(replica1, broker1) -> ru(replica0, broker0)
ru(replica0, broker0) -> ru(replica1, broker1) -> undo(ru(replica0, broker0)) == ru(replica1, broker1)
ResourceUsage
來描述 constraint,但是該 constraint 只能是resource_usage <= constraint_value
,比如 RackAwareness 就是topic_partition_rackA <= 1.0
,該比較關係不能是別的方向,我們不能有一個 Constraint 是比如500 < resource_usage
這個做法和既有的 CostFunction 計算 CostValue 有非常顯著的差異,CostFunction 目前會把整個叢集的狀態壓成一個數字,這個數字只單純反映好壞,我們很難去從輸入的 ClusterInfo/ClusterBean 去得知出來的數字的前因後果,比如 NetworkIngressCost 中,會影響 cost value 的值就 max 和 min 的節點流量,如果我們的調整影響 max/min 之外的數字,我們沒辦法在 cost value 上看到任何數字上的變化。這導致我們很難從 cost value 去推論剛剛的變化對長遠的影響是好是壞。ResourceUsage 則把所有東西都攤開,所以能以比較細的粒度看到資源的使用情況,這個在後面我們
ResourceBalancer
做決策或提早截斷切斷不可能成立的解是有很大的幫助。程式碼設計上,我們會需要
ClusterCostFunction
和MoveCostFunction
實作ResourceUsageHint
界面來描述他能夠支援他提供這些資訊,具體要實作的函數包含:Replica
的資源開銷有何看法,他最終會回傳一個Map<String, Double>
之類的資訊,描述該Replica
的擺放會帶來什麼樣的資源開銷。NetworkIngressCost
可能會輸出NetworkIngress_Broker0
NetworkIngress_Broker1
NetworkIngress_Broker2
RackAwarenessCost
可能會輸出topicA_partition0_rackA
topicA_partition0_rackB
Replica
在具體資源上的開銷,後面ResourceBalancer
會用上Comparator
比較ResourceUsage
的理想程度,後面ResourceBalancer
會用上Predicate
衡量ResourceUsage
的分配方法是不是踩到限制的底線,後面ResourceBalancer
會用上。ResourceBalancer
ResourceBalancer
本身有融合很多關於 Kafka 節點端優化問題的 heuristic,包含GreedyBalancer
沒有做到這一點,這導致他後面很多優化的嘗試可能都在推翻他前面的搬移,這導致他需要一點時間撞牆撞到更好的解。18^10000
可能的分佈。針對比較 “重要的" replica 我們會嘗試比較多種可能,而不重要的 replica 則可能只挑唯一一種可能做測試。從圖片來看這個過程大概類似這樣
當我們到達這個搜尋樹的結尾時,我們就得到了一個可行的解,會再跑
ClusterCost
和MoveCost
檢查,更新目前找到的最佳解等。比較
下面比較
GreedyBalancer
和 POC 版本的ResourceBalancer
的搬移效果差異測試有 Constraint 的情況
使用
NetworkIngressCost
和NetworkEgressCost
當做ClusterCost
,限制的部分是採用修正後的ReplicaLeaderCost
,限制只能更動 60 個 leader,二者執行時間皆是 180 秒。GreedyBalancer
在 0.07 附近撞牆
ResourceBalancer (第一版 POC)
找到的最佳解在 0.04 附近
ResourceBalancer (第二版 POC)
找到的最佳解也是在 0.04 附近
測試沒有 Constraint 的情況
使用
NetworkIngressCost
和NetworkEgressCost
當做ClusterCost
,沒有限制,二者執行時間皆是 180 秒。GreedyBalancer
他跑出最好的 cost 是 0.012
ResourceBalancer (第一版 POC)
他跑出最好的 cost 是 0.018
ResourceBalancer (第二版 POC)
跑出最好的成績是 0.0118854,類似 GreedyBalancer 的分數
The text was updated successfully, but these errors were encountered: