quartz mysql索引_分布式系统中的定时任务全解(二)
在實際項目中,通常需要用到定時任務(定時作業),spring框架提供了很好的實現。 1、? 下載spring-quartz插件包 這里默認當前系統中是集成了spring框架的基本功能的。去網上下載spring定時器的jar包,這里用的是quartz-all-1.8.4.jar,下載完成之后添加的項
概述
上一篇分布式系統中的定時任務全解(一)中對定時任務和定時任務的基礎使用方式進行了說明。這一小節,把分布式場景下的定時任務進行一個大致的講解。
什么是分布式場景呢,當單臺服務器服務能力不夠的時候,就需要更多的服務器進行水平向的擴展,由多臺服務器分工(任務量上的水平劃分,而非業務線上的垂直劃分)的方式來增強服務能力,提供更強的并發請求處理,更短的時間響應。
像第一節說到的定時任務使用場景,大多是一次任務執行僅能有一個服務器在執行,如果是所有服務器都在執行相同的任務,一個是會造成錯誤,就算不會造成錯誤,很多服務器在做重復的工作也是極大的浪費。
所以,分布式場景下定時任務要做的一個基本難點就是:怎么讓某一個定時任務,在一個觸發時點上僅有一臺服務器在執行。
更進一步,如果,你的定時任務涉及到很多同類型的數據要處理,比如說要處理100個輸入文件,處理方式相同;再比如說你的數據庫已經做了分庫處理,業務數據被寫入到了10個數據庫實例中,處理方式相同。那么此時,可以讓更多臺服務器執行定時任務,每臺執行其中的一部分,比如10個輸入文件;再比如1個數據庫實例中的業務數據。
以上兩種場景怎么辦呢?第一種很簡單,后續會提供三種方式去做:1.設置某一臺為任務執行服務器,其他服務器不執行;2.使用quartz的集群功能,實現某一臺執行;3.使用當當開源的elastic-job,實現某一臺執行。第二種場景只有第一種場景中的第3中方式可以做到。
接下來逐個看一下。
實現分布式的方式
設置某一臺為任務執行服務器
這種方式可以采用環境變量的方式來實現,定時任務運行時檢查本機的環境變量值是否為可執行,如果是則執行定時任務,如果不是則直接返回。
@Value("${ISTIMERRUNNER}")
private String isTimerRunner;
@Scheduled(cron="0 0 0 * * ? ")
public void task(){
try {
if("true".equals(isTimerRunner)){
//do something.....
}
} catch (Exception e) {
e.printStackTrace();
}
}
這里有一個需要注意的事項,如果集群環境下,你使用了腳本部署的方式,而且是類似于作者的方式。也就是先把文件拷貝到一臺服務器,啟動好后,調用腳本(腳本參見:http://blog.csdn.net/buqutianya/article/details/51062384),逐個部署到其他服務器。那么,你就需要注意一下了。
遠程ssh調用startup.sh時,tomcat取不到環境變量,這里需要把startup.sh的頂部進行修改:
#!/bin/sh --login
當然這里還有另外一種方式,就是在tomcat的bin目錄中添加一個setenv.sh文件,startup.sh執行時會加載其中的內容。
export ISTIMERRUNNER=true
這種方式有十分明顯的缺陷:1.單點,當任務執行節點出現問題時,整個定時任務全部over;2.資源分配不均衡,隨著定時任務的增多,任務執行服務器的資源占用壓力會越來越大。
當然了,這是在技術能力不夠的時候,最簡單有效的實現方式。
使用quartz的集群功能
quartz這個老牌的定時任務執行工具,在集群方面也提供了很好的支持。quartz的集群是借助數據庫來實現的,所有的服務器實例共享一套數據庫表中存儲的任務、觸發器和調度器信息,實現一個時間點,同一個任務僅有一臺服務器在執行。而且提供了負載均衡和failover失敗轉移功能。
quartz的負載均衡大概是這樣的策略:對于需要調度很多任務的調度器,會近似隨機的選擇服務器執行;對于調度的任務數比較少的(1個或者2個)的觸發器,會盡量的在同一臺服務器上執行。(可以參見這里:http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-11.html)一、Quartz的特點 按作業類的繼承方式來分,主要有以下兩種: 作業類繼承org.springframework.scheduling.quartz.QuartzJobBean類的方式作業類不繼承org.springframework.scheduling.quartz.QuartzJobBean類的方式 注:個人比較推崇第二種,因為這種方式下的
quartz的集群使用也不復雜,接下來一起看一下:
1.導入數據庫表
quartz的集群是基于數據庫實現的,所以首先要把數據庫表結構創建好。創建腳本在quartz的完整下載包里可以找到(官網下載地址:http://www.quartz-scheduler.org/downloads/)。
解壓之后,在docs/dbTable目錄下可以找到你想要的所有常見數據庫類型的創建腳本。
我使用的是sql數據庫,所以使用了tables_mysql_innodb.sql。
這里導入的時候遇到了一個問題,就是創建索引時索引字段過長。這里我采用的方法是把所有的scheduler的長度變成了50,修改之后也就是會限制所有的scheduler的名字在50個字節以內。
2.創建支持集群的scheduler
集群和非集群的配置不同,關鍵就在于scheduler,集群時需要給scheduler配置數據源、將org.quartz.jobStore.isClustered設置為true、以及配置quartz.properties屬性文件。詳細的實現方式可以參見:http://sundoctor.iteye.com/blog/486055
使用elastic-job
elastic-job是基于quartz實現的,最大的不同點是elastic-job把做為共享中心的數據庫換成了zookeeper。所以要使用elastic-job首先要安裝zookeeper。
安裝好zookeeper之后,使用elastic-job也不難,它做了很好的spring集成支持,只需要配置注冊中心和執行任務的job即可。
以下是一個配置文件的示例:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:reg="http://www.dangdang.com/schema/ddframe/reg"
xmlns:job="http://www.dangdang.com/schema/ddframe/job"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.dangdang.com/schema/ddframe/reg http://www.dangdang.com/schema/ddframe/reg/reg.xsd http://www.dangdang.com/schema/ddframe/job http://www.dangdang.com/schema/ddframe/job/job.xsd ">
這里簡單的說一下elastic-job相對于quartz的優勢:
1.使用zookeeper做為協調,更加輕量級,這一點對于使用者來說也是一個困難項,因為無論再小的服務也有一個數據庫,所以定時任務也使用數據庫,那么用起來省事一點。但使用zookeeper一方面速度快,另一方面是不占用現有數據庫的連接和計算資源。
2.支持任務的分片,quartz同一時點,同一任務只能在一臺機器上運行,但是elastic-job可以在多臺機器上運行,并且能夠指定每臺服務器上運行的輸入分片。比如業務數據在10個數據庫,這里總共有5臺服務器,那么每臺服務器在同一個時點,僅處理其中的2個數據庫。做到將可縱向切分的任務,切分給不同的服務器,充分利用資源,加快計算速度。
elastic-job怎么做到的分片,在不同的場景下我們該怎么使用elastic-job,接下來的一節將從源代碼的角度進行講解。
總結
以上是生活随笔為你收集整理的quartz mysql索引_分布式系统中的定时任务全解(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 特斯拉大规模裁员:数百名自动辅助驾驶系统
- 下一篇: mysql 7天自动拒单功能,mysql