Java 任務排程器的靈感來自於對比 Quartz 更簡單的叢集java.util.concurrent.ScheduledExecutorService
的需求。
因此,也受到使用者的讚賞(cbarbosa2、rafaelhofmann、BukhariH):
你的自由棒極了!我很高興我擺脫了石英並用你的取代了它,這更容易處理!
巴博薩2
另請參閱為什麼不使用 Quartz?
< dependency >
< groupId >com.github.kagkarlsson</ groupId >
< artifactId >db-scheduler</ artifactId >
< version >15.0.0</ version >
</ dependency >
在資料庫模式中建立scheduled_tasks
表。請參閱 postgresql、oracle、mssql 或 mysql 的表定義。
實例化並啟動調度程序,然後調度程序將啟動任何定義的重複任務。
RecurringTask < Void > hourlyTask = Tasks . recurring ( "my-hourly-task" , FixedDelay . ofHours ( 1 ))
. execute (( inst , ctx ) -> {
System . out . println ( "Executed!" );
});
final Scheduler scheduler = Scheduler
. create ( dataSource )
. startTasks ( hourlyTask )
. threads ( 5 )
. build ();
// hourlyTask is automatically scheduled on startup if not already started (i.e. exists in the db)
scheduler . start ();
有關更多範例,請繼續閱讀。有關內部工作原理的詳細信息,請參閱工作原理。如果您有 Spring Boot 應用程序,請查看 Spring Boot 用法。
已知在生產中運行 db-scheduler 的組織清單:
公司 | 描述 |
---|---|
數位郵政 | 挪威數位信箱供應商 |
維集團 | 北歐國家最大的運輸集團之一。 |
明智的 | 一種廉價、快速的海外匯款方式。 |
貝克爾職業教育 | |
莫尼托里亞 | 網站監控服務。 |
裝載機 | Web 應用程式的負載測試。 |
州政府 | 挪威公共道路管理局 |
光年 | 一種簡單易行的全球投資方式。 |
資產淨值 | 挪威勞工及福利管理局 |
現代循環 | 使用 ModernLoop 提高面試安排、溝通和協調的效率,從而滿足公司的招募需求。 |
迪菲亞 | 挪威電子醫療公司 |
天鵝 | Swan 幫助開發人員將銀行服務輕鬆嵌入他們的產品中。 |
陶朗 | TOMRA 是一家挪威跨國公司,設計和製造用於回收的反向自動販賣機。 |
請隨意打開 PR 將您的組織加入到清單中。
另請參閱可運行的範例。
使用startTasks
建構器方法定義一個重複任務並安排該任務在啟動時首次執行。完成後,任務將根據定義的時間表重新排程(請參閱預先定義的時間表類型)。
RecurringTask < Void > hourlyTask = Tasks . recurring ( "my-hourly-task" , FixedDelay . ofHours ( 1 ))
. execute (( inst , ctx ) -> {
System . out . println ( "Executed!" );
});
final Scheduler scheduler = Scheduler
. create ( dataSource )
. startTasks ( hourlyTask )
. registerShutdownHook ()
. build ();
// hourlyTask is automatically scheduled on startup if not already started (i.e. exists in the db)
scheduler . start ();
對於具有多個實例和計劃的重複任務,請參閱範例 RecurringTaskWithPersistentScheduleMain.java。
一次性任務的實例在將來的某個時間(即非重複性)具有單一執行時間。實例 ID 在此任務中必須是唯一的,並且可用於對某些元資料(例如 ID)進行編碼。對於更複雜的狀態,支援自訂可序列化 java 物件(如範例中所使用的)。
定義一個一次性任務並啟動調度程序:
TaskDescriptor < MyTaskData > MY_TASK =
TaskDescriptor . of ( "my-onetime-task" , MyTaskData . class );
OneTimeTask < MyTaskData > myTaskImplementation =
Tasks . oneTime ( MY_TASK )
. execute (( inst , ctx ) -> {
System . out . println ( "Executed! Custom data, Id: " + inst . getData (). id );
});
final Scheduler scheduler = Scheduler
. create ( dataSource , myTaskImplementation )
. registerShutdownHook ()
. build ();
scheduler . start ();
……然後在某個時刻(在運行時),使用SchedulerClient
安排執行:
// Schedule the task for execution a certain time in the future and optionally provide custom data for the execution
scheduler . schedule (
MY_TASK
. instanceWithId ( "1045" )
. data ( new MyTaskData ( 1001L ))
. scheduledTo ( Instant . now (). plusSeconds ( 5 )));
例子 | 描述 |
---|---|
啟用立即執行Main.java | 當調度執行到now() 或更早運行時,本地Scheduler 將得到提示,並「喚醒」以比正常情況更早地檢查新執行(由pollingInterval 配置)。 |
MaxRetriesMain.java | 如何設定執行重試次數的限制。 |
ExponentialBackoffMain.java | 如何使用指數退避作為重試策略,而不是預設的固定延遲。 |
ExponentialBackoffWithMaxRetriesMain.java | 如何使用指數退避作為重試策略以及對最大重試次數的硬性限制。 |
TrackingProgressRecurringTaskMain.java | 重複作業可以儲存task_data 作為跨執行持久狀態的一種方式。這個例子展示瞭如何操作。 |
SpawningOtherTasksMain.java | 使用executionContext.getSchedulerClient() 示範另一個任務調度實例。 |
SchedulerClientMain.java | 示範SchedulerClient 的一些功能。調度、獲取計劃執行等。 |
RecurringTaskWithPersistentScheduleMain.java | 多實例重複作業,其中Schedule 作為task_data 的一部分儲存。例如,適用於多租戶應用程序,其中每個租戶都應該有一個重複任務。 |
StatefulRecurringTaskWithPersistentScheduleMain.java | |
JsonSerializerMain.java | 將task_data 的序列化從 Java 序列化(預設)覆寫為 JSON。 |
JobChainingUsingTaskDataMain.java | 作業鏈,即「當該實例執行完畢後,安排另一個任務。 |
JobChainingUsingSeparateTasksMain.java | 作業鏈,如上所述。 |
攔截器Main.java | 使用ExecutionInterceptor 在所有ExecutionHandler 執行之前和之後注入邏輯。 |
例子 | 描述 |
---|---|
基本範例 | 基本的一次性任務和重複任務 |
事務性暫存作業 | 以事務方式暫存作業的範例,即確保當事務提交(以及其他資料庫修改)時後台作業運行。 |
長時間運行作業 | 長時間運行的作業需要在應用程式重新啟動後繼續存在,並避免從頭開始重新啟動。此範例示範如何在關閉時保持進度,以及限製作業每晚執行的技術。 |
循環狀態追蹤 | 一個循環任務,其狀態可以在每次運行後修改。 |
平行作業產生器 | 示範如何使用重複作業產生一次性作業,例如用於並行化。 |
作業鏈 | 具有多個步驟的一次性工作。下一步安排在上一個步驟完成後。 |
多實例循環 | 示範如何實現相同類型但可能不同的計劃和資料的多個重複作業。 |
調度程序是使用Scheduler.create(...)
建構器建立的。建構器具有合理的預設值,但以下選項是可配置的。
.threads(int)
線程數。預設10
。
.pollingInterval(Duration)
調度程序檢查資料庫是否正常執行的頻率。預設10s
。
.alwaysPersistTimestampInUTC()
調度程序假設用於持久時間戳記的列持久存在Instant
s,而不是LocalDateTime
s,即以某種方式將時間戳綁定到區域。但是,某些資料庫對此類類型(沒有區域資訊)或其他怪癖的支援有限,這使得「始終以 UTC 儲存」成為更好的選擇。對於這種情況,請使用此設定始終以 UTC 格式儲存即時資訊。 PostgreSQL 和 Oracle 模式經過測試以保留區域資訊。 MySQL和MariaDB -schemas不並且應該使用此設定。注意:為了向後相容,「未知」資料庫的預設行為是假設資料庫保留時區。對於「已知」資料庫,請參閱AutodetectJdbcCustomization
類別。
.enableImmediateExecution()
如果啟用此功能,調度程序將嘗試向本機Scheduler
提示在計劃運行now()
或過去的某個時間後有要執行的執行。注意:如果在事務內呼叫schedule(..)
/ reschedule(..)
,調度程式可能會嘗試在更新可見之前執行它(交易尚未提交)。但它仍然保留,因此即使未命中,它也會在下一個polling-interval
之前運行。您也可以使用排程器方法scheduler.triggerCheckForDueExecutions()
) 以程式設計方式觸發提前檢查到期執行。預設false
。
.registerShutdownHook()
註冊一個關閉鉤子,它將在關閉時呼叫Scheduler.stop()
。應始終呼叫 Stop 來正常關閉並避免死執行。
.shutdownMaxWait(Duration)
調度程序在中斷執行程式服務執行緒之前將等待多長時間。如果您發現自己使用此功能,請考慮是否可以定期檢查 ExecutionHandler 中的executionContext.getSchedulerState().isShuttingDown()
併中止長時間運行的任務。預設30min
。
.enablePriority()
可以定義執行的優先級,並確定從資料庫中取得到期執行的順序。具有較高優先值的執行將在具有較低優先值的執行之前運行(從技術上講,排序將按order by priority desc, execution_time asc
)。考慮使用 0-32000 範圍內的優先級,因為此欄位定義為SMALLINT
。如果需要更大的值,請修改架構。目前,此功能是可選的,只有選擇透過此組態設定啟用優先權的使用者才需要列priority
。
使用TaskInstance.Builder
設定每個實例的優先權:
scheduler . schedule (
MY_TASK
. instance ( "1" )
. priority ( 100 )
. scheduledTo ( Instant . now ()));
筆記:
(execution_time asc, priority desc)
上新增索引(取代舊的execution_time asc
)可能會有所幫助。null
值可能會根據資料庫(低或高)進行不同的解釋。 如果您每秒執行 >1000 次執行,您可能需要使用lock-and-fetch
輪詢策略來降低開銷和提高吞吐量(了解更多)。如果沒有,預設的fetch-and-lock-on-execute
就可以了。
.pollUsingFetchAndLockOnExecute(double, double)
使用預設輪詢策略fetch-and-lock-on-execute
。
如果上次從資料庫取得的是完整批次 ( executionsPerBatchFractionOfThreads
),則當剩餘執行數小於或等於lowerLimitFractionOfThreads * nr-of-threads
時,將觸發新的取得。取得的執行不會被鎖定/選取,因此調度程式在執行時將與其他執行個體競爭鎖定。所有資料庫都支援。
預設值: 0,5, 3.0
.pollUsingLockAndFetch(double, double)
使用輪詢策略lock-and-fetch
該策略使用select for update .. skip locked
以減少開銷。
如果上次從資料庫取得的是完整批次,則當剩餘執行數小於或等於lowerLimitFractionOfThreads * nr-of-threads
時,將觸發新的取得。每次取得的執行數量等於(upperLimitFractionOfThreads * nr-of-threads) - nr-executions-left
。已為此調度程序實例鎖定/選取取得的執行,從而節省一個UPDATE
語句。
對於正常使用,設定為例如0.5, 1.0
。
對於高吞吐量(即保持線程繁忙),設定為例如1.0, 4.0
。目前,心跳不會針對佇列中選取的執行進行更新(如果upperLimitFractionOfThreads > 1.0
則適用)。如果它們停留在那裡超過4 * heartbeat-interval
(預設20m
),而不開始執行,它們將被檢測為死亡並可能再次解鎖(由DeadExecutionHandler
確定)。目前由postgres支援。 sql-server也支援這一點,但測試表明這很容易出現死鎖,因此在理解/解決之前不建議這樣做。
.heartbeatInterval(Duration)
更新運行執行的心跳時間戳記的頻率。預設5m
。
.missedHeartbeatsLimit(int)
在執行被認為死亡之前可能會錯過多少次心跳。預設6
。
.addExecutionInterceptor(ExecutionInterceptor)
增加一個ExecutionInterceptor
,它可以圍繞執行注入邏輯。對於 Spring Boot,只需註冊一個ExecutionInterceptor
類型的 Bean 即可。
.addSchedulerListener(SchedulerListener)
新增一個SchedulerListener
,它將接收與 Scheduler 和 Execution 相關的事件。對於 Spring Boot,只需註冊一個SchedulerListener
類型的 Bean 即可。
.schedulerName(SchedulerName)
此調度程序實例的名稱。當調度程序選擇執行時,該名稱將儲存在資料庫中。預設<hostname>
。
.tableName(String)
用於追蹤任務執行的表的名稱。建立表格時會相應地變更表定義中的名稱。預設的scheduled_tasks
。
.serializer(Serializer)
序列化任務資料時使用的序列化器實作。預設使用標準 Java 序列化,但 db-scheduler 也捆綁了GsonSerializer
和JacksonSerializer
。請參閱 KotlinSerializer 的範例。另請參閱序列化器下的其他文件。
.executorService(ExecutorService)
如果指定,則使用此外部管理的執行程式服務來執行執行。理想情況下,仍應提供它將使用的線程數(用於調度程序輪詢優化)。預設為null
。
.deleteUnresolvedAfter(Duration)
執行未知任務後自動刪除的時間。這些通常可能是不再使用的舊的重複任務。這是非零的,以防止由於配置錯誤(丟失已知任務)和滾動升級期間的問題而意外刪除任務。預設14d
。
.jdbcCustomization(JdbcCustomization)
db-scheduler 嘗試自動偵測用於查看是否有任何 jdbc 互動需要自訂的資料庫。此方法是一個逃生口,允許明確設定JdbcCustomizations
。預設自動檢測。
.commitWhenAutocommitDisabled(boolean)
預設情況下,不會對資料來源連線發出提交。如果停用自動提交,則假定事務由外部事務管理器處理。將此屬性設為true
可覆寫此行為並使調度程序始終發出提交。預設false
。
.failureLogging(Level, boolean)
配置如何記錄任務失敗,即從任務執行處理程序拋出的Throwable
。使用日誌等級OFF
可以完全停用這種日誌記錄。預設WARN, true
。
任務是使用Tasks
中的建構器類別之一建立的。建構器具有合理的預設值,但可以覆寫以下選項。
選項 | 預設 | 描述 |
---|---|---|
.onFailure(FailureHandler) | 參見說明。 | 當ExecutionHandler 拋出異常時該怎麼辦。預設情況下,重複任務會根據其Schedule 重新安排,一次性任務會在 5m 後再次重試。 |
.onDeadExecution(DeadExecutionHandler) | ReviveDeadExecution | 當偵測到死執行(即心跳時間戳過時的執行)時該怎麼辦。預設情況下,死執行被重新安排到now() 。 |
.initialData(T initialData) | null | 第一次安排重複任務時要使用的資料。 |
該庫包含許多用於重複任務的計劃實作。參見課程Schedules
。
行程 | 描述 |
---|---|
.daily(LocalTime ...) | 每天在指定時間運行。可選擇指定時區。 |
.fixedDelay(Duration) | 下一次執行時間是上次完成執行後的Duration 。注意:當在startTasks(...) 中使用時,此Schedule 將初始執行安排到Instant.now() |
.cron(String) | Spring 風格的 cron 表達式 (v5.3+)。該模式- 被解釋為禁用的時間表。 |
配置計劃的另一個選項是使用Schedules.parse(String)
讀取字串模式。
目前可用的模式有:
圖案 | 描述 |
---|---|
FIXED_DELAY|Ns | 與.fixedDelay(Duration) 相同,持續時間設定為 N 秒。 |
DAILY|12:30,15:30...(|time_zone) | 與.daily(LocalTime) 相同,具有可選時區(例如歐洲/羅馬、UTC) |
- | 殘障時間表 |
有關時區格式的更多詳細信息,請參閱此處。
可以將Schedule
標記為停用。調度程序不會為停用計劃的任務安排初始執行,並且會刪除該任務的任何現有執行。
任務實例可能在欄位task_data
中有一些關聯的資料。調度程序使用Serializer
來讀取此資料並將其寫入資料庫。預設情況下,使用標準 Java 序列化,但提供了許多選項:
GsonSerializer
JacksonSerializer
對於 Java 序列化,建議指定一個serialVersionUID
以便能夠發展表示資料的類別。如果未指定,且類別發生更改,反序列化可能會失敗並出現InvalidClassException
。如果發生這種情況,請明確尋找並設定目前自動產生的serialVersionUID
。然後就可以對類別進行不間斷的更改。
如果您需要從 Java 序列化遷移到GsonSerializer
,請將調度程式配置為使用SerializerWithFallbackDeserializers
:
. serializer ( new SerializerWithFallbackDeserializers ( new GsonSerializer (), new JavaSerializer ()))
對於 Spring Boot 應用程序,有一個啟動器db-scheduler-spring-boot-starter
使調度程序接線非常簡單。 (請參閱完整的範例項目)。
DataSource
。 (在範例中使用 HSQLDB 並自動套用架構。)< dependency >
< groupId >com.github.kagkarlsson</ groupId >
< artifactId >db-scheduler-spring-boot-starter</ artifactId >
< version >15.0.0</ version >
</ dependency >
Task
公開為 Spring beans。如果它們重複出現,它們將自動被拾取並啟動。Scheduler
狀態公開到執行器運作狀況資訊中,則需要啟用db-scheduler
運作狀況指示器。春季健康資訊。配置主要透過application.properties
完成。調度程序名稱、序列化程序和執行程序服務的配置是透過將DbSchedulerCustomizer
類型的 bean 新增到 Spring 上下文來完成的。
# application.properties example showing default values
db-scheduler.enabled=true
db-scheduler.heartbeat-interval=5m
db-scheduler.polling-interval=10s
db-scheduler.polling-limit=
db-scheduler.table-name=scheduled_tasks
db-scheduler.immediate-execution-enabled=false
db-scheduler.scheduler-name=
db-scheduler.threads=10
db-scheduler.priority-enabled=false
# Ignored if a custom DbSchedulerStarter bean is defined
db-scheduler.delay-startup-until-context-ready=false
db-scheduler.polling-strategy=fetch
db-scheduler.polling-strategy-lower-limit-fraction-of-threads=0.5
db-scheduler.polling-strategy-upper-limit-fraction-of-threads=3.0
db-scheduler.shutdown-max-wait=30m
可以使用Scheduler
與持久的未來執行進行互動。對於不需要完整Scheduler
實例的情況,可以使用其建構器建立更簡單的 SchedulerClient:
SchedulerClient . Builder . create ( dataSource , taskDefinitions ). build ()
它將允許執行以下操作:
單一資料庫表用於追蹤未來的任務執行。當任務執行到期時,db-scheduler 會選擇它並執行它。執行完成後,將諮詢Task
以了解應該做什麼。例如, RecurringTask
通常會根據其Schedule
在未來重新安排。
調度程序使用樂觀鎖定或選擇更新(取決於輪詢策略)來確保只有一個調度程序實例可以選擇並執行任務執行。
術語「重複任務」用於應根據某個計劃定期運行的任務。
當重複性任務的執行完成時,將參考Schedule
來確定下一次執行的時間,並為該時間建立未來的任務執行(即重新安排)。選擇的時間將是根據Schedule
最近的時間,但仍然是將來的時間。
有兩種類型的重複任務,常規靜態重複任務,其中Schedule
在程式碼中靜態定義,以及動態重複任務,其中Schedule
在運行時定義並保存在資料庫中(仍然只需要一個表) 。
靜態重複任務是最常見的任務,適用於常規後台作業,因為如果任務實例不存在,調度程序會自動調度該實例,並且如果更新Schedule
,也會更新下一個執行時間。
為了建立靜態重複任務的初始執行,調度程序有一個方法startTasks(...)
,該方法會取得一個任務列表,如果這些任務還沒有現有的執行,則應「啟動」這些任務。初始執行時間由Schedule
決定。如果任務已經有未來的執行(即之前至少啟動過一次),但更新的Schedule
現在指示另一個執行時間,則現有的執行將被重新安排到新的執行時間(非確定性任務除外)諸如FixedDelay
之類的調度,其中新的執行時間在更遠的將來)。
使用Tasks.recurring(..)
建立。
動態重複任務是後來添加到 db-scheduler 中的,添加它是為了支援需要具有不同調度的相同類型任務(即相同實現)的多個實例的用例。 Schedule
與任何常規資料一起保存在task_data
中。與靜態重複任務不同,動態任務不會自動排程任務實例。使用者可以根據需要建立實例並更新現有實例的計劃(使用SchedulerClient
介面)。有關更多詳細信息,請參閱範例 RecurringTaskWithPersistentScheduleMain.java。
使用Tasks.recurringWithPersistentSchedule(..)
建立。
術語“一次性任務”用於具有單一執行時間的任務。除了將資料編碼到任務執行的instanceId
中之外,還可以將任意二進位資料儲存在單獨的欄位中以供執行時使用。預設情況下,Java 序列化用於封送/解封資料。
使用Tasks.oneTime(..)
建立。
對於不符合上述類別的任務,可以使用Tasks.custom(..)
完全自訂任務的行為。
用例可能是:
在執行期間,調度程序會定期更新任務執行的心跳時間。如果一個執行被標記為正在執行,但沒有接收到心跳時間的更新,則在時間 X 之後它將被視為死執行。
當發現死執行時,將諮詢Task
以了解應該做什麼。失效的RecurringTask
通常會重新排程到now()
。
雖然 db-scheduler 最初是針對中低吞吐量用例,但它可以很好地處理高吞吐量用例(1000+ 執行/秒),因為它的資料模型非常簡單,包括單一執行表。要了解它將如何執行,考慮它在每批執行中運行的 SQL 語句很有用。
原始的預設輪詢策略fetch-and-lock-on-execute
將執行以下操作:
select
一批到期執行update
為picked=true
。可能會由於調度程序競爭而錯過。update
或delete
記錄。每批總計:1 次選擇,2 * 批次大小更新(不包括未命中)
在 v10 中,新增了新的輪詢策略( lock-and-fetch
)。它利用了這樣一個事實:大多數資料庫現在都支援SELECT FOR UPDATE
語句中的SKIP LOCKED
(請參閱第二象限部落格)。使用這樣的策略,可以取得預先鎖定的執行,從而減少一條語句:
select for update .. skip locked
一批到期執行。這些將已經由調度程序實例選擇。update
或delete
記錄。每批總計:1 次選擇和更新,1 * 批次大小更新(無遺漏)
若要了解 db-scheduler 的預期結果,請參閱下方在 GCP 中執行的測試的結果。測試使用了幾種不同的配置來運行,但每個配置都使用在不同虛擬機器上運行的 4 個競爭調度程序實例。 TPS 是大約。 GCP 中顯示的每秒交易數。
吞吐量取得(ex/s) | TPS 取得(估計) | 鎖定和取得吞吐量(ex/s) | TPS 鎖定和獲取(估計) | |
---|---|---|---|---|
Postgres 4 核 25GB 內存,4xVM(2 核) | ||||
20 個螺紋,下部 4.0,上部 20.0 | 2000年 | 9000 | 10600 | 11500 |
100個線程,下2.0,上6.0 | 2560 | 11000 | 11200 | 11200 |
Postgres 8 核 50GB 內存,4xVM(4 核) | ||||
50 個螺紋,下部:0.5,上部:4.0 | 4000 | 22000 | 11840 | 10300 |
這些測試的觀察:
fetch-and-lock-on-execute
lock-and-fetch
目前,輪詢策略lock-and-fetch
僅針對Postgres實作。歡迎貢獻更多資料庫支援。
有許多用戶正在使用 db-scheduler 來實現高吞吐量用例。請參閱範例:
不保證RecurringTask
計劃中的所有時刻都會被執行。上一次任務執行完成後,會查閱Schedule
,並選擇未來最接近的時間作為下一次執行的時間。將來可能會添加新類型的任務來提供此類功能。
SchedulerClient
上的方法( schedule
、 cancel
、 reschedule
)將使用提供的DataSource
中的新Connection
運行。要讓操作成為交易的一部分,必須由提供的DataSource
處理它,例如使用 Spring 的TransactionAwareDataSourceProxy
之類的東西。
目前,db-scheduler 的精確度取決於pollingInterval
(預設 10 秒),它指定在表中尋找到期執行的頻率。如果您知道自己在做什麼,則可能會在運行時透過scheduler.triggerCheckForDueExecutions()
指示排程器「儘早查看」。 (另請參閱Builder
上的enableImmediateExecution()
)
請參閱發行版以取得發行說明。
升級到 15.x
priority
和索引priority_execution_time_idx
必須加入到資料庫模式中。請參閱 postgresql、oracle 或 mysql 的表定義。在某些時候,此欄將成為必填欄。這將在未來的版本/升級說明中明確說明。升級到 8.x
boolean isDeterministic()
方法來指示它們是否總是產生相同的時刻。升級到 4.x
consecutive_failures
加入到資料庫架構中。請參閱 postgresql、oracle 或 mysql 的表定義。 null
被視為 0,因此無需更新現有記錄。升級到 3.x
Tasks
類別中的建構器完成升級到 2.x
task_data
加入到資料庫架構中。請參閱 postgresql、oracle 或 mysql 的表定義。 先決條件
請依照下列步驟操作:
克隆存儲庫。
git clone https://github.com/kagkarlsson/db-scheduler
cd db-scheduler
使用 Maven 建置(透過新增-DskipTests=true
跳過測試)
mvn package
推薦規格
有些使用者在單核心虛擬機器上運作時遇到間歇性測試失敗的情況。因此,建議至少使用:
Quartz
為什麼還要db-scheduler
呢? db-scheduler
的目標是非侵入性且易於使用,但仍解決持久性問題和群集協調問題。它最初是針對具有適度資料庫模式的應用程序,添加 11 個表會讓人感覺有點大材小用。
吻。這是最常見的共享狀態應用程式類型。
請建立一個有關功能請求的問題,我們可以在那裡進行討論。如果您不耐煩(或想貢獻),歡迎拉取請求:)
是的。目前已在多家企業生產使用,運作順利。