分佈式任務調度系統設計與實現

背景

最近一直忙於對數據進行清洗及業務數據輸出,構建了大量的hadoop、hive等定時任務,這些任務存在依賴關係,任務A是任務B的基礎數據生產者,但且叫做B依賴A,那麼B必須在A之後運行(複雜的依賴關係可以查看下圖),同時,這些任務分散到各個系統中,僅僅依靠linux的crontab,或者開發語言內的定時框架,不能更好的維護、管理越來越多的任務,因此,我需要一個可以方便調度、管理的任務中心平臺,但僅限於管理和調度,不對單個任務做分佈式的計算,所以,基於此做了一個簡單的實現。

任務依賴關係圖

目的

  • 實現分佈式調度任務
  • 實現負載均衡
  • 實現任務的依賴關係管理,被依賴任務可自動觸發依賴任務的執行
  • 實現方便添加、刪除、觸發任務等
  • 實現對任務的監控、告警
  • 調度中心必須高可用

架構設計

  • 整體設計
    使用後臺管理系統申請分組,創建任務等。任務創建好後,使用第三方組件(robfig/cron)做定時任務的觸發,任務觸發後,將任務數據包裝,丟進Redis的隊列中,客戶端通過接口消費Redis隊列數據。在任務觸發到丟進Redis隊列之間這個時間段,可以做依賴關係、任務狀態、負載均衡等等操作,以決定是否下發此任務,或者選擇客戶端某個節點執行。客戶端獲取到任務消息後,負責執行任務,上報任務狀態及上報節點負載情況。
  • 模塊
    • 任務調度模塊
    • api模塊(支持rpc、http等)
    • client模塊(支持衆多語言,如Go、Java、Python、Shell等)
    • web後臺管理模塊
    • 內部定時任務

架構設計圖如下
架構設計圖

數據庫設計

  • task:任務表
  • task_prev:前置任務任務表
  • job:觸發的作業表
  • job_state:作業執行狀態表
  • group:分組表,一般以項目或者團隊分組
  • node:用戶節點表

Redis設計

  • tsc:t:i:{tid}:數據庫任務對應cron裝配的任務ID,結構string
  • tsc:j:q:{tid}:{node}:任務隊列,結構list
  • tsc:t:j:l:{tid}:{date}:任務執行中鎖,結構string
  • tsc:w:s:{tid}:{date}:後置任務列表,結構set
  • tsc:w:s:l:{tid}:{date}:後置任務表操作鎖,結構string

核心代碼實現

  • 任務調度
//檢驗是否有任務已經在運行
	exists, err := existsJob(t.Tid, t.TaskDate)
	if err != nil {
		fmt.Println(fmt.Sprintf("task job exists err,jobId:%d,%v", jobId, err))
		saveJobState(jobId, domain.StateInnerFailed)
		return jobId
	}
	if exists {
		fmt.Println(fmt.Sprintf("task job exists,jobId:%d", jobId))
		saveJobState(jobId, domain.StateDuplicated)
		return jobId
	}
//負載均衡,目前簡單做成隨機,後續根據任務數量、cpu、內存等節點負載情況做優化
	targetIp := ips[rand.Intn(len(ips))]
	key := fmt.Sprintf(db.TaskJobQueue, t.gid, targetIp)
	t.JobId = jobId
	value, err := json.Marshal(t)
	if err != nil {
		fmt.Println(fmt.Sprintf("serialization job err,job_id:%d,%v", jobId, err))
		saveJobState(jobId, domain.StateInnerFailed)
		return jobId
	}
	err = db.RDB.RPush(context.Background(), key, value).Err()
	if err != nil {
		fmt.Println(fmt.Sprintf("add job to queue err, job_id: %d,%v", jobId, err))
		saveJobState(jobId, domain.StateInnerFailed)
		return jobId
	}

總結

由於時間有限,花了兩天時間寫完了大概的代碼,項目使用go語言開發,本人一直使用go刷lc,對go情有獨鍾,當然,以目前的情況看,本人go代碼寫的並不夠美觀,但並不影響這個項目的設計初衷。目前待做的事情很多,如權限代碼的加入,負載均衡的完善,日誌的收集,監控告警的實現等等,後面有時間慢慢實現吧。查看源碼請移步 jackmanwu/task-schedule-center

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章