淺談任務分發中的機制與併發
導言
任務模型的抽象具有廣泛通用性的,例如餓了麼騎手每筆騎單是任務,小法庭中交易糾紛的評審也可以被抽象為任務。
下面是簡易的任務系統模組圖,圖示中去除了上下游的模組,保留了核心與小法庭業務特色部分。
在任務分發中核心會遇到以下的挑戰和難點:
• 分配製下任務消費堆積問題以及解法
• 申領制下任務異常消費問題以及解法
• 併發下任務過度消費問題以及解法
任務堆積
任務堆積根本原因是任務的流入速度大於任務的消費速度,導致任務失去時效性。
一個穩定的系統,產生任務堆積的原因可能是流入速度的瞬時增大,例如業務准入規則的變化。也可能是任務消費速度的下降,例如業務完結條件的改變、操作人處理效率下降等。
小法庭任務系統在重構之前,任務的分發採用了分配製(見下圖),任務投票系統處理效率不光低,更致命的是不穩定。造成系統在一個月內流判(未在指定時間內完成)的任務達到了近上萬件。
分配製會設定一個每小時級別的定時任務,該定時任務的邏輯如下:
1.撈取全量在庫任務,對於每個任務,重複以下2-4操作
2.從使用者底池中隨機撈取,進行規則校驗(如同人模型去重、買賣家去重等業務規則),透過校驗後,對選定的使用者進行賦權操作-即加上任務-人關係鎖。
3.重複步驟2,直到一個任務已經分配給N位使用者
4.傳送系統訊息給N位使用者,邀請使用者來小法庭進行評審
對單個任務進行分配,程式平均處理需要花費1-2s。糾紛場景在庫任務量日均為3000件,每次對3000件任務進行程式處理花費0.8-1.6小時。實際中我們經常能發現如下圖所示的定時任務超時的情況,在9-12點時間段,理論上進行了4次定時任務,但是由於執行超時,實際只執行了2次定時任務。此時業務實際系統訊息量就會大大低於預期。下圖是一個定時任務理論執行與實際超時執行的示意圖,其中定時任務的寬度代表所耗時間。
分配製的問題總結
• 分配製的技術定時任務執行時間長,影響了任務投票系統的處理效率,導致任務消費堆積,帶來業務上流判問題。
• 評審員隨機抽取,部分使用者並不願意參與小法庭評審,此時系統訊息就會打擾使用者。
主動申領制
針對任務分發模式進行了技術改造,將任務發放由系統透過業務處理計算分配改成使用者主動來獲取當前可評審任務(如下圖)。在申領制下,我們為符合小法庭評審員資質的使用者,開放了小法庭入口,人群的計算透過每天的離線任務產出獲得。
申領制的鏈路進行了業務邏輯解耦,例如使用者資質校驗的業務邏輯前置在使用者模組與後置投票模組。而不是像分配製中在任務分發環節進行校驗。
模組之間的解耦提高了技術系統的效能與穩定性。且使用者不再被邀約訊息打擾。
任務異常消費
任務異常消費,定義為任務的完成不符合預期的業務規範。各個業務系統表現不一,此處依舊以小法庭系統舉例。
申領制上線後,業務同學發現有評審員向買賣家提供“買票”服務。具體的表現為買家或者賣家一方支付了“服務費”後,評審員選擇該方進行投票。申領制允許使用者換評審任務,因此灰產可以利用反覆刷任務,最終找到指定任務進行評審,更有甚者利用多端裝置同時對指定的任務的一方投票,達到“包贏”操作。此種行為不僅擾亂了評審公正性並且還對正常使用者進行了打擾。
針對這種異常消費現象,技術同學在任務分發時引入使用者鎖佇列。其思想是在分配任務時,不允許使用者無限制換任務,對於單個賬號,在指定時間內的只能看到m件任務,使得灰黑產無法透過不斷重新整理的方式,找到他們期望的任務,從而打擊評審員幫投、包贏的非法手段。
我們在技術上的實現是基於使用者鎖佇列。每次分發任務時,對使用者鎖佇列進行業務規則校驗與維護,再隨機從維護後的m件任務選擇一件任務分發給來申領任務的使用者。
任務過消
在本文中,任務過消是一種併發下的業務系統現象。隨著入口流量逐步增大,使用者評審熱情的持續提升,申領任務爭搶高併發的現象也逐漸增多,造成了任務過快消費。帶來的業務影響是評審員資源的浪費與使用者輿情(使用者看完陳詞進行投票時,任務已經完結)。
透過完善了監控項,業務開發同學統計出某半天併發衝突的量達1.5w,單月估算資源浪費數量可達100萬!
可調整引數分析-使用者疲勞度
小法庭系統核心的任務處理是投票操作,以一秒的時間滑動視窗去計算。投票介面的qps為y,假定申領任務時均勻,當前剩餘可投票數目為r,在當前時刻資源衝突的條件為r < y。此時衝突資源計算可得為:c = y - r
舉一個例子,假設當前只有1個任務,買家支援7票,賣家支援6票,9票為單方勝利條件,此時剩餘可投票數為Min(9 - 6, 9 - 7) = 2。如果此時y = 3,那麼會有產生一個人的投票資源浪費。
我們的目標是,如何透過技術側能力建設,使得系統任務處理時間相對精確可控,同時降低人力資源浪費的情況。對於小法庭這個系統,想要減小併發衝突造成資源浪費的情況,我們要儘量減小單位時間內的系統投票數目為Na。此處有關係:Na∝(線上使用者量Np、使用者疲勞度F、使用者參與意願度M......)。
Na正相關於若干因素,其中調節使用者的疲勞度是一個可控方案,能使得Na變化。透過推理以及實際觀察,當減小使用者疲勞度F時,Na減小,同時資源浪費的情況減少了。調控使用者疲勞度只能進行宏觀的調整,無法做到更精粒度的調整,同時降低了使用者體驗(即使用者每天可參與投票次數減少),不是一個合理的調控方案。
申領時分配-任務鎖佇列
我們上文還提到分配製的缺點,轉頭又有分配的概念了!這並不是烏龍,此處分配的本質是設計任務鎖佇列,來降低資源衝突問題,具體邏輯如下,在每次進行任務發放時
1.從資料庫中撈取n件任務到記憶體中
2.判斷當前是否還有可剩餘任務,若有否則進入下一步,否則進入步驟6。
3.任務鎖佇列作校驗
4.如果佇列 size > m ,重試步驟2。如果佇列 size < m ,將使用者加入該佇列,並設定相應快取失效時間
5.返回該任務
6.不返回任務
到這裡,筆者想提問一下讀者,這種方案能不能徹底解決資源浪費的現象?
答案是不能。對於小法庭的業務場景,假設單邊勝利投票剩餘投票數為m,任務鎖佇列大小為n,只要 n > m,理論上就有機會產生併發衝突。不過合理的設定任務鎖佇列大小n與任務鎖佇列的生命週期T,可以最大程度減少資源浪費。
總結
本文介紹了任務(投票)系統中的三個挑戰,並以小法庭系統為例展開具體的解法。在實際落地中,獲得了不錯的業務效果。
1.任務分配製最佳化為主動申領制後,任務處理效率有了極大提升,任務完結率達到100%,任務的處理時長從平均20小時下降至2小時以內,有效解決了任務堆積的問題。同時再無輿情反饋系統訊息打擾。
2.透過使用者鎖佇列,有效解決了任務異常消費的現象。
3.針對申領制帶來的任務過消,利用分配製中任務鎖的思想,將兩種任務發放方式結合,有效降低了併發衝突產生的資源浪費現象。
思考
橫向來看,除了任務分發(排程)模組,任務流入模組在貼合業務做的定製開發時,也要保障系統程度的通用抽象性。例如,為保證新場景快速穩定的接入,可以採用工廠+策略的設計模式組織程式碼,留給技術系統一定的可擴充套件性。
來自 “ 閒魚技術 ”, 原文作者:皓澤;原文連結:https://mp.weixin.qq.com/s/nGMxR7QDnoolTU5SYIDy2A,如有侵權,請聯絡管理員刪除。
相關文章
- 淺談Android中的事件分發機制Android事件
- 淺談Android 事件分發機制(二)Android事件
- 淺談java中的併發控制Java
- RabbitMQ訊息佇列(三):任務分發機制MQ佇列
- 淺談Java併發Java
- 鴻蒙程式設計江湖:併發程式設計基礎與鴻蒙中的任務併發鴻蒙程式設計
- 淺談併發加鎖
- 深入解析 PostgreSQL 系列之併發控制與事務機制SQL
- 淺談JS事件機制與React事件機制JS事件React
- Python併發程式設計之談談執行緒中的“鎖機制”(三)Python程式設計執行緒
- OkHttp3.0解析——談談內部任務分發器dispatcherHTTP
- HBase 事務和併發控制機制原理
- 聊聊 Elasticsearch 中的任務管理機制Elasticsearch
- 淺談NLP 文字分類/情感分析 任務中的文字預處理工作文字分類
- Python | 淺談併發鎖與死鎖問題Python
- 【多執行緒與高併發】- 淺談volatile執行緒
- MySQL優化系列(八)--鎖機制超詳細解析(鎖分類、事務併發、引擎併發控制)MySql優化
- 淺談高併發-前端優化前端優化
- 淺談Webpack的AMD外掛開發和執行機制Web
- MySQL多版本併發控制機制(MVCC)-原始碼淺析MySqlMVC原始碼
- iOS事件分發機制與實踐iOS事件
- 淺談 PHP 與手機 APP 開發(API 介面開發)PHPAPPAPI
- 「Golang成長之路」併發任務的控制Golang
- WebSphere Process Server V7 中的併發人工任務分配WebServer
- 瞭解js執行機制——微任務與巨集任務JS
- 淺談uCOS-II的任務(上)
- 淺談前端業務開發中的經驗與感想前端
- 【Storm篇】--Storm併發機制ORM
- DB2預設的事務及併發鎖機制DB2
- 淺談雲端計算與安全沙箱機制!
- Fork Join 併發任務執行框架框架
- Java併發程式設計中的鎖機制詳解Java程式設計
- 併發機制的底層實現
- Java 同步機制淺談Java
- 淺談TCP(1):狀態機與重傳機制TCP
- View事件分發機制View事件
- 淺談 LiveData 的通知機制LiveData
- 探索View的事件分發機制View事件