分散式計劃任務設計與實現
分散式計劃任務設計與實現
摘要
本文主要通過分散式計劃任務軟體設計講述分散式軟體開發。
我的系列文件
Netkiller Architect 手札 |
Netkiller Developer 手札 |
Netkiller PHP 手札 |
Netkiller Python 手札 |
Netkiller Testing 手札 |
---|---|---|---|---|
Netkiller Cryptography 手札 |
Netkiller Linux 手札 |
Netkiller Debian 手札 |
Netkiller CentOS 手札 |
Netkiller FreeBSD 手札 |
Netkiller Shell 手札 |
Netkiller Security 手札 |
Netkiller Web 手札 |
Netkiller Monitoring 手札 |
Netkiller Storage 手札 |
Netkiller Mail 手札 |
Netkiller Docbook 手札 |
Netkiller Project 手札 |
Netkiller Database 手札 |
Netkiller PostgreSQL 手札 |
Netkiller MySQL 手札 |
Netkiller NoSQL 手札 |
Netkiller LDAP 手札 |
Netkiller Network 手札 |
Netkiller Cisco IOS 手札 |
Netkiller H3C 手札 |
Netkiller Multimedia 手札 |
Netkiller Perl 手札 |
Netkiller Amateur Radio 手札 |
Netkiller DevOps 手札 |
您可以使用iBook閱讀當前文件
目錄
- 1. 什麼是分散式計劃任務
- 2. 為什麼採用分散式計劃任務
- 3. 何時使用分散式計劃任務
- 4. 分散式計劃任務的部署
- 5. 誰來寫分散式計劃任務
- 6. 怎麼實現分散式計劃任務
- 6.1. 分散式互斥鎖
- 6.2. 佇列
- 6.3. 其他
1. 什麼是分散式計劃任務
首先我們解釋一下計劃任務,計劃任務是指有計劃的定時執行或者週期性執行的程式,我們最常見的就是Linux “crontab”與Windows “計劃任務程式”,我們也常常藉助他們實現我們的計劃任務,因它們的時間排程程式非常成熟,無需我們再開發一套。
2. 為什麼採用分散式計劃任務
起初,我們也跟大多數人一樣採用crontab排程程式,但隨著專案越來越大,系統越來越複雜,就抱漏出許多問題。
首先是高可用HA需求,當執行計劃任務的伺服器一旦出現故障,所有的計劃任務將停止工作。
其次是效能問題,越來越多的大型計劃任務程式出現,對CPU/IO密集操作,單個節點已經不能滿足我們的需求。
讓計劃任務7*24*365不間斷執行,必需有一套行之有效的方案才行,我意識到必須開發一個全新的分散式計劃任務框架,這樣開發人員無需關注怎樣實現分散式執行,集中寫任務即可。
我首先提出這個框架必需具備幾個特性:
分散式計劃任務需具備以下特性
- 故障轉移,我們至少使用兩個節點,當一個節點出現問題,通過健康狀態檢查程式,另一個節點會自動接管任務。
- 分散式執行,一個任務可以執行在多個節點之上,能夠同時執行,能夠調整執行的前後順序,能夠併發互斥控制。
- 節點可動態調整,最少兩個節點,可以隨時新增節點,解除安裝節點。
- 狀態共享,任務可能會涉及的通訊,例如狀態同步等等。
3. 何時使用分散式計劃任務
何時使用分散式計劃任務
- 遇到效能問題,遇到效能問題你可能首先想到的是分伺服器,但很多應用不具備跨伺服器執行。
- 高可用,一個節點出現故障,另一個節點將接管並繼續執行。
- 災備,你可以將兩個或兩個以上的計劃任務節點分別部署在兩個以上的機房,通過HA特性任何一個機房出現故障,其他機房仍會繼續執行。
4. 分散式計劃任務的部署
兩個節點部署
兩個節點可以實現“主”、“備”方案,佇列(排隊)執行方案與並行方案,其中並行方案又分為不同運行於非同步執行,還涉及到互斥執行。
兩個以上節點部署
多節點建議採用佇列執行方案,並行方案,但不建議使用互斥並行方案(浪費資源)
5. 誰來寫分散式計劃任務
當我們的分散式計劃任務框架一旦完成,任務的編寫部分非常輕鬆,只需繼承框架程式便具備分散式執行的特性。
6. 怎麼實現分散式計劃任務
計劃任務是一個相當複雜的一塊,有作業系統計劃任務,有運用程式計劃任務,有基於TCP/IP的訪問的,有基於命令列訪問的,有定時執行的,有周期執行的,還有基於某些條件觸發執行的。總之解決計劃任務災備,要比web,cache, database 複雜的多。
圖 1. 分時方案
嚴格劃分時間片,交替執行計劃任務,當主系統宕機後,備用系統仍然工作,只不過處理週期拉長了。缺點:週期延長了
圖 2. HA 高可用方案
正常情況下主系統工作,備用系統守候,心跳檢測發現主系統出現故障,備用傳統啟動。缺點:單一系統,不能負載均衡,只能垂直擴充套件(硬體升級),無法水平擴充套件
圖 3. 多路心跳方案
上面的HA是三層的基於VIP技術實現,下面這個方案我採用多路心跳,做服務級,程序級,IP與埠級別的心跳檢測,做正常情況下主系統工作,備用系統守候,心跳檢測發現主系統出現故障,備用傳統啟動,當再次檢測到主系統工作,將執行權交回主系統.缺點:開發複雜,程式健壯性要求高
圖 4. 任務搶佔方案
A,B 兩臺伺服器同時工作,啟動需要一前一後,誰先啟動誰率先加鎖,其他伺服器只能等待,他們同時對互斥鎖進行監控,一旦發現鎖被釋放,其他服務誰先搶到誰執行,執行前首先加排他鎖。 優點:可以進一步優化實現多伺服器橫向擴充套件。 缺點:開發複雜,程式健壯性要求高,有時會出現不釋放鎖的問題。
圖 5. 任務輪循或任務輪循+搶佔排隊方案
任務輪循或任務輪循+搶佔排隊方案
- 每個伺服器首次啟動時加入佇列。
- 每次任務執行首先判斷自己是否是當前可執行任務,如果是便執行。
- 否則檢查自己是否在佇列中,如果在,便推出,如果不在佇列中,便加入佇列。
6.1. 分散式互斥鎖
互斥鎖也叫排它鎖,用於併發時管理多程序或多執行緒同一時刻只能有一個程序或者執行緒操作一個功能。如果你理解什麼是互斥鎖,便很容易理解分散式鎖。
我們將程序,執行緒中的鎖延伸到網際網路上,實現對一個節點執行的程序或執行緒加鎖,解鎖操作。這樣便能控制節點上程序或執行緒的併發。
+------------------+ +------------------+
| Server A | | Server B |
+------------------+ +---------------+ +------------------+
| Thread-1 | | Cluster Mutex | | Thread-1 |
| Thread-2 |----> +---------------+ <----| Thread-2 |
| Thread-3 | | A Thread-2 | | Thread-3 |
+------------------+ +---------------+ +------------------+
|
V
+---------------+
| Cluster Mutex |
+---------------+
| A Thread-2 |
+---------------+
上圖中有兩臺伺服器上執行任務,其中Server A 的 Thread-2 做了加鎖操作,其他程式必須等待它釋放鎖才能執行。
你會問如果 Server A 宕機怎麼辦,是否會一直處於被鎖狀態?我的答案是每個鎖都有一個超時閥值,一旦超時便自動解鎖。
另外我們還要考慮“域”的問題,你也可以叫它命令空間,主要是防止鎖出現同名被覆蓋。
6.2. 佇列
排隊執行
+------------------+ +------------------+
| Server A | | Server B |
+------------------+ +---------------+ +------------------+
| Thread-1 | | Task Queue A | | Thread-1 |
| Thread-2 |----> +---------------+ <----| Thread-2 |
| Thread-3 | | A Thread-2 | | Thread-3 |
+------------------+ | B Thread-1 | +------------------+
| B Thread-3 |
| A Thread-3 |
+---------------+
|
| <sync>
V
+---------------+
| Task Queue B |
+---------------+
| A Thread-2 |
| B Thread-1 |
| B Thread-3 |
| A Thread-3 |
+---------------+
從上圖中我可以看到Task Queue中排隊情況,執行是自上而下的。
注意Task Queue 需要兩個節點,它們是主從結構,A 節點實時向 B 節點同步sh狀態。如果 A 節點出現故障, B 節點立即取代 A 節點。
6.3. 其他
計劃任務可以分散式運行了,但並不能保證萬無一失,配套其他伺服器也要做調整。例如資料庫,快取等等。