天天看點

分布式計劃任務設計與實作

中國廣東省深圳市龍華新區民治街道溪山美地

518131

+86 13113668890

+86 755 29812080

版權聲明

轉載請與作者聯系,轉載時請務必标明文章原始出處和作者資訊及本聲明。

分布式計劃任務設計與實作

文檔出處:

<a target="_top" href="http://netkiller.github.io/">http://netkiller.github.io</a>

<a target="_top" href="http://netkiller.sourceforge.net/">http://netkiller.sourceforge.net</a>

2014-09-30

摘要

本文主要通過分布式計劃任務軟體設計講述分布式軟體開發。

我的系列文檔

<a target="_top" href="http://netkiller.github.io/architect/index.html">netkiller architect 手劄</a>

<a target="_top" href="http://netkiller.github.io/developer/index.html">netkiller developer 手劄</a>

<a target="_top" href="http://netkiller.github.io/php/index.html">netkiller php 手劄</a>

<a target="_top" href="http://netkiller.github.io/python/index.html">netkiller python 手劄</a>

<a target="_top" href="http://netkiller.github.io/testing/index.html">netkiller testing 手劄</a>

<a target="_top" href="http://netkiller.github.io/cryptography/index.html">netkiller cryptography 手劄</a>

<a target="_top" href="http://netkiller.github.io/linux/index.html">netkiller linux 手劄</a>

<a target="_top" href="http://netkiller.github.io/debian/index.html">netkiller debian 手劄</a>

<a target="_top" href="http://netkiller.github.io/centos/index.html">netkiller centos 手劄</a>

<a target="_top" href="http://netkiller.github.io/freebsd/index.html">netkiller freebsd 手劄</a>

<a target="_top" href="http://netkiller.github.io/shell/index.html">netkiller shell 手劄</a>

<a target="_top" href="http://netkiller.github.io/security/index.html">netkiller security 手劄</a>

<a target="_top" href="http://netkiller.github.io/www/index.html">netkiller web 手劄</a>

<a target="_top" href="http://netkiller.github.io/monitoring/index.html">netkiller monitoring 手劄</a>

<a target="_top" href="http://netkiller.github.io/storage/index.html">netkiller storage 手劄</a>

<a target="_top" href="http://netkiller.github.io/mail/index.html">netkiller mail 手劄</a>

<a target="_top" href="http://netkiller.github.io/docbook/index.html">netkiller docbook 手劄</a>

<a target="_top" href="http://netkiller.github.io/version/index.html">netkiller version 手劄</a>

<a target="_top" href="http://netkiller.github.io/database/index.html">netkiller database 手劄</a>

<a target="_top" href="http://netkiller.github.io/postgresql/index.html">netkiller postgresql 手劄</a>

<a target="_top" href="http://netkiller.github.io/mysql/index.html">netkiller mysql 手劄</a>

<a target="_top" href="http://netkiller.github.io/nosql/index.html">netkiller nosql 手劄</a>

<a target="_top" href="http://netkiller.github.io/ldap/index.html">netkiller ldap 手劄</a>

<a target="_top" href="http://netkiller.github.io/network/index.html">netkiller network 手劄</a>

<a target="_top" href="http://netkiller.github.io/cisco/index.html">netkiller cisco ios 手劄</a>

<a target="_top" href="http://netkiller.github.io/h3c/index.html">netkiller h3c 手劄</a>

<a target="_top" href="http://netkiller.github.io/multimedia/index.html">netkiller multimedia 手劄</a>

<a target="_top" href="http://netkiller.github.io/perl/index.html">netkiller perl 手劄</a>

<a target="_top" href="http://netkiller.github.io/radio/index.html">netkiller amateur radio 手劄</a>

<a target="_top" href="http://netkiller.github.io/devops/index.html">netkiller devops 手劄</a>

目錄

<a href="http://netkiller.github.io/journal/scheduler.html#what">1. 什麼是分布式計劃任務</a>

<a href="http://netkiller.github.io/journal/scheduler.html#why">2. 為什麼采用分布式計劃任務</a>

<a href="http://netkiller.github.io/journal/scheduler.html#when">3. 何時使用分布式計劃任務</a>

<a href="http://netkiller.github.io/journal/scheduler.html#where">4. 分布式計劃任務的部署</a>

<a href="http://netkiller.github.io/journal/scheduler.html#who">5. 誰來寫分布式計劃任務</a>

<a href="http://netkiller.github.io/journal/scheduler.html#how">6. 怎麼實作分布式計劃任務</a>

<a href="http://netkiller.github.io/journal/scheduler.html#idp55576240">6.1. 分布式互斥鎖</a>

<a href="http://netkiller.github.io/journal/scheduler.html#idp55581312">6.2. 隊列</a>

<a href="http://netkiller.github.io/journal/scheduler.html#idp55585216">6.3. 其他</a>

首先我們解釋一下計劃任務,計劃任務是指有計劃的定時運作或者周期性運作的程式,我們最常見的就是linux “crontab”與windows “計劃任務程式”,我們也常常借助他們實作我們的計劃任務,因它們的時間排程程式非常成熟,無需我們再開發一套。

