系統架構設計之-任務排程系統的設計
實習生張大胖
這是個程式碼寫得很爛的電商系統,只要執行一段時間,伺服器就會出現Out Of Memory。
別人都忙得四腳朝天,於是實習生張大胖被抓了壯丁去研究為什麼會出現OOM。
剛入行的張大胖技術水平一般,“裝模作樣”地看程式碼,研究日誌,請教老員工,一個星期過去了,還是一無所獲。
週一例行的專案會議上, 大家似乎要看張大胖的笑話了,沒想到他卻提了一個歪招:“這個OOM問題非常複雜,一時半會兒也解決不了,要不我們定時重啟伺服器怎麼樣?”
一臉嚴肅的專案經理老樑點點頭:“以目前的情況看,也只能如此了。但是不能讓服務中斷,這樣吧,公司有兩臺伺服器,一臺在凌晨1點重啟, 另外一臺在凌晨2點重啟。”
得到了領導的首肯,張大胖趕緊行動,週末他其實已經做了準備,研究了Linux上的crontab,它的格式是這樣樣子:
每天凌晨一點重啟系統,可以這麼寫:
0 1 * * * restart.sh
(注:這裡只是個簡單的例子, 實際上crontab及其靈活)
這個OOM的問題被張大胖靈機一動給解決了,或者說,被臨時隱藏了。
crontab達人的煩惱
大家知道張大胖擅長crontab, 都把一些定時的任務扔給他去做: 什麼定時統計報表,定時同步資料,定時刪除表中的無效訂單… 等等。
張大胖整天面對的就是crontab和指令碼,都快要吐了。
不僅如此,同事們還經常提出一些“變態”的需求:
“大胖,那個定時任務執行得怎麼樣了?”
“大胖,我想把那個定時任務給停掉。”
“大胖,那個定時任務今晚別執行啊!”
“…”
張大胖真是煩死了,他心想,要是提供個介面讓大家使用就好了, 可是crontab似乎並不支援。
要不自己開發一個?
有一次張大胖偶然發現了JDK中的Timer類,似乎也是做這些定時任務的, 不由地眼前一亮,但是仔細研究以後就發現,JDK的Timer還是太簡單了,做點簡單的定時任務還行, 對於複雜的情況,尤其是複雜的時間策略,還是力不從心。
另起爐灶
看來自己需要從頭設計了,張大胖想到了一篇文章《一個著名的日誌系統是怎麼設計出來的?》, 小張用“正交”的原則設計出了Logger, Appender, Formatter這些類。
我也可以使用同樣的原則啊,小張能行,我憑什麼不行?
說幹就幹,先想想需求,非常簡單,不就是定時地執行任務嘛!
“任務”應該是正交中的一個“維度”,我可以抽象出一個介面叫做Task , 嗯,還是叫做Job吧。
對使用者來說,他需要提供一個實現類出來,在實現類中描述要做什麼事情,比如:生成報表,複製資料…
“定時”該怎麼處理? 定時,定時觸發,乾脆叫做Trigger吧。
這個Trigger 可以指定什麼時間開始,時間間隔,執行多少次, 能覆蓋大部分需求了。
可是張大胖轉念一想,如果有人要求類似日曆的重複間隔該怎麼處理? 比如每月的第一天執行,或者每週的最後一天執行,該怎麼辦? crontab特別適合描述這種情況,對,可以搞一個類似於crontab的Trigger。
看來Trigger最好也是個介面,我來提供幾個預設的實現,比如SimpleTrigger,CronTrigger,使用者還可以擴充套件,這樣就靈活了。
Job和Trigger也是正交的關係, 兩者可以互不影響,可以獨立擴充套件,真是不錯, 張大胖不僅得意起來,這設計也很簡單嘛!
但是怎麼把這兩個傢伙結合起來?
必須得有個“大管家”才行,這個大管家應該可以接受Job, 然後按照各種Trigger去執行,嗯,叫做排程器Scheduler應該不錯。
張大胖畫了個草圖,來展示三者之間的關係:
設計得差不多了,可以進入開發階段了, 因為是自己要寫一個類似於框架的東西,讓別人去使用,張大胖開發起來非常有激情,即使是利用晚上和週末的時間來寫程式碼,也是像打了雞血一樣,根本不覺得累。
一個月過去了,第一版新鮮出爐。
這個版本不僅有核心的API像Job, Trigger, Scheduler ,張大胖還專門開發了一個介面,用來展示定時任務的進展,例如什麼時間執行,執行了幾次,失敗了幾次…等等。
張大胖把它叫做“大胖定時任務排程系統”。
持久化
他興奮地拿去讓專案經理老樑看, 可是老樑並不感冒,面無表情地說:“你這個小軟體有啥用啊。”
張大胖被潑了一盆冷水,依然熱情滿滿地推銷:“用了我的這個定時排程系統,任何人都可以輕鬆地啟動,停止任務, 我們們專案中所有的定時任務一目瞭然。 大家就不用找我來手工調整了。”
老樑開玩笑地說:“奧,那你的實習工作就可以結束了,哈哈。”
正巧CTO Bill經過,他饒有興趣地看了一會,提了一個問題:“假設你這個大胖排程系統在執行的時候,機器突然間Down掉了,怎麼處理?”
張大胖一臉懵逼:“什麼怎麼處理,重啟機器唄。”
Bill 說: “之前的任務還能接著執行嗎,比如說一個任務需要執行100次,在機器down掉之前執行了90次,重啟後能不能從第91次執行?”
張大胖有點發窘,不好意思地撓撓頭:“這一點我還真沒考慮到,我現在都是在記憶體中記錄執行的情況,看來得做持久化了。”
Bill 聽到持久化這個詞,知道張大胖已經Get到了,他說,你把這個持久化實現了,到時候直接向我彙報。
得到了CTO的賞識,張大胖不敢怠慢,趕緊進行新的設計, 他抽象了一個叫做JobStore的介面,表示Job的儲存,像什麼Job,Trigger, Job執行情況都儲存在其中。
下面有兩個實現,分別對應記憶體儲存和資料庫儲存。
雖然SQL是標準的,但是不同的資料庫還是有細微的差異, 張大胖覺得得把這些差異給封裝起來, 他又提取了一個介面叫做DriverDelegate, 遮蔽了資料庫細節,讓DbJobStore使用。
他還提供了一個預設的實現StdJDBCDelegate,如果那些資料庫還有獨特的實現,那就寫個子類就行了。
高可用
“大胖定時任務排程系統 2.0” 開發完成以後,張大胖仔細地想了一遍,似乎沒有什麼漏洞了,決定正式向CTO Bill去彙報。
Bill 親切地詢問了張大胖加班加點設計和開發的情況,對他這種不計較個人得失,一心一意為公司謀福利的精神表示了高度的讚賞。
張大胖受寵若驚。
Bill話鋒一轉:“我們的系統最近使用者越來越多,老闆特別提出了高可用的需求,系統的各個元件也得達到高可用!”
“高可用? 拿我的定時排程系統來說,就是說可以部署在多個機器上,一個down掉了,其他的還可以執行,對吧?” 張大胖一點就透。
Bill 讚許地點點頭:“你想好怎麼去實現了嗎?”
“很簡單啊,把定時排程系統部署到多個機器上,形成幾個備份就行了!”
張大胖還在白板上畫了這麼一個圖:
“那同一個時刻,有多少個Scheduler 在執行?” Bill 終於丟擲了重磅炸彈。
張大胖現在明白Bill的疑問了了,三個例項都在執行,那一個Job就有可能執行多次,這肯定是不行的!
他說道:“要不讓三個例項A,B,C都去訪問同一個資料庫吧!”
Bill說:“那三個例項訪問同一份資料,肯定會出現衝突,互相覆蓋,那就亂套了!”
其實,例項A,例項B,例項C組成一個類似叢集的東西,但是同一時刻,一個Job只能在一個例項上執行。
比如Job X 從凌晨1點開始,每隔1小時執行一次,那1:00 的時候Job X可能在例項A上執行, 2:00的時候可能在例項B上執行, 3:00的時候可能在例項C上執行。
也就是說,這三個例項部分地實現了負載均衡。
張大胖說:“這可就難辦了。難道讓這三個例項A,B,C之間互相通訊?”
Bill說道:“那樣有點麻煩,就變成一個分散式系統下的通訊問題了,我們要不用這個資料庫做點文章? 反正這個資料庫已經存了Job的資訊,Trigger的資訊,我們就多加一個表吧,就叫LOCKS,這個表裡邊每一行記錄都可以當做一個‘鎖’來用。”
張大胖表示不太明白。
“很簡單,就是資料庫的‘行’鎖嘛, 比如SELECT * FROM LOCKS where LOCK_NAME=‘TRIGGER’ FOR UPDATE ,這就把那一行記錄給鎖住了, 別的事務只能等待當前事務commit以後才能訪問。”
張大胖還是不太明白。
“比如,伺服器A的例項A在一個事務中先執行了上面SQL, 就把那一行給鎖住了,當伺服器B的例項B也去執行同樣的SQL的時候, 只能等待,對吧? 這不就相當於例項A獲得了鎖嗎?”
“原來如此,以後任何一個排程器例項想要獲取Job的執行時間,設定Job的下一次執行時間的時候,都必須先獲得這個鎖。這樣這些分散式的排程器就不會衝突了,只會執行一個特定時間的Job。 我這就去做個詳細設計,再來彙報。”
開源
兩個月後,“大胖定時任務排程系統 3.0” 開發完畢,在Bill的大力支援和推動下,成功地應用在了公司的專案中。
靈活的設計和擴充套件性,加上持久化,叢集等強大的功能, 系統受到了大家的歡迎。
考慮到很多公司都會有類似的需求,Bill決定把系統開源, 只是“大胖定時任務排程系統”這個名字有點俗,還有點長,Bill把它改名為“Quartz”。
Quartz從此流行開來。
本文轉載自:http://www.dalbll.com/Group/Topic/ArchitecturedDesign/5246
相關文章
- 分散式任務排程系統設計小結分散式
- 分散式系統架構之構建你的任務排程中心分散式架構
- 排程系統設計精要
- 淺談分散式任務排程系統Celery的設計與實現分散式
- PetShop的系統架構設計架構
- Java 系統架構設計Java架構
- 滿大街微服務的年代,滬江任務排程系統獨特的設計思維微服務
- 嵌入式軟體開發之程式架構設計-任務排程架構
- 系統架構設計師學習(二)系統架構設計師緒論架構
- Schedule 排程系統設計(單機版)
- 系統架構設計師感想架構
- PetShop的系統架構設計(一)(轉)架構
- 作業系統精髓設計原理 程式排程作業系統
- 秒殺系統架構如何設計之我見架構
- SaaS架構:多租戶系統架構設計架構
- SaaS架構:中央庫存系統架構設計架構
- 分散式、服務化的 ERP 系統架構設計分散式架構
- 詳解BI系統中的任務排程
- 系統架構設計面試指南(01)-微服務和CAP架構面試微服務
- Hadoop - 任務排程系統比較Hadoop
- 【逆水寒】多方任務系統的資訊架構與行為引導設計——以懸賞系統為例架構
- 億級流量系統架構之如何設計高容錯分散式計算系統架構分散式
- 基於Redis的任務排程設計方案Redis
- B站評論系統架構設計架構
- .NET企業級系統架構設計架構
- 業務單系統架構設計心得(一)架構
- 系統設計:如何設計一個分散式作業排程器 ?- Rakshesh分散式
- 億級流量系統架構之如何設計高容錯分散式計算系統【石杉的架構筆記】架構分散式筆記
- B站千億級點贊系統服務架構設計架構
- 程式設計體系結構(09):分散式系統架構程式設計分散式架構
- Java程式設計知識列表與系統架構演化過程Java程式設計架構
- 技術分享| 快對講排程系統設計概要
- 系統架構設計筆記(105)—— 雲端計算架構筆記
- 系統架構設計師學習之路(31)架構
- 淘寶系商品詳情繫統架構設計架構
- 資料密集型系統架構設計架構
- PDM系統的結構設計
- 劉慎寶 :京東集團財務系統架構設計之路架構