Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

8.6. 怎麼實現分散式計劃任務

計劃任務是一個相當複雜的一塊,有操作系統計劃任務,有運用程序計劃任務,有基于TCP/IP的訪問的,有基于命令行訪問的,有定時執行的,有周期運行的,還有基于某些條件觸發運行的。總之解決計劃任務災備,要比web,cache, database 複雜的多。

圖 8.1. 分時方案

分時方案

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

圖 8.2. HA 高可用方案

HA 高可用方案

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

圖 8.3. 多路心跳方案

多路心跳方案

上面的HA是三層的基于VIP技術實現,下面這個方案我採用多路心跳,做服務級,進程級,IP與連接埠級別的心跳檢測,做正常情況下主系統工作,備用系統守候,心跳檢測發現主系統出現故障,備用傳統啟動,當再次檢測到主系統工作,將執行權交回主系統.缺點:開發複雜,程序健壯性要求高

圖 8.4. 任務搶佔方案

任務搶佔方案

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

圖 8.5. 任務輪循或任務輪循+搶佔排隊方案

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

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

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

  2. 每次任務運行首先判斷自己是否是當前可運行任務,如果是便運行。

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

8.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 宕機怎麼辦,是否會一直處于被鎖狀態?我的答案是每個鎖都有一個超時閥值,一旦超時便自動解鎖。

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

8.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 節點。

8.6.3. 其他

計劃任務可以分散式運行了,但並不能保證萬無一失,配套其他伺服器也要做調整。例如資料庫,緩存等等。