起初,我們也跟大多數人一樣采用crontab排程程式,但随着項目越來越大,系統越來越複雜,就抱漏出許多問題。

首先是高可用ha需求,當運作計劃任務的伺服器一旦出現故障,所有的計劃任務将停止工作。

其次是性能問題,越來越多的大型計劃任務程式出現,對cpu/io密集操作,單個節點已經不能滿足我們的需求。

讓計劃任務7*24*365不間斷運作,必需有一套行之有效的方案才行,我意識到必須開發一個全新的分布式計劃任務架構,這樣開發人員無需關注怎樣實作分布式運作,集中寫任務即可。

我首先提出這個架構必需具備幾個特性:

分布式計劃任務需具備以下特性

故障轉移,我們至少使用兩個節點,當一個節點出現問題,通過健康狀态檢查程式,另一個節點會自動接管任務。

分布式運作,一個任務可以運作在多個節點之上,能夠同時運作,能夠調整運作的前後順序,能夠并發互斥控制。

節點可動态調整,最少兩個節點,可以随時新增節點,解除安裝節點。

狀态共享,任務可能會涉及的通信,例如狀态同步等等。

何時使用分布式計劃任務

遇到性能問題,遇到性能問題你可能首先想到的是分伺服器,但很多應用不具備跨伺服器運作。

高可用,一個節點出現故障,另一個節點将接管并繼續運作。

災備,你可以将兩個或兩個以上的計劃任務節點分别部署在兩個以上的機房,通過ha特性任何一個機房出現故障,其他機房仍會繼續運作。

兩個節點部署

兩個節點可以實作“主”、“備”方案,隊列(排隊)運作方案與并行方案,其中并行方案又分為不同運作于異步運作,還涉及到互斥運作。

兩個以上節點部署

多節點建議采用隊列運作方案,并行方案,但不建議使用互斥并行方案(浪費資源)

當我們的分布式計劃任務架構一旦完成,任務的編寫部分非常輕松,隻需繼承架構程式便具備分布式運作的特性。

計劃任務是一個相當複雜的一塊,有作業系統計劃任務,有運用程式計劃任務,有基于tcp/ip的通路的,有基于指令行通路的,有定時執行的,有周期運作的,還有基于某些條件觸發運作的。總之解決計劃任務災備,要比web,cache, database 複雜的多。

圖 1. 分時方案

分布式計劃任務設計與實作

嚴格劃分時間片,交替運作計劃任務,當主系統當機後,備用系統仍然工作,隻不過處理周期拉長了。缺點:周期延長了

圖 2. ha 高可用方案

分布式計劃任務設計與實作

正常情況下主系統工作,備用系統守候,心跳檢測發現主系統出現故障,備用傳統啟動。缺點:單一系統,不能負載均衡,隻能垂直擴充(硬體更新),無法水準擴充

圖 3. 多路心跳方案

分布式計劃任務設計與實作

上面的ha是三層的基于vip技術實作,下面這個方案我采用多路心跳,做服務級,程序級,ip與端口級别的心跳檢測,做正常情況下主系統工作,備用系統守候,心跳檢測發現主系統出現故障,備用傳統啟動,當再次檢測到主系統工作,将執行權交回主系統.缺點:開發複雜,程式健壯性要求高

圖 4. 任務搶占方案

分布式計劃任務設計與實作

a,b 兩台伺服器同時工作,啟動需要一前一後,誰先啟動誰率先加鎖,其他伺服器隻能等待,他們同時對互斥鎖進行監控,一旦發現鎖被釋放,其他服務誰先搶到誰運作,運作前首先加排他鎖。 優點:可以進一步優化實作多伺服器橫向擴充。 缺點:開發複雜,程式健壯性要求高,有時會出現不釋放鎖的問題。

圖 5. 任務輪循或任務輪循+搶占排隊方案

分布式計劃任務設計與實作

任務輪循或任務輪循+搶占排隊方案

每個伺服器首次啟動時加入隊列。

每次任務運作首先判斷自己是否是目前可運作任務,如果是便運作。

否則檢查自己是否在隊列中,如果在,便推出,如果不在隊列中,便加入隊列。

互斥鎖也叫排它鎖,用于并發時管理多程序或多線程同一時刻隻能有一個程序或者線程操作一個功能。如果你了解什麼是互斥鎖,便很容易了解分布式鎖。

我們将程序,線程中的鎖延伸到網際網路上,實作對一個節點運作的程序或線程加鎖,解鎖操作。這樣便能控制節點上程序或線程的并發。

上圖中有兩台伺服器上運作任務,其中server a 的 thread-2 做了加鎖操作,其他程式必須等待它釋放鎖才能運作。

你會問如果 server a 當機怎麼辦,是否會一直處于被鎖狀态?我的答案是每個鎖都有一個逾時閥值,一旦逾時便自動解鎖。

另外我們還要考慮“域”的問題,你也可以叫它指令空間,主要是防止鎖出現同名被覆寫。

排隊運作

從上圖中我可以看到task queue中排隊情況,運作是自上而下的。

注意task queue 需要兩個節點,它們是主從結構,a 節點實時向 b 節點同步sh狀态。如果 a 節點出現故障, b 節點立即取代 a 節點。

繼續閱讀