You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2020/07/09 16:55:04 UTC

[shardingsphere-elasticjob-lite] branch master updated: Merge ElasticJob Lite and ElasticJob Cloud to one repo (#1012)

This is an automated email from the ASF dual-hosted git repository.

zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob-lite.git


The following commit(s) were added to refs/heads/master by this push:
     new bf6aff6  Merge ElasticJob Lite and ElasticJob Cloud to one repo (#1012)
bf6aff6 is described below

commit bf6aff67e2901b0ce6f46ddf1aab29e2f77678ce
Author: Liang Zhang <te...@163.com>
AuthorDate: Fri Jul 10 00:54:52 2020 +0800

    Merge ElasticJob Lite and ElasticJob Cloud to one repo (#1012)
    
    * Move elastic-job-cloud and elastic-job-lite to same repo
    
    * Rename shardingsphere-elastic-job-lite to shardingsphere-elastic-job
    
    * Update example pom
    
    * Rename elastic-job to elasticjob
    
    * Add elasticjob-lite module
    
    * Add elasticjob-cloud module
    
    * Rename elastic-job-example to elasticjob-example
    
    * Rename elastic-job-lite to elasticjob-lite
    
    * Rename elastic-job-cloud to elasticjob-cloud
---
 README.md                                          |    4 +-
 README_ZH.md                                       |    6 +-
 docs/content/quick-start/_index.cn.md              |    4 +-
 docs/content/user-manual/deploy-guide.cn.md        |    4 +-
 docs/content/user-manual/job-config.cn.md          |    4 +-
 docs/content/user-manual/web-console.cn.md         |    4 +-
 elastic-job-lite-console/.dockerignore             |   18 -
 elastic-job-lite-console/Dockerfile                |   23 -
 elastic-job-lite-console/README.md                 |    7 -
 elastic-job-lite-console/pom.xml                   |  147 -
 .../src/main/resources/bin/start.sh                |   51 -
 .../src/main/resources/logback.xml                 |   75 -
 elastic-job-lite-core/pom.xml                      |  106 -
 .../src/test/resources/logback-test.xml            |   42 -
 .../elastic-job-lite-dataflow-executor/pom.xml     |   48 -
 .../elastic-job-lite-script-executor/pom.xml       |   48 -
 .../elastic-job-lite-simple-executor/pom.xml       |   48 -
 elastic-job-lite-executor/pom.xml                  |   37 -
 elastic-job-lite-lifecycle/pom.xml                 |  105 -
 .../src/test/resources/logback-test.xml            |   38 -
 elastic-job-lite-spring/pom.xml                    |  114 -
 .../src/test/resources/conf/job/conf.properties    |   39 -
 .../elastic-job-lite-tracing-api/pom.xml           |   79 -
 .../src/test/resources/logback-test.xml            |   41 -
 .../elastic-job-lite-tracing-rdb/pom.xml           |   80 -
 .../src/test/resources/logback-test.xml            |   38 -
 elastic-job-lite-tracing/pom.xml                   |   36 -
 elasticjob-cloud/elasticjob-cloud-common/pom.xml   |  119 +
 .../elasticjob/cloud/api/ElasticJob.java           |   24 +
 .../elasticjob/cloud/api/JobType.java              |   26 +
 .../elasticjob/cloud/api/ShardingContext.java      |   72 +
 .../elasticjob/cloud/api/dataflow/DataflowJob.java |   47 +
 .../elasticjob/cloud/api/script/ScriptJob.java     |   26 +
 .../elasticjob/cloud/api/simple/SimpleJob.java     |   34 +
 .../cloud/config/JobCoreConfiguration.java         |  189 +
 .../cloud/config/JobRootConfiguration.java         |   31 +
 .../cloud/config/JobTypeConfiguration.java         |   47 +
 .../config/dataflow/DataflowJobConfiguration.java  |   40 +
 .../config/script/ScriptJobConfiguration.java      |   41 +
 .../config/simple/SimpleJobConfiguration.java      |   38 +
 .../elasticjob/cloud/context/ExecutionType.java    |   34 +
 .../elasticjob/cloud/context/TaskContext.java      |  163 +
 .../elasticjob/cloud/event/JobEvent.java           |   31 +
 .../elasticjob/cloud/event/JobEventBus.java        |   71 +
 .../cloud/event/JobEventConfiguration.java         |   32 +
 .../elasticjob/cloud/event/JobEventIdentity.java   |   31 +
 .../elasticjob/cloud/event/JobEventListener.java   |   47 +
 .../JobEventListenerConfigurationException.java    |   30 +
 .../elasticjob/cloud/event/rdb/DatabaseType.java   |   58 +
 .../cloud/event/rdb/JobEventRdbConfiguration.java  |   49 +
 .../cloud/event/rdb/JobEventRdbIdentity.java       |   31 +
 .../cloud/event/rdb/JobEventRdbListener.java       |   47 +
 .../cloud/event/rdb/JobEventRdbSearch.java         |  300 +
 .../cloud/event/rdb/JobEventRdbStorage.java        |  364 ++
 .../cloud/event/type/JobExecutionEvent.java        |  104 +
 .../event/type/JobExecutionEventThrowable.java     |   37 +
 .../cloud/event/type/JobStatusTraceEvent.java      |   68 +
 .../cloud/exception/AppConfigurationException.java |   34 +
 .../elasticjob/cloud/exception/ExceptionUtil.java  |   48 +
 .../cloud/exception/JobConfigurationException.java |   34 +
 .../JobExecutionEnvironmentException.java          |   30 +
 .../cloud/exception/JobStatisticException.java     |   30 +
 .../cloud/exception/JobSystemException.java        |   34 +
 .../cloud/executor/AbstractElasticJobExecutor.java |  221 +
 .../cloud/executor/JobExecutorFactory.java         |   56 +
 .../elasticjob/cloud/executor/JobFacade.java       |  144 +
 .../cloud/executor/ShardingContexts.java           |   90 +
 .../executor/handler/ExecutorServiceHandler.java   |   35 +
 .../handler/ExecutorServiceHandlerRegistry.java    |   57 +
 .../executor/handler/JobExceptionHandler.java      |   32 +
 .../cloud/executor/handler/JobProperties.java      |  116 +
 .../impl/DefaultExecutorServiceHandler.java        |   34 +
 .../handler/impl/DefaultJobExceptionHandler.java   |   33 +
 .../cloud/executor/type/DataflowJobExecutor.java   |   75 +
 .../cloud/executor/type/ScriptJobExecutor.java     |   59 +
 .../cloud/executor/type/SimpleJobExecutor.java     |   41 +
 .../cloud/reg/base/CoordinatorRegistryCenter.java  |   96 +
 .../cloud/reg/base/ElectionCandidate.java          |   42 +
 .../elasticjob/cloud/reg/base/RegistryCenter.java  |   88 +
 .../cloud/reg/exception/RegException.java          |   34 +
 .../cloud/reg/exception/RegExceptionHandler.java   |   55 +
 .../reg/zookeeper/ZookeeperConfiguration.java      |   77 +
 .../reg/zookeeper/ZookeeperElectionService.java    |   81 +
 .../reg/zookeeper/ZookeeperRegistryCenter.java     |  331 +
 .../cloud/statistics/StatisticInterval.java        |   37 +
 .../statistics/rdb/StatisticRdbRepository.java     |  495 ++
 .../type/job/JobExecutionTypeStatistics.java       |   33 +
 .../statistics/type/job/JobRegisterStatistics.java |   41 +
 .../statistics/type/job/JobRunningStatistics.java  |   41 +
 .../statistics/type/job/JobTypeStatistics.java     |   35 +
 .../statistics/type/task/TaskResultStatistics.java |   46 +
 .../type/task/TaskRunningStatistics.java           |   41 +
 .../cloud/util/concurrent/BlockUtils.java          |   44 +
 .../util/concurrent/ExecutorServiceObject.java     |   81 +
 .../cloud/util/config/ShardingItemParameters.java  |   80 +
 .../cloud/util/config/ShardingItems.java           |   66 +
 .../elasticjob/cloud/util/digest/Encryption.java   |   51 +
 .../elasticjob/cloud/util/env/HostException.java   |   32 +
 .../elasticjob/cloud/util/env/IpUtils.java         |   98 +
 .../elasticjob/cloud/util/env/TimeService.java     |   33 +
 .../AbstractJobConfigurationGsonTypeAdapter.java   |  193 +
 .../elasticjob/cloud/util/json/GsonFactory.java    |   57 +
 .../elasticjob/cloud/AllCoreTests.java             |   49 +
 .../elasticjob/cloud/api/AllApiTests.java          |   27 +
 .../elasticjob/cloud/api/ShardingContextTest.java  |   45 +
 .../elasticjob/cloud/config/AllConfigTests.java    |   27 +
 .../cloud/config/JobCoreConfigurationTest.java     |   87 +
 .../elasticjob/cloud/context/AllContextTests.java  |   26 +
 .../elasticjob/cloud/context/TaskContextTest.java  |  121 +
 .../elasticjob/cloud/event/AllEventTests.java      |   39 +
 .../elasticjob/cloud/event/JobEventBusTest.java    |   76 +
 .../cloud/event/JobExecutionEventTest.java         |   57 +
 .../cloud/event/fixture/JobEventCaller.java        |   26 +
 .../event/fixture/TestJobEventConfiguration.java   |   34 +
 .../fixture/TestJobEventFailureConfiguration.java  |   30 +
 .../cloud/event/fixture/TestJobEventIdentity.java  |   28 +
 .../cloud/event/fixture/TestJobEventListener.java  |   51 +
 .../event/rdb/JobEventRdbConfigurationTest.java    |   53 +
 .../cloud/event/rdb/JobEventRdbIdentityTest.java   |   30 +
 .../cloud/event/rdb/JobEventRdbListenerTest.java   |   79 +
 .../cloud/event/rdb/JobEventRdbSearchTest.java     |  241 +
 .../cloud/event/rdb/JobEventRdbStorageTest.java    |  136 +
 .../cloud/exception/AllExceptionTests.java         |   33 +
 .../cloud/exception/ExceptionUtilTest.java         |   40 +
 .../exception/JobConfigurationExceptionTest.java   |   36 +
 .../JobExecutionEnvironmentExceptionTest.java      |   30 +
 .../cloud/exception/JobStatisticExceptionTest.java |   32 +
 .../cloud/exception/JobSystemExceptionTest.java    |   36 +
 .../cloud/executor/AllExecutorTests.java           |   43 +
 .../cloud/executor/JobExecutorFactoryTest.java     |   75 +
 .../ExecutorServiceHandlerRegistryTest.java        |   91 +
 .../cloud/executor/handler/JobPropertiesTest.java  |   86 +
 .../impl/DefaultJobExceptionHandlerTest.java       |   40 +
 .../executor/type/DataflowJobExecutorTest.java     |  176 +
 .../cloud/executor/type/ElasticJobVerify.java      |   54 +
 .../cloud/executor/type/ScriptJobExecutorTest.java |   87 +
 .../cloud/executor/type/SimpleJobExecutorTest.java |  232 +
 .../cloud/executor/type/WrongJobExecutorTest.java  |   71 +
 .../elasticjob/cloud/fixture/APIJsonConstants.java |   78 +
 .../cloud/fixture/EmbedTestingServer.java          |   72 +
 .../cloud/fixture/ShardingContextsBuilder.java     |   52 +
 .../config/TestDataflowJobConfiguration.java       |   41 +
 .../fixture/config/TestJobRootConfiguration.java   |   33 +
 .../fixture/config/TestScriptJobConfiguration.java |   41 +
 .../fixture/config/TestSimpleJobConfiguration.java |   56 +
 .../elasticjob/cloud/fixture/context/TaskNode.java |   52 +
 .../fixture/handler/IgnoreJobExceptionHandler.java |   27 +
 .../fixture/handler/ThrowJobExceptionHandler.java  |   29 +
 .../elasticjob/cloud/fixture/job/JobCaller.java    |   41 +
 .../elasticjob/cloud/fixture/job/OtherJob.java     |   23 +
 .../cloud/fixture/job/TestDataflowJob.java         |   42 +
 .../cloud/fixture/job/TestSimpleJob.java           |   33 +
 .../elasticjob/cloud/fixture/job/TestWrongJob.java |   31 +
 .../elasticjob/cloud/reg/AllRegTests.java          |   49 +
 .../reg/exception/RegExceptionHandlerTest.java     |   74 +
 .../reg/zookeeper/ZookeeperConfigurationTest.java  |   35 +
 .../zookeeper/ZookeeperElectionServiceTest.java    |   69 +
 .../ZookeeperRegistryCenterForAuthTest.java        |   75 +
 .../ZookeeperRegistryCenterInitFailureTest.java    |   30 +
 .../ZookeeperRegistryCenterMiscellaneousTest.java  |   68 +
 .../ZookeeperRegistryCenterModifyTest.java         |  126 +
 .../ZookeeperRegistryCenterQueryWithCacheTest.java |   62 +
 ...okeeperRegistryCenterQueryWithoutCacheTest.java |   94 +
 .../util/ZookeeperRegistryCenterTestUtil.java      |   36 +
 .../cloud/statistics/AllStatisticsTests.java       |   31 +
 .../statistics/rdb/StatisticRdbRepositoryTest.java |  216 +
 .../elasticjob/cloud/util/AllUtilTests.java        |   49 +
 .../util/concurrent/ExecutorServiceObjectTest.java |   58 +
 .../util/config/ShardingItemParametersTest.java    |   55 +
 .../cloud/util/config/ShardingItemsTest.java       |   59 +
 .../cloud/util/digest/EncryptionTest.java          |   30 +
 .../cloud/util/env/HostExceptionTest.java          |   34 +
 .../elasticjob/cloud/util/env/IpUtilsTest.java     |   35 +
 .../elasticjob/cloud/util/env/TimeServiceTest.java |   31 +
 .../cloud/util/json/GsonFactoryTest.java           |   56 +
 .../json/JobConfigurationGsonTypeAdapterTest.java  |  105 +
 .../src/test/resources/conf/reg}/local.properties  |    0
 .../resources/conf/reg}/local_overwrite.properties |    0
 .../src/test/resources/logback-test.xml            |   43 +
 elasticjob-cloud/elasticjob-cloud-executor/pom.xml |   97 +
 .../elasticjob/cloud/api/JobBootstrap.java         |   39 +
 .../elasticjob/cloud/executor/CloudJobFacade.java  |  115 +
 .../cloud/executor/DaemonTaskScheduler.java        |  171 +
 .../cloud/executor/JobConfigurationContext.java    |   85 +
 .../elasticjob/cloud/executor/TaskExecutor.java    |  177 +
 .../executor/local/LocalCloudJobConfiguration.java |   50 +
 .../cloud/executor/local/LocalTaskExecutor.java    |  114 +
 .../cloud/executor/AllCloudExecutorTests.java      |   38 +
 .../cloud/executor/CloudJobFacadeTest.java         |  160 +
 .../cloud/executor/DaemonTaskSchedulerTest.java    |   93 +
 .../executor/JobConfigurationContextTest.java      |   79 +
 .../cloud/executor/TaskExecutorTest.java           |  121 +
 .../cloud/executor/TaskExecutorThreadTest.java     |  158 +
 .../elasticjob/cloud/executor/fixture/TestJob.java |   28 +
 .../fixture/TestScriptJobConfiguration.java        |   37 +
 .../executor/local/AllLocalExecutorTests.java      |   29 +
 .../executor/local/LocalTaskExecutorTest.java      |  103 +
 .../executor/local/fixture/TestDataflowJob.java    |   52 +
 .../executor/local/fixture/TestSimpleJob.java      |   45 +
 .../src/test/resources/applicationContext.xml      |   27 +
 .../src/test/resources/logback-test.xml            |   40 +
 .../src/test/resources/script/TestScriptJob.bat    |   18 +
 .../src/test/resources/script/TestScriptJob.sh     |   19 +
 .../elasticjob-cloud-scheduler/pom.xml             |  154 +
 .../elasticjob/cloud/restful/GsonJsonProvider.java |   82 +
 .../elasticjob/cloud/restful/RestfulException.java |   30 +
 .../cloud/restful/RestfulExceptionMapper.java      |   37 +
 .../elasticjob/cloud/restful/RestfulServer.java    |  126 +
 .../elasticjob/cloud/scheduler/Bootstrap.java      |   65 +
 .../config/app/CloudAppConfiguration.java          |   47 +
 .../app/CloudAppConfigurationGsonFactory.java      |  120 +
 .../config/app/CloudAppConfigurationNode.java      |   36 +
 .../config/app/CloudAppConfigurationService.java   |   93 +
 .../constants/CloudConfigurationConstants.java     |   46 +
 .../config/job/CloudJobConfiguration.java          |   56 +
 .../job/CloudJobConfigurationGsonFactory.java      |  119 +
 .../config/job/CloudJobConfigurationListener.java  |  114 +
 .../config/job/CloudJobConfigurationNode.java      |   36 +
 .../config/job/CloudJobConfigurationService.java   |   93 +
 .../config/job/CloudJobExecutionType.java          |   26 +
 .../cloud/scheduler/context/JobContext.java        |   56 +
 .../cloud/scheduler/env/BootstrapEnvironment.java  |  224 +
 .../scheduler/env/FrameworkConfiguration.java      |   42 +
 .../cloud/scheduler/env/MesosConfiguration.java    |   45 +
 .../scheduler/env/RestfulServerConfiguration.java  |   31 +
 .../cloud/scheduler/ha/FrameworkIDService.java     |   53 +
 .../elasticjob/cloud/scheduler/ha/HANode.java      |   39 +
 .../scheduler/ha/SchedulerElectionCandidate.java   |   53 +
 .../scheduler/mesos/AppConstraintEvaluator.java    |  163 +
 .../cloud/scheduler/mesos/FacadeService.java       |  344 +
 .../cloud/scheduler/mesos/JobTaskRequest.java      |  104 +
 .../cloud/scheduler/mesos/LaunchingTasks.java      |   94 +
 .../cloud/scheduler/mesos/LeasesQueue.java         |   69 +
 .../cloud/scheduler/mesos/MesosStateService.java   |  177 +
 .../cloud/scheduler/mesos/ReconcileService.java    |  106 +
 .../cloud/scheduler/mesos/SchedulerEngine.java     |  166 +
 .../cloud/scheduler/mesos/SchedulerService.java    |  154 +
 .../scheduler/mesos/SupportedExtractionType.java   |   59 +
 .../cloud/scheduler/mesos/TaskInfoData.java        |   71 +
 .../mesos/TaskLaunchScheduledService.java          |  269 +
 .../cloud/scheduler/producer/ProducerManager.java  |  198 +
 .../producer/TransientProducerRepository.java      |   72 +
 .../producer/TransientProducerScheduler.java       |  155 +
 .../scheduler/restful/CloudAppRestfulApi.java      |  228 +
 .../scheduler/restful/CloudJobRestfulApi.java      |  478 ++
 .../restful/CloudOperationRestfulApi.java          |  100 +
 .../cloud/scheduler/restful/RestfulService.java    |   65 +
 .../cloud/scheduler/state/StateNode.java           |   33 +
 .../state/disable/app/DisableAppNode.java          |   37 +
 .../state/disable/app/DisableAppService.java       |   72 +
 .../state/disable/job/DisableJobNode.java          |   37 +
 .../state/disable/job/DisableJobService.java       |   72 +
 .../scheduler/state/failover/FailoverNode.java     |   44 +
 .../scheduler/state/failover/FailoverService.java  |  186 +
 .../scheduler/state/failover/FailoverTaskInfo.java |   34 +
 .../cloud/scheduler/state/ready/ReadyNode.java     |   37 +
 .../cloud/scheduler/state/ready/ReadyService.java  |  185 +
 .../cloud/scheduler/state/running/RunningNode.java |   44 +
 .../scheduler/state/running/RunningService.java    |  267 +
 .../scheduler/statistics/StatisticManager.java     |  291 +
 .../scheduler/statistics/StatisticsScheduler.java  |   98 +
 .../scheduler/statistics/TaskResultMetaData.java   |   79 +
 .../statistics/job/AbstractStatisticJob.java       |   52 +
 .../statistics/job/JobRunningStatisticJob.java     |  150 +
 .../statistics/job/RegisteredJobStatisticJob.java  |  100 +
 .../scheduler/statistics/job/StatisticJob.java     |   51 +
 .../statistics/job/TaskResultStatisticJob.java     |  106 +
 .../statistics/util/StatisticTimeUtils.java        |   72 +
 .../elasticjob/cloud/security/WwwAuthFilter.java   |  124 +
 .../src/main/resources/assembly/assembly.xml       |   44 +
 .../src/main/resources/bin/dcos.sh                 |   27 +
 .../src/main/resources/bin/start.sh                |   35 +
 .../src/main/resources/conf/auth.properties        |   21 +
 .../conf/elastic-job-cloud-scheduler.properties    |   62 +
 .../src/main/resources/console/css/common.css      |  161 +
 .../src/main/resources/console/favicon.ico         |  Bin 0 -> 1150 bytes
 .../main/resources/console/html/app/add_app.html   |   98 +
 .../resources/console/html/app/apps_overview.html  |   99 +
 .../resources/console/html/app/detail_app.html     |   89 +
 .../resources/console/html/app/modify_app.html     |   98 +
 .../console/html/history/job_dashboard.html        |  134 +
 .../console/html/history/job_exec_details.html     |  101 +
 .../console/html/history/job_exec_status.html      |  122 +
 .../main/resources/console/html/job/add_job.html   |  191 +
 .../resources/console/html/job/detail_job.html     |  183 +
 .../resources/console/html/job/job_status.html     |  117 +
 .../resources/console/html/job/jobs_overview.html  |  127 +
 .../resources/console/html/job/modify_job.html     |  191 +
 .../main/resources/console/i18n/message.properties |   16 +
 .../resources/console/i18n/message_en.properties   |  190 +
 .../resources/console/i18n/message_zh.properties   |  190 +
 .../src/main/resources/console/index.html          |  301 +
 .../src/main/resources/console/js/app/add_app.js   |   21 +
 .../main/resources/console/js/app/app_common.js    |  132 +
 .../main/resources/console/js/app/apps_overview.js |  178 +
 .../main/resources/console/js/app/modify_app.js    |   21 +
 .../src/main/resources/console/js/common/common.js |  161 +
 .../resources/console/js/history/history_common.js |   59 +
 .../resources/console/js/history/job_dashboard.js  |  291 +
 .../console/js/history/job_exec_details.js         |   68 +
 .../console/js/history/job_exec_status.js          |   82 +
 .../src/main/resources/console/js/index.js         |   45 +
 .../src/main/resources/console/js/job/add_job.js   |   22 +
 .../main/resources/console/js/job/job_common.js    |  257 +
 .../main/resources/console/js/job/jobs_overview.js |  230 +
 .../main/resources/console/js/job/modify_job.js    |   22 +
 .../console/lib/AdminLTE/css/AdminLTE.min.css      |    0
 .../lib/AdminLTE/css/skins/_all-skins.min.css      |    0
 .../resources/console/lib/AdminLTE/js/app.min.js   |    0
 .../BootstrapValidator/js/bootstrapValidator.js    |    0
 .../js/bootstrapValidator_zh_CN.js                 |  386 ++
 .../lib/bootstrap-table/bootstrap-table-zh-CN.js   |   44 +
 .../lib/bootstrap-table/bootstrap-table.css        |  302 +
 .../console/lib/bootstrap-table/bootstrap-table.js | 2801 ++++++++
 .../lib/bootstrap-table/bootstrap-table.min.css    |    1 +
 .../lib/bootstrap-table/bootstrap-table.min.js     |    8 +
 .../console/lib/bootstrap/css/bootstrap.css        | 6800 ++++++++++++++++++++
 .../console/lib/bootstrap/css/bootstrap.css.map    |    1 +
 .../console/lib/bootstrap/css/bootstrap.min.css    |    0
 .../fonts/glyphicons-halflings-regular.eot         |  Bin
 .../fonts/glyphicons-halflings-regular.svg         |    0
 .../fonts/glyphicons-halflings-regular.ttf         |  Bin
 .../fonts/glyphicons-halflings-regular.woff        |  Bin
 .../fonts/glyphicons-halflings-regular.woff2       |  Bin
 .../console/lib/bootstrap/js/bootstrap.js          | 2317 +++++++
 .../console/lib/bootstrap/js/bootstrap.min.js      |    7 +
 .../main/resources/console/lib/bootstrap/js/npm.js |   13 +
 .../lib/daterangepicker/daterangepicker.css        |  269 +
 .../console/lib/daterangepicker/daterangepicker.js | 1622 +++++
 .../console/lib/daterangepicker/moment.js          | 4040 ++++++++++++
 .../console/lib/daterangepicker/moment.min.js      |    0
 .../lib/font-awesome-4.5.0/css/font-awesome.css    | 2086 ++++++
 .../font-awesome-4.5.0/css/font-awesome.min.css    |    0
 .../lib/font-awesome-4.5.0/fonts/FontAwesome.otf   |  Bin
 .../fonts/fontawesome-webfont.eot                  |  Bin
 .../fonts/fontawesome-webfont.svg                  |    0
 .../fonts/fontawesome-webfont.ttf                  |  Bin
 .../fonts/fontawesome-webfont.woff                 |  Bin
 .../fonts/fontawesome-webfont.woff2                |  Bin
 .../console/lib/highcharts/js/highcharts.js        |  383 ++
 .../input-mask/jquery.inputmask.date.extensions.js |  488 ++
 .../lib/input-mask/jquery.inputmask.extensions.js  |  122 +
 .../console/lib/input-mask/jquery.inputmask.js     | 1627 +++++
 .../jquery.inputmask.numeric.extensions.js         |  177 +
 .../jquery.inputmask.phone.extensions.js           |   50 +
 .../jquery.inputmask.regex.extensions.js           |  169 +
 .../lib/input-mask/phone-codes/phone-be.json       |    0
 .../lib/input-mask/phone-codes/phone-codes.json    |    0
 .../console/lib/input-mask/phone-codes/readme.txt  |    0
 .../console/lib/jQuery/jQuery-2.1.4.min.js         |    0
 .../lib/jQuery}/jquery.i18n.properties-min.js      |    0
 .../src/main/resources/logback.xml                 |   75 +
 .../shardingsphere/elasticjob/cloud/AllTests.java  |   35 +
 .../elasticjob/cloud/restful/AllRestfulTests.java  |   33 +
 .../cloud/restful/RestfulExceptionTest.java        |   30 +
 .../cloud/restful/RestfulServerTest.java           |  101 +
 .../elasticjob/cloud/restful/fixture/Caller.java   |   33 +
 .../cloud/restful/fixture/TestFilter.java          |   46 +
 .../cloud/restful/fixture/TestRestfulApi.java      |   54 +
 .../cloud/scheduler/AllCloudSchedulerTests.java    |   45 +
 .../cloud/scheduler/config/AllConfigTests.java     |   31 +
 .../config/app/AllCloudAppConfigTests.java         |   29 +
 .../config/app/CloudAppConfigurationNodeTest.java  |   30 +
 .../app/CloudAppConfigurationServiceTest.java      |   99 +
 .../config/job/AllCloudJobConfigTests.java         |   30 +
 .../job/CloudJobConfigurationListenerTest.java     |  123 +
 .../config/job/CloudJobConfigurationNodeTest.java  |   30 +
 .../job/CloudJobConfigurationServiceTest.java      |  115 +
 .../cloud/scheduler/context/AllContextTests.java   |   26 +
 .../cloud/scheduler/context/JobContextTest.java    |   38 +
 .../cloud/scheduler/env/AllEnvTests.java           |   26 +
 .../scheduler/env/BootstrapEnvironmentTest.java    |  114 +
 .../fixture/CloudAppConfigurationBuilder.java      |   35 +
 .../scheduler/fixture/CloudAppJsonConstants.java   |   37 +
 .../fixture/CloudJobConfigurationBuilder.java      |  146 +
 .../scheduler/fixture/CloudJsonConstants.java      |   85 +
 .../scheduler/fixture/EmbedTestingServer.java      |   72 +
 .../cloud/scheduler/fixture/TaskNode.java          |   61 +
 .../cloud/scheduler/fixture/TestSimpleJob.java     |   28 +
 .../elasticjob/cloud/scheduler/ha/AllHATests.java  |   26 +
 .../cloud/scheduler/ha/FrameworkIDServiceTest.java |   62 +
 .../cloud/scheduler/mesos/AllMesosTests.java       |   41 +
 .../mesos/AppConstraintEvaluatorTest.java          |  197 +
 .../cloud/scheduler/mesos/FacadeServiceTest.java   |  319 +
 .../cloud/scheduler/mesos/JobTaskRequestTest.java  |  102 +
 .../cloud/scheduler/mesos/LaunchingTasksTest.java  |   82 +
 .../cloud/scheduler/mesos/LeasesQueueTest.java     |   36 +
 .../scheduler/mesos/MesosStateServiceTest.java     |   72 +
 .../scheduler/mesos/ReconcileServiceTest.java      |   88 +
 .../cloud/scheduler/mesos/SchedulerEngineTest.java |  291 +
 .../scheduler/mesos/SchedulerServiceTest.java      |  151 +
 .../mesos/SupportedExtractionTypeTest.java         |   41 +
 .../cloud/scheduler/mesos/TaskInfoDataTest.java    |   57 +
 .../mesos/TaskLaunchScheduledServiceTest.java      |  141 +
 .../scheduler/mesos/fixture/OfferBuilder.java      |   42 +
 .../fixture/master/MesosMasterServerMock.java      |   78 +
 .../mesos/fixture/slave/MesosSlaveServerMock.java  |   92 +
 .../cloud/scheduler/producer/AllProducerTests.java |   31 +
 .../cloud/scheduler/producer/ProducerJobTest.java  |   62 +
 .../scheduler/producer/ProducerManagerTest.java    |  193 +
 .../producer/TransientProducerRepositoryTest.java  |   84 +
 .../producer/TransientProducerSchedulerTest.java   |   86 +
 .../restful/AbstractCloudRestfulApiTest.java       |   95 +
 .../cloud/scheduler/restful/AllRestfulTests.java   |   30 +
 .../scheduler/restful/CloudAppRestfulApiTest.java  |  118 +
 .../scheduler/restful/CloudJobRestfulApiTest.java  |  323 +
 .../restful/CloudOperationRestfulApiTest.java      |   57 +
 .../cloud/scheduler/restful/RestfulTestsUtil.java  |   98 +
 .../cloud/scheduler/state/AllStateTests.java       |   47 +
 .../state/disable/app/DisableAppNodeTest.java      |   30 +
 .../state/disable/app/DisableAppServiceTest.java   |   68 +
 .../state/disable/job/DisableJobNodeTest.java      |   30 +
 .../state/disable/job/DisableJobServiceTest.java   |   68 +
 .../scheduler/state/failover/FailoverNodeTest.java |   38 +
 .../state/failover/FailoverServiceTest.java        |  218 +
 .../cloud/scheduler/state/ready/ReadyNodeTest.java |   30 +
 .../scheduler/state/ready/ReadyServiceTest.java    |  286 +
 .../scheduler/state/running/RunningNodeTest.java   |   37 +
 .../state/running/RunningServiceTest.java          |  161 +
 .../scheduler/statistics/AllStatisticTests.java    |   40 +
 .../scheduler/statistics/StatisticManagerTest.java |  236 +
 .../statistics/StatisticsSchedulerTest.java        |   63 +
 .../statistics/TaskResultMetaDataTest.java         |   56 +
 .../statistics/job/BaseStatisticJobTest.java       |   59 +
 .../statistics/job/JobRunningStatisticJobTest.java |  119 +
 .../job/RegisteredJobStatisticJobTest.java         |  101 +
 .../statistics/job/TaskResultStatisticJobTest.java |  109 +
 .../scheduler/statistics/job/TestStatisticJob.java |   58 +
 .../statistics/util/StatisticTimeUtilsTest.java    |   72 +
 .../src/test/resources/logback-test.xml            |   43 +
 elasticjob-cloud/pom.xml                           |   37 +
 .../elasticjob-lite-console/.dockerignore          |   18 +
 elasticjob-lite/elasticjob-lite-console/Dockerfile |   23 +
 elasticjob-lite/elasticjob-lite-console/README.md  |    7 +
 elasticjob-lite/elasticjob-lite-console/pom.xml    |  147 +
 .../elasticjob/lite/console/ConsoleBootstrap.java  |    0
 .../console/config/DynamicDataSourceConfig.java    |    0
 .../lite/console/config/FilterRegisterConfig.java  |    0
 .../lite/console/config/WebMvcConfig.java          |    0
 .../config/advice/ConsoleRestControllerAdvice.java |    0
 .../controller/EventTraceDataSourceController.java |    0
 .../controller/EventTraceHistoryController.java    |    0
 .../console/controller/JobConfigController.java    |    0
 .../console/controller/JobOperationController.java |    0
 .../controller/RegistryCenterController.java       |    0
 .../controller/ServerOperationController.java      |    0
 .../dao/search/JobExecutionLogRepository.java      |    0
 .../dao/search/JobStatusTraceLogRepository.java    |    0
 .../JobRegisterStatisticsRepository.java           |    0
 .../statistics/JobRunningStatisticsRepository.java |    0
 .../console/dao/statistics/StatisticInterval.java  |    0
 .../statistics/TaskResultStatisticsRepository.java |    0
 .../TaskRunningStatisticsRepository.java           |    0
 .../type/job/JobExecutionTypeStatistics.java       |    0
 .../dao/statistics/type/job/JobTypeStatistics.java |    0
 .../lite/console/domain/DataSourceFactory.java     |    0
 .../lite/console/domain/EventTraceDataSource.java  |    0
 .../domain/EventTraceDataSourceConfiguration.java  |    0
 .../domain/EventTraceDataSourceConfigurations.java |    0
 .../domain/EventTraceDataSourceFactory.java        |    0
 .../lite/console/domain/GlobalConfiguration.java   |    0
 .../lite/console/domain/JobExecutionLog.java       |    0
 .../lite/console/domain/JobRegisterStatistics.java |    0
 .../lite/console/domain/JobRunningStatistics.java  |    0
 .../lite/console/domain/JobStatusTraceLog.java     |    0
 .../domain/RegistryCenterConfiguration.java        |    0
 .../domain/RegistryCenterConfigurations.java       |    0
 .../lite/console/domain/TaskResultStatistics.java  |    0
 .../lite/console/domain/TaskRunningStatistics.java |    0
 .../lite/console/dto/request/BasePageRequest.java  |    0
 .../dto/request/FindJobExecutionEventsRequest.java |    0
 .../request/FindJobStatusTraceEventsRequest.java   |    0
 .../console/dto/response/BasePageResponse.java     |    0
 .../console/exception/JobConsoleException.java     |    0
 .../console/filter/GlobalConfigurationFilter.java  |    0
 .../repository/ConfigurationsXmlRepository.java    |    0
 .../lite/console/repository/XmlRepository.java     |    0
 .../repository/impl/AbstractXmlRepositoryImpl.java |    0
 .../impl/ConfigurationsXmlRepositoryImpl.java      |    0
 .../console/security/AuthenticationResult.java     |    0
 .../security/UserAuthenticationService.java        |    0
 .../lite/console/security/WwwAuthFilter.java       |    0
 .../EventTraceDataSourceConfigurationService.java  |    0
 .../console/service/EventTraceHistoryService.java  |    0
 .../lite/console/service/JobAPIService.java        |    0
 .../RegistryCenterConfigurationService.java        |    0
 ...entTraceDataSourceConfigurationServiceImpl.java |    0
 .../service/impl/EventTraceHistoryServiceImpl.java |    0
 .../console/service/impl/JobAPIServiceImpl.java    |    0
 .../RegistryCenterConfigurationServiceImpl.java    |    0
 .../elasticjob/lite/console/util/BeanUtils.java    |    0
 .../lite/console/util/HomeFolderUtils.java         |    0
 .../SessionEventTraceDataSourceConfiguration.java  |    0
 .../util/SessionRegistryCenterConfiguration.java   |    0
 .../src/main/resources/application.properties      |    0
 .../src/main/resources/assembly/assembly.xml       |    0
 .../src/main/resources/bin/start.bat               |    0
 .../src/main/resources/bin/start.sh                |   50 +
 .../src/main/resources/console/css/index.css       |    0
 .../src/main/resources/console/favicon.ico         |  Bin
 .../html/global/event_trace_data_source.html       |    0
 .../console/html/global/registry_center.html       |    0
 .../src/main/resources/console/html/help/help.html |    0
 .../html/history/job_event_trace_history.html      |    0
 .../console/html/history/job_status_history.html   |    0
 .../console/html/status/job/job_config.html        |    0
 .../console/html/status/job/job_status_detail.html |    0
 .../html/status/job/jobs_status_overview.html      |    0
 .../html/status/server/server_status_detail.html   |    0
 .../status/server/servers_status_overview.html     |    0
 .../main/resources/console/i18n/message.properties |    0
 .../resources/console/i18n/message_en.properties   |    0
 .../resources/console/i18n/message_zh.properties   |    0
 .../src/main/resources/console/index.html          |    0
 .../console/js/global/event_trace_data_source.js   |    0
 .../resources/console/js/global/registry_center.js |    0
 .../console/js/history/job_event_trace_history.js  |    0
 .../console/js/history/job_status_history.js       |    0
 .../src/main/resources/console/js/index.js         |    0
 .../resources/console/js/status/job/job_config.js  |    0
 .../console/js/status/job/job_status_detail.js     |    0
 .../console/js/status/job/jobs_status_overview.js  |    0
 .../js/status/server/server_status_detail.js       |    0
 .../js/status/server/servers_status_overview.js    |    0
 .../src/main/resources/console/js/util/common.js   |    0
 .../main/resources/console/js/util/dashboard.js    |    0
 .../main/resources/console/js/util/formatter.js    |    0
 .../console/lib/AdminLTE/css/AdminLTE.min.css      |    0
 .../lib/AdminLTE/css/skins/_all-skins.min.css      |    0
 .../resources/console/lib/AdminLTE/js/app.min.js   |    0
 .../BootstrapValidator/js/bootstrapValidator.js    |    0
 .../js/bootstrapValidator_zh_CN.js                 |    0
 .../console/lib/bootstrap-table/bootstrap-table.js |    0
 .../lib/bootstrap-table/bootstrap-table.min.css    |    0
 .../lib/bootstrap/css/bootstrap-theme.min.css      |    0
 .../console/lib/bootstrap/css/bootstrap.min.css    |    0
 .../fonts/glyphicons-halflings-regular.eot         |  Bin
 .../fonts/glyphicons-halflings-regular.svg         |    0
 .../fonts/glyphicons-halflings-regular.ttf         |  Bin
 .../fonts/glyphicons-halflings-regular.woff        |  Bin
 .../fonts/glyphicons-halflings-regular.woff2       |  Bin
 .../console/lib/bootstrap/js/bootstrap.min.js      |    0
 .../lib/daterangepicker/daterangepicker.css        |    0
 .../console/lib/daterangepicker/daterangepicker.js |    0
 .../console/lib/daterangepicker/moment.min.js      |    0
 .../font-awesome-4.5.0/css/font-awesome.min.css    |    0
 .../lib/font-awesome-4.5.0/fonts/FontAwesome.otf   |  Bin
 .../fonts/fontawesome-webfont.eot                  |  Bin
 .../fonts/fontawesome-webfont.svg                  |    0
 .../fonts/fontawesome-webfont.ttf                  |  Bin
 .../fonts/fontawesome-webfont.woff                 |  Bin
 .../fonts/fontawesome-webfont.woff2                |  Bin
 .../input-mask/jquery.inputmask.date.extensions.js |    0
 .../lib/input-mask/jquery.inputmask.extensions.js  |    0
 .../console/lib/input-mask/jquery.inputmask.js     |    0
 .../jquery.inputmask.numeric.extensions.js         |    0
 .../jquery.inputmask.phone.extensions.js           |    0
 .../jquery.inputmask.regex.extensions.js           |    0
 .../lib/input-mask/phone-codes/phone-be.json       |    0
 .../lib/input-mask/phone-codes/phone-codes.json    |    0
 .../console/lib/input-mask/phone-codes/readme.txt  |    0
 .../console/lib/jquery/jquery-2.1.4.min.js         |    0
 .../lib/jquery/jquery.i18n.properties-min.js       |    0
 .../src/main/resources/log4j.properties            |    0
 .../src/main/resources/logback.xml                 |   75 +
 .../console/dao/search/RDBJobEventSearchTest.java  |    0
 .../search/RDBJobEventSearchTestConfiguration.java |    0
 .../statistics/rdb/RDBStatisticRepositoryTest.java |    0
 .../lite/console/util/HomeFolderUtilsTest.java     |    0
 elasticjob-lite/elasticjob-lite-core/pom.xml       |  106 +
 .../lite/api/bootstrap/JobBootstrap.java           |    0
 .../api/bootstrap/impl/OneOffJobBootstrap.java     |    0
 .../api/bootstrap/impl/ScheduleJobBootstrap.java   |    0
 .../elasticjob/lite/api/job/ElasticJob.java        |    0
 .../elasticjob/lite/api/job/JobConfiguration.java  |    0
 .../elasticjob/lite/api/job/ShardingContext.java   |    0
 .../AbstractDistributeOnceElasticJobListener.java  |    0
 .../lite/api/listener/ElasticJobListener.java      |    0
 .../elasticjob/lite/context/ExecutionType.java     |    0
 .../elasticjob/lite/context/TaskContext.java       |    0
 .../lite/exception/AppConfigurationException.java  |    0
 .../elasticjob/lite/exception/ExceptionUtils.java  |    0
 .../lite/exception/JobConfigurationException.java  |    0
 .../JobExecutionEnvironmentException.java          |    0
 .../lite/exception/JobStatisticException.java      |    0
 .../lite/exception/JobSystemException.java         |    0
 .../lite/executor/ElasticJobExecutor.java          |    0
 .../elasticjob/lite/executor/JobFacade.java        |    0
 .../elasticjob/lite/executor/ShardingContexts.java |    0
 .../lite/executor/item/JobItemExecutor.java        |    0
 .../lite/executor/item/JobItemExecutorFactory.java |    0
 .../executor/item/impl/ClassedJobItemExecutor.java |    0
 .../executor/item/impl/TypedJobItemExecutor.java   |    0
 .../lite/handler/error/JobErrorHandler.java        |    0
 .../lite/handler/error/JobErrorHandlerFactory.java |    0
 .../handler/error/impl/IgnoreJobErrorHandler.java  |    0
 .../handler/error/impl/LogJobErrorHandler.java     |    0
 .../handler/error/impl/ThrowJobErrorHandler.java   |    0
 .../lite/handler/sharding/JobInstance.java         |    0
 .../lite/handler/sharding/JobShardingStrategy.java |    0
 .../sharding/JobShardingStrategyFactory.java       |    0
 .../impl/AverageAllocationJobShardingStrategy.java |    0
 .../impl/OdevitySortByNameJobShardingStrategy.java |    0
 .../impl/RoundRobinByNameJobShardingStrategy.java  |    0
 .../threadpool/JobExecutorServiceHandler.java      |    0
 .../JobExecutorServiceHandlerFactory.java          |    0
 .../impl/AbstractJobExecutorServiceHandler.java    |    0
 .../impl/CPUUsageJobExecutorServiceHandler.java    |    0
 .../SingleThreadJobExecutorServiceHandler.java     |    0
 .../lite/internal/config/ConfigurationNode.java    |    0
 .../lite/internal/config/ConfigurationService.java |    0
 .../internal/config/RescheduleListenerManager.java |    0
 .../internal/config/yaml/YamlJobConfiguration.java |    0
 .../internal/election/ElectionListenerManager.java |    0
 .../lite/internal/election/LeaderNode.java         |    0
 .../lite/internal/election/LeaderService.java      |    0
 .../internal/failover/FailoverListenerManager.java |    0
 .../lite/internal/failover/FailoverNode.java       |    0
 .../lite/internal/failover/FailoverService.java    |    0
 .../guarantee/GuaranteeListenerManager.java        |    0
 .../lite/internal/guarantee/GuaranteeNode.java     |    0
 .../lite/internal/guarantee/GuaranteeService.java  |    0
 .../lite/internal/instance/InstanceNode.java       |    0
 .../lite/internal/instance/InstanceOperation.java  |    0
 .../lite/internal/instance/InstanceService.java    |    0
 .../internal/instance/ShutdownListenerManager.java |    0
 .../internal/instance/TriggerListenerManager.java  |    0
 .../internal/listener/AbstractJobListener.java     |    0
 .../internal/listener/AbstractListenerManager.java |    0
 .../lite/internal/listener/ListenerManager.java    |    0
 .../RegistryCenterConnectionStateListener.java     |    0
 .../lite/internal/reconcile/ReconcileService.java  |    0
 .../lite/internal/schedule/JobRegistry.java        |    0
 .../internal/schedule/JobScheduleController.java   |    0
 .../lite/internal/schedule/JobScheduler.java       |    0
 .../internal/schedule/JobShutdownHookPlugin.java   |    0
 .../lite/internal/schedule/JobTriggerListener.java |    0
 .../elasticjob/lite/internal/schedule/LiteJob.java |    0
 .../lite/internal/schedule/LiteJobFacade.java      |    0
 .../lite/internal/schedule/SchedulerFacade.java    |    0
 .../lite/internal/server/ServerNode.java           |    0
 .../lite/internal/server/ServerService.java        |    0
 .../lite/internal/server/ServerStatus.java         |    0
 .../lite/internal/setup/SetUpFacade.java           |    0
 .../internal/sharding/ExecutionContextService.java |    0
 .../lite/internal/sharding/ExecutionService.java   |    0
 .../sharding/MonitorExecutionListenerManager.java  |    0
 .../internal/sharding/ShardingListenerManager.java |    0
 .../lite/internal/sharding/ShardingNode.java       |    0
 .../lite/internal/sharding/ShardingService.java    |    0
 .../lite/internal/snapshot/SnapshotService.java    |    0
 .../lite/internal/storage/JobNodePath.java         |    0
 .../lite/internal/storage/JobNodeStorage.java      |    0
 .../internal/storage/LeaderExecutionCallback.java  |    0
 .../storage/TransactionExecutionCallback.java      |    0
 .../lite/internal/util/SensitiveInfoUtils.java     |    0
 .../lite/reg/base/CoordinatorRegistryCenter.java   |    0
 .../lite/reg/base/ElectionCandidate.java           |    0
 .../elasticjob/lite/reg/base/RegistryCenter.java   |    0
 .../lite/reg/exception/RegException.java           |    0
 .../lite/reg/exception/RegExceptionHandler.java    |    0
 .../lite/reg/zookeeper/ZookeeperConfiguration.java |    0
 .../reg/zookeeper/ZookeeperElectionService.java    |    0
 .../reg/zookeeper/ZookeeperRegistryCenter.java     |    0
 .../elasticjob/lite/spi/TypedSPI.java              |    0
 .../lite/util/concurrent/BlockUtils.java           |    0
 .../util/concurrent/ElasticJobExecutorService.java |    0
 .../lite/util/config/ShardingItemParameters.java   |    0
 .../elasticjob/lite/util/config/ShardingItems.java |    0
 .../elasticjob/lite/util/env/HostException.java    |    0
 .../elasticjob/lite/util/env/IpUtils.java          |    0
 .../elasticjob/lite/util/env/TimeService.java      |    0
 .../elasticjob/lite/util/json/GsonFactory.java     |    0
 .../lite/util/yaml/DefaultYamlTupleProcessor.java  |    0
 .../lite/util/yaml/ElasticJobYamlRepresenter.java  |    0
 .../elasticjob/lite/util/yaml/YamlEngine.java      |    0
 ...e.elasticjob.lite.handler.error.JobErrorHandler |    0
 ...icjob.lite.handler.sharding.JobShardingStrategy |    0
 ...te.handler.threadpool.JobExecutorServiceHandler |    0
 .../lite/api/job/JobConfigurationTest.java         |    0
 .../lite/api/job/ShardingContextTest.java          |    0
 .../DistributeOnceElasticJobListenerTest.java      |    0
 .../listener/fixture/ElasticJobListenerCaller.java |    0
 .../TestDistributeOnceElasticJobListener.java      |    0
 .../listener/fixture/TestElasticJobListener.java   |    0
 .../elasticjob/lite/context/TaskContextTest.java   |    0
 .../lite/exception/ExceptionUtilsTest.java         |    0
 .../exception/JobConfigurationExceptionTest.java   |    0
 .../JobExecutionEnvironmentExceptionTest.java      |    0
 .../lite/exception/JobStatisticExceptionTest.java  |    0
 .../lite/exception/JobSystemExceptionTest.java     |    0
 .../lite/executor/ElasticJobExecutorTest.java      |    0
 .../executor/item/JobItemExecutorFactoryTest.java  |    0
 .../lite/fixture/EmbedTestingServer.java           |    0
 .../elasticjob/lite/fixture/LiteYamlConstants.java |    0
 .../elasticjob/lite/fixture/context/TaskNode.java  |    0
 .../fixture/executor/ClassedFooJobExecutor.java    |    0
 .../lite/fixture/executor/TypedFooJobExecutor.java |    0
 .../lite/fixture/job/DetailedFooJob.java           |    0
 .../elasticjob/lite/fixture/job/FailedJob.java     |    0
 .../elasticjob/lite/fixture/job/FooJob.java        |    0
 .../handler/error/JobErrorHandlerFactoryTest.java  |    0
 .../error/impl/IgnoreJobErrorHandlerTest.java      |    0
 .../handler/error/impl/LogJobErrorHandlerTest.java |    0
 .../error/impl/ThrowJobErrorHandlerTest.java       |    0
 .../lite/handler/sharding/JobInstanceTest.java     |    0
 .../sharding/JobShardingStrategyFactoryTest.java   |    0
 .../AverageAllocationJobShardingStrategyTest.java  |    0
 .../OdevitySortByNameJobShardingStrategyTest.java  |    0
 .../RotateServerByNameJobShardingStrategyTest.java |    0
 .../JobExecutorServiceHandlerFactoryTest.java      |    0
 .../lite/integrate/BaseIntegrateTest.java          |    0
 .../disable/DisabledJobIntegrateTest.java          |    0
 .../disable/OneOffDisabledJobIntegrateTest.java    |    0
 .../disable/ScheduleDisabledJobIntegrateTest.java  |    0
 .../integrate/enable/EnabledJobIntegrateTest.java  |    0
 .../enable/OneOffEnabledJobIntegrateTest.java      |    0
 .../enable/ScheduleEnabledJobIntegrateTest.java    |    0
 .../internal/config/ConfigurationNodeTest.java     |    0
 .../internal/config/ConfigurationServiceTest.java  |    0
 .../config/RescheduleListenerManagerTest.java      |    0
 .../config/yaml/YamlJobConfigurationTest.java      |    0
 .../election/ElectionListenerManagerTest.java      |    0
 .../lite/internal/election/LeaderNodeTest.java     |    0
 .../lite/internal/election/LeaderServiceTest.java  |    0
 .../failover/FailoverListenerManagerTest.java      |    0
 .../lite/internal/failover/FailoverNodeTest.java   |    0
 .../internal/failover/FailoverServiceTest.java     |    0
 .../guarantee/GuaranteeListenerManagerTest.java    |    0
 .../lite/internal/guarantee/GuaranteeNodeTest.java |    0
 .../internal/guarantee/GuaranteeServiceTest.java   |    0
 .../lite/internal/instance/InstanceNodeTest.java   |    0
 .../internal/instance/InstanceServiceTest.java     |    0
 .../instance/ShutdownListenerManagerTest.java      |    0
 .../instance/TriggerListenerManagerTest.java       |    0
 .../lite/internal/listener/JobListenerTest.java    |    0
 .../internal/listener/ListenerManagerTest.java     |    0
 .../RegistryCenterConnectionStateListenerTest.java |    0
 .../internal/listener/fixture/FooJobListener.java  |    0
 .../internal/reconcile/ReconcileServiceTest.java   |    0
 .../lite/internal/schedule/JobRegistryTest.java    |    0
 .../schedule/JobScheduleControllerTest.java        |    0
 .../internal/schedule/JobTriggerListenerTest.java  |    0
 .../lite/internal/schedule/LiteJobFacadeTest.java  |    0
 .../internal/schedule/SchedulerFacadeTest.java     |    0
 .../lite/internal/server/ServerNodeTest.java       |    0
 .../lite/internal/server/ServerServiceTest.java    |    0
 .../lite/internal/setup/SetUpFacadeTest.java       |    0
 .../sharding/ExecutionContextServiceTest.java      |    0
 .../internal/sharding/ExecutionServiceTest.java    |    0
 .../MonitorExecutionListenerManagerTest.java       |    0
 .../sharding/ShardingListenerManagerTest.java      |    0
 .../lite/internal/sharding/ShardingNodeTest.java   |    0
 .../internal/sharding/ShardingServiceTest.java     |    0
 .../internal/snapshot/BaseSnapshotServiceTest.java |    0
 .../snapshot/SnapshotServiceDisableTest.java       |    0
 .../snapshot/SnapshotServiceEnableTest.java        |    0
 .../lite/internal/snapshot/SocketUtils.java        |    0
 .../lite/internal/storage/JobNodePathTest.java     |    0
 .../lite/internal/storage/JobNodeStorageTest.java  |    0
 .../lite/internal/util/SensitiveInfoUtilsTest.java |    0
 .../reg/exception/RegExceptionHandlerTest.java     |    0
 .../reg/zookeeper/ZookeeperConfigurationTest.java  |    0
 .../zookeeper/ZookeeperElectionServiceTest.java    |    0
 .../ZookeeperRegistryCenterForAuthTest.java        |    0
 .../ZookeeperRegistryCenterInitFailureTest.java    |    0
 .../ZookeeperRegistryCenterMiscellaneousTest.java  |    0
 .../ZookeeperRegistryCenterModifyTest.java         |    0
 .../ZookeeperRegistryCenterQueryWithCacheTest.java |    0
 ...okeeperRegistryCenterQueryWithoutCacheTest.java |    0
 .../util/ZookeeperRegistryCenterTestUtil.java      |    0
 .../elasticjob/lite/util/ReflectionUtils.java      |    0
 .../concurrent/ElasticJobExecutorServiceTest.java  |    0
 .../util/config/ShardingItemParametersTest.java    |    0
 .../lite/util/config/ShardingItemsTest.java        |    0
 .../lite/util/env/HostExceptionTest.java           |    0
 .../elasticjob/lite/util/env/IpUtilsTest.java      |    0
 .../elasticjob/lite/util/env/TimeServiceTest.java  |    0
 .../elasticjob/lite/util/json/GsonFactoryTest.java |    0
 .../elasticjob/lite/util/yaml/YamlEngineTest.java  |    0
 ...e.elasticjob.lite.executor.item.JobItemExecutor |    0
 .../src/test/resources/conf.reg/local.properties   |    0
 .../resources/conf.reg/local_overwrite.properties  |    0
 .../src/test/resources/logback-test.xml            |   42 +
 .../elasticjob-lite-dataflow-executor/pom.xml      |   48 +
 .../dataflow/executor/DataflowJobExecutor.java     |    0
 .../elasticjob/lite/dataflow/job/DataflowJob.java  |    0
 .../lite/dataflow/props/DataflowJobProperties.java |    0
 ...e.elasticjob.lite.executor.item.JobItemExecutor |    0
 .../lite/dataflow/job/BatchDataflowJob.java        |    0
 .../lite/dataflow/job/StreamingDataflowJob.java    |    0
 .../elasticjob-lite-script-executor/pom.xml        |   48 +
 .../lite/script/executor/ScriptJobExecutor.java    |    0
 .../lite/script/props/ScriptJobProperties.java     |    0
 ...e.elasticjob.lite.executor.item.JobItemExecutor |    0
 .../elasticjob-lite-simple-executor/pom.xml        |   48 +
 .../lite/simple/executor/SimpleJobExecutor.java    |    0
 .../elasticjob/lite/simple/job/SimpleJob.java      |    0
 ...e.elasticjob.lite.executor.item.JobItemExecutor |    0
 .../elasticjob/lite/simple/job/FooSimpleJob.java   |    0
 elasticjob-lite/elasticjob-lite-executor/pom.xml   |   37 +
 elasticjob-lite/elasticjob-lite-lifecycle/pom.xml  |  105 +
 .../lite/lifecycle/api/JobAPIFactory.java          |    0
 .../lite/lifecycle/api/JobConfigurationAPI.java    |    0
 .../lite/lifecycle/api/JobOperateAPI.java          |    0
 .../lite/lifecycle/api/JobStatisticsAPI.java       |    0
 .../lite/lifecycle/api/ServerStatisticsAPI.java    |    0
 .../lite/lifecycle/api/ShardingOperateAPI.java     |    0
 .../lite/lifecycle/api/ShardingStatisticsAPI.java  |    0
 .../lite/lifecycle/domain/JobBriefInfo.java        |    0
 .../lite/lifecycle/domain/ServerBriefInfo.java     |    0
 .../lite/lifecycle/domain/ShardingInfo.java        |    0
 .../internal/operate/JobOperateAPIImpl.java        |    0
 .../internal/operate/ShardingOperateAPIImpl.java   |    0
 .../internal/reg/RegistryCenterFactory.java        |    0
 .../internal/settings/JobConfigurationAPIImpl.java |    0
 .../internal/statistics/JobStatisticsAPIImpl.java  |    0
 .../statistics/ServerStatisticsAPIImpl.java        |    0
 .../statistics/ShardingStatisticsAPIImpl.java      |    0
 .../lifecycle/AbstractEmbedZookeeperBaseTest.java  |    0
 .../lite/lifecycle/api/JobAPIFactoryTest.java      |    0
 .../lite/lifecycle/domain/ShardingStatusTest.java  |    0
 .../lifecycle/fixture/LifecycleYamlConstants.java  |    0
 .../lite/lifecycle/fixture/TestDataflowJob.java    |    0
 .../lite/lifecycle/fixture/TestSimpleJob.java      |    0
 .../internal/operate/JobOperateAPIImplTest.java    |    0
 .../operate/ShardingOperateAPIImplTest.java        |    0
 .../internal/reg/RegistryCenterFactoryTest.java    |    0
 .../settings/JobConfigurationAPIImplTest.java      |    0
 .../statistics/JobStatisticsAPIImplTest.java       |    0
 .../statistics/ServerStatisticsAPIImplTest.java    |    0
 .../statistics/ShardingStatisticsAPIImplTest.java  |    0
 .../src/test/resources/logback-test.xml            |   38 +
 elasticjob-lite/elasticjob-lite-spring/pom.xml     |  114 +
 .../lite/spring/ElasticJobNamespaceHandler.java    |    0
 .../spring/job/parser/JobBeanDefinitionParser.java |    0
 .../lite/spring/job/tag/JobBeanDefinitionTag.java  |    0
 .../job/tag/JobListenerBeanDefinitionTag.java      |    0
 .../lite/spring/job/util/AopTargetUtils.java       |    0
 .../reg/parser/ZookeeperBeanDefinitionParser.java  |    0
 .../spring/reg/tag/ZookeeperBeanDefinitionTag.java |    0
 .../parser/SnapshotBeanDefinitionParser.java       |    0
 .../snapshot/tag/SnapshotBeanDefinitionTag.java    |    0
 .../parser/TracingBeanDefinitionParser.java        |    0
 .../tracing/tag/TracingBeanDefinitionTag.java      |    0
 .../resources/META-INF/namespace/elasticjob.xsd    |    0
 .../src/main/resources/META-INF/spring.handlers    |    0
 .../src/main/resources/META-INF/spring.schemas     |    0
 .../lite/spring/fixture/aspect/SimpleAspect.java   |    0
 .../spring/fixture/job/DataflowElasticJob.java     |    0
 .../spring/fixture/job/FooSimpleElasticJob.java    |    0
 .../fixture/job/ref/RefFooDataflowElasticJob.java  |    0
 .../fixture/job/ref/RefFooSimpleElasticJob.java    |    0
 .../fixture/listener/SimpleCglibListener.java      |    0
 .../listener/SimpleJdkDynamicProxyListener.java    |    0
 .../spring/fixture/listener/SimpleListener.java    |    0
 .../fixture/listener/SimpleOnceListener.java       |    0
 .../lite/spring/fixture/service/FooService.java    |    0
 .../spring/fixture/service/FooServiceImpl.java     |    0
 .../spring/job/AbstractJobSpringIntegrateTest.java |    0
 .../JobSpringNamespaceWithEventTraceRdbTest.java   |    0
 .../job/JobSpringNamespaceWithJobHandlerTest.java  |    0
 ...JobSpringNamespaceWithListenerAndCglibTest.java |    0
 ...amespaceWithListenerAndJdkDynamicProxyTest.java |    0
 .../job/JobSpringNamespaceWithListenerTest.java    |    0
 .../spring/job/JobSpringNamespaceWithRefTest.java  |    0
 .../job/JobSpringNamespaceWithoutListenerTest.java |    0
 .../SnapshotSpringNamespaceDisableTest.java        |    0
 .../SnapshotSpringNamespaceEnableTest.java         |    0
 .../lite/spring/snapshot/SocketUtils.java          |    0
 .../AbstractZookeeperJUnit4SpringContextTests.java |    0
 .../test/EmbedZookeeperTestExecutionListener.java  |    0
 .../src/test/resources/META-INF/job/base.xml       |    0
 .../resources/META-INF/job/withEventTraceRdb.xml   |    0
 .../test/resources/META-INF/job/withJobHandler.xml |    0
 .../src/test/resources/META-INF/job/withJobRef.xml |    0
 .../test/resources/META-INF/job/withListener.xml   |    0
 .../META-INF/job/withListenerAndCglib.xml          |    0
 .../job/withListenerAndJdkDynamicProxy.xml         |    0
 .../resources/META-INF/job/withoutListener.xml     |    0
 .../src/test/resources/META-INF/reg/regContext.xml |    0
 .../META-INF/snapshot/snapshotDisabled.xml         |    0
 .../META-INF/snapshot/snapshotEnabled.xml          |    0
 .../src/test/resources/conf/job/conf.properties    |   39 +
 .../src/test/resources/conf/reg/conf.properties    |    0
 .../src/test/resources/logback-test.xml            |    0
 .../elasticjob-lite-tracing-api/pom.xml            |   79 +
 .../elasticjob/lite/tracing/JobEventBus.java       |    0
 .../lite/tracing/api/TracingConfiguration.java     |    0
 .../elasticjob/lite/tracing/event/JobEvent.java    |    0
 .../lite/tracing/event/JobExecutionEvent.java      |    0
 .../lite/tracing/event/JobStatusTraceEvent.java    |    0
 .../exception/TracingConfigurationException.java   |    0
 .../lite/tracing/listener/TracingListener.java     |    0
 .../listener/TracingListenerConfiguration.java     |    0
 .../tracing/listener/TracingListenerFactory.java   |    0
 .../elasticjob/lite/tracing/JobEventBusTest.java   |    0
 .../lite/tracing/event/JobExecutionEventTest.java  |    0
 .../lite/tracing/fixture/JobEventCaller.java       |    0
 .../fixture/TestTracingFailureConfiguration.java   |    0
 .../lite/tracing/fixture/TestTracingListener.java  |    0
 .../fixture/TestTracingListenerConfiguration.java  |    0
 .../listener/TracingListenerFactoryTest.java       |    0
 ...e.tracing.listener.TracingListenerConfiguration |    0
 .../src/test/resources/logback-test.xml            |   41 +
 .../elasticjob-lite-tracing-rdb/pom.xml            |   80 +
 .../tracing/rdb/listener/RDBTracingListener.java   |    0
 .../listener/RDBTracingListenerConfiguration.java  |    0
 .../tracing/rdb/storage/RDBJobEventStorage.java    |    0
 .../tracing/rdb/storage/RDBStorageSQLMapper.java   |    0
 .../lite/tracing/rdb/type/DatabaseType.java        |    0
 .../tracing/rdb/type/impl/DB2DatabaseType.java     |    0
 .../lite/tracing/rdb/type/impl/H2DatabaseType.java |    0
 .../tracing/rdb/type/impl/MySQLDatabaseType.java   |    0
 .../tracing/rdb/type/impl/OracleDatabaseType.java  |    0
 .../rdb/type/impl/PostgreSQLDatabaseType.java      |    0
 .../rdb/type/impl/SQLServerDatabaseType.java       |    0
 ...e.tracing.listener.TracingListenerConfiguration |    0
 ...e.elasticjob.lite.tracing.rdb.type.DatabaseType |    0
 .../src/main/resources/META-INF/sql/db2.properties |    0
 .../src/main/resources/META-INF/sql/h2.properties  |    0
 .../main/resources/META-INF/sql/mysql.properties   |    0
 .../main/resources/META-INF/sql/oracle.properties  |    0
 .../resources/META-INF/sql/postgresQL.properties   |    0
 .../main/resources/META-INF/sql/sql92.properties   |    0
 .../resources/META-INF/sql/sqlserver.properties    |    0
 .../RDBTracingListenerConfigurationTest.java       |    0
 .../rdb/listener/RDBTracingListenerTest.java       |    0
 .../rdb/storage/RDBJobEventStorageTest.java        |    0
 .../src/test/resources/logback-test.xml            |   38 +
 elasticjob-lite/elasticjob-lite-tracing/pom.xml    |   36 +
 elasticjob-lite/pom.xml                            |   40 +
 examples/elastic-job-example-embed-zk/pom.xml      |   37 -
 examples/elastic-job-example-jobs/pom.xml          |   54 -
 examples/elastic-job-example-lite-java/pom.xml     |   77 -
 .../elasticjob/lite/example/JavaMain.java          |  110 -
 .../src/main/resources/logback.xml                 |   40 -
 examples/elastic-job-example-lite-spring/pom.xml   |   81 -
 .../src/main/resources/conf/job.properties         |   59 -
 .../src/main/resources/conf/reg.properties         |   22 -
 .../src/main/resources/logback.xml                 |   40 -
 .../elastic-job-example-lite-springboot/pom.xml    |   97 -
 .../src/main/resources/application.yml             |   17 -
 .../src/main/resources/logback.xml                 |   40 -
 examples/elasticjob-example-cloud/pom.xml          |   80 +
 examples/elasticjob-example-cloud/src/README.txt   |   41 +
 .../dangdang/ddframe/job/example/CloudJobMain.java |   29 +
 .../main/resources/META-INF/applicationContext.xml |   14 +
 .../src/main/resources/assembly/assembly.xml       |   25 +
 .../src/main/resources/bin/start.sh                |    2 +
 .../src/main/resources/logback.xml                 |   23 +
 .../src/main/resources/script/demo.sh              |    2 +
 examples/elasticjob-example-embed-zk/pom.xml       |   37 +
 .../lite/example/EmbedZookeeperServer.java         |    0
 examples/elasticjob-example-jobs/pom.xml           |   54 +
 .../lite/example/fixture/entity/Foo.java           |    0
 .../example/fixture/repository/FooRepository.java  |    0
 .../fixture/repository/FooRepositoryFactory.java   |    0
 .../lite/example/job/dataflow/JavaDataflowJob.java |    0
 .../example/job/dataflow/SpringDataflowJob.java    |    0
 .../lite/example/job/simple/JavaSimpleJob.java     |    0
 .../lite/example/job/simple/SpringSimpleJob.java   |    0
 examples/elasticjob-example-lite-java/pom.xml      |   77 +
 .../elasticjob/lite/example/JavaMain.java          |  110 +
 .../src/main/resources/logback.xml                 |   40 +
 .../src/main/resources/script/demo.bat             |    0
 .../src/main/resources/script/demo.sh              |    0
 examples/elasticjob-example-lite-spring/pom.xml    |   81 +
 .../elasticjob/lite/example/SpringMain.java        |    0
 .../main/resources/META-INF/applicationContext.xml |    0
 .../src/main/resources/conf/job.properties         |   59 +
 .../src/main/resources/conf/reg.properties         |   22 +
 .../src/main/resources/logback.xml                 |   40 +
 .../src/main/resources/script/demo.bat             |    0
 .../src/main/resources/script/demo.sh              |    0
 .../elasticjob-example-lite-springboot/pom.xml     |   96 +
 .../elasticjob/lite/example/SpringBootMain.java    |    0
 .../lite/example/config/DataflowJobConfig.java     |    0
 .../lite/example/config/RegistryCenterConfig.java  |    0
 .../lite/example/config/SimpleJobConfig.java       |    0
 .../lite/example/config/TracingConfig.java         |    0
 .../src/main/resources/application-dev.yml         |    0
 .../src/main/resources/application-prod.yml        |    0
 .../src/main/resources/application.yml             |   17 +
 .../src/main/resources/logback.xml                 |   40 +
 examples/pom.xml                                   |   26 +-
 pom.xml                                            |   48 +-
 987 files changed, 56120 insertions(+), 1927 deletions(-)

diff --git a/README.md b/README.md
index c28a8dc..c486e4c 100644
--- a/README.md
+++ b/README.md
@@ -73,14 +73,14 @@ Welcome communicate with community via [mail list](mailto:dev@shardingsphere.apa
 <!-- import elastic-job lite core -->
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-core</artifactId>
+    <artifactId>elasticjob-lite-core</artifactId>
     <version>${lasted.release.version}</version>
 </dependency>
 
 <!-- import other module if need -->
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-spring</artifactId>
+    <artifactId>elasticjob-lite-spring</artifactId>
     <version>${lasted.release.version}</version>
 </dependency>
 ```
diff --git a/README_ZH.md b/README_ZH.md
index f61e0f8..af53478 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -68,17 +68,17 @@ ElasticJob 已于 2020 年 5 月 28 日成为 [Apache ShardingSphere](https://sh
 ### 引入maven依赖
 
 ```xml
-<!-- 引入elastic-job-lite核心模块 -->
+<!-- 引入elasticjob-lite核心模块 -->
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-core</artifactId>
+    <artifactId>elasticjob-lite-core</artifactId>
     <version>${latest.release.version}</version>
 </dependency>
 
 <!-- 使用springframework自定义命名空间时引入 -->
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-spring</artifactId>
+    <artifactId>elasticjob-lite-spring</artifactId>
     <version>${latest.release.version}</version>
 </dependency>
 ```
diff --git a/docs/content/quick-start/_index.cn.md b/docs/content/quick-start/_index.cn.md
index 013858e..c6f5494 100644
--- a/docs/content/quick-start/_index.cn.md
+++ b/docs/content/quick-start/_index.cn.md
@@ -12,7 +12,7 @@ chapter = true
 ```xml
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-core</artifactId>
+    <artifactId>elasticjob-lite-core</artifactId>
     <version>${latest.release.version}</version>
 </dependency>
 ```
@@ -78,7 +78,7 @@ public class JobDemo {
 ```xml
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-spring</artifactId>
+    <artifactId>elasticjob-lite-spring</artifactId>
     <version>${latest.release.version}</version>
 </dependency>
 ```
diff --git a/docs/content/user-manual/deploy-guide.cn.md b/docs/content/user-manual/deploy-guide.cn.md
index 03f9ed1..75571d3 100644
--- a/docs/content/user-manual/deploy-guide.cn.md
+++ b/docs/content/user-manual/deploy-guide.cn.md
@@ -13,10 +13,10 @@ chapter = true
 
 ## 运维平台和 RESTFul API 部署(可选)
 
-1. 解压缩 `elastic-job-lite-console-${version}.tar.gz` 并执行 `bin\start.sh`。
+1. 解压缩 `elasticjob-lite-console-${version}.tar.gz` 并执行 `bin\start.sh`。
 
 2. 打开浏览器访问 `http://localhost:8899/` 即可访问控制台。8899 为默认端口号,可通过启动脚本输入 `-p` 自定义端口号。
 
 3. 访问 RESTFul API 方法同控制台。
 
-4. `elastic-job-lite-console-${version}.tar.gz`可通过 `mvn install` 编译获取。
+4. `elasticjob-lite-console-${version}.tar.gz`可通过 `mvn install` 编译获取。
diff --git a/docs/content/user-manual/job-config.cn.md b/docs/content/user-manual/job-config.cn.md
index 5b3fb0d..a4d2795 100644
--- a/docs/content/user-manual/job-config.cn.md
+++ b/docs/content/user-manual/job-config.cn.md
@@ -51,12 +51,12 @@ chapter = true
 
 ## 2. Spring 命名空间配置
 
-Spring 命名空间与 Java Code 方式配置类似,大部分属性只是将命名方式由驼峰式改为以减号间隔。使用 Spring 命名空间需在 pom.xml 文件中添加 elastic-job-lite-spring 模块的依赖。
+Spring 命名空间与 Java Code 方式配置类似,大部分属性只是将命名方式由驼峰式改为以减号间隔。使用 Spring 命名空间需在 pom.xml 文件中添加 elasticjob-lite-spring 模块的依赖。
 
 ```xml
 <dependency>
     <groupId>org.apache.shardingsphere.elasticjob</groupId>
-    <artifactId>elastic-job-lite-spring</artifactId>
+    <artifactId>elasticjob-lite-spring</artifactId>
     <version>${latest.release.version}</version>
 </dependency>
 ```
diff --git a/docs/content/user-manual/web-console.cn.md b/docs/content/user-manual/web-console.cn.md
index d60ba00..d7469ba 100644
--- a/docs/content/user-manual/web-console.cn.md
+++ b/docs/content/user-manual/web-console.cn.md
@@ -5,9 +5,9 @@ weight = 11
 chapter = true
 +++
 
-解压缩`elastic-job-lite-console-${version}.tar.gz`并执行bin\start.sh。打开浏览器访问`http://localhost:8899/`即可访问控制台。8899为默认端口号,可通过启动脚本输入-p自定义端口号。
+解压缩`elasticjob-lite-console-${version}.tar.gz`并执行bin\start.sh。打开浏览器访问`http://localhost:8899/`即可访问控制台。8899为默认端口号,可通过启动脚本输入-p自定义端口号。
 
-`elastic-job-lite-console-${version}.tar.gz`可通过mvn install编译获取。
+`elasticjob-lite-console-${version}.tar.gz`可通过mvn install编译获取。
 
 ## 登录
 
diff --git a/elastic-job-lite-console/.dockerignore b/elastic-job-lite-console/.dockerignore
deleted file mode 100644
index 0743e9c..0000000
--- a/elastic-job-lite-console/.dockerignore
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-*
-!target/elastic-job-lite-console-*-console-bin.tar.gz
diff --git a/elastic-job-lite-console/Dockerfile b/elastic-job-lite-console/Dockerfile
deleted file mode 100644
index de24d4b..0000000
--- a/elastic-job-lite-console/Dockerfile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-FROM adoptopenjdk:8-jre-hotspot
-CMD bin/start.sh -p $CONSOLE_PORT
-ENV CONSOLE_PORT=8899
-ADD target/elastic-job-lite-console-*.tar.gz /
-RUN mv $(ls -d /elastic-job-lite-console-*) /elastic-job-lite-console
-WORKDIR /elastic-job-lite-console
diff --git a/elastic-job-lite-console/README.md b/elastic-job-lite-console/README.md
deleted file mode 100644
index 168b142..0000000
--- a/elastic-job-lite-console/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# ElasticJob Lite Console
-
-Usage:
-1. Execute `mvn install`.
-2. Extract `elastic-job-lite-console/target/elastic-job-lite-console-${version}.tar.gz` and goto the extracted directory.
-3. Add JDBC Driver (Such as `mysql-connector-java-8.0.13.jar`) to directory `ext-lib`.
-4. Run ElasticJob Lite Console with `bin/start.sh`
diff --git a/elastic-job-lite-console/pom.xml b/elastic-job-lite-console/pom.xml
deleted file mode 100644
index 4491c63..0000000
--- a/elastic-job-lite-console/pom.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-console</artifactId>
-    <packaging>jar</packaging>
-    <name>${project.artifactId}</name>
-    
-    <properties>
-        <spring-boot.version>2.3.1.RELEASE</spring-boot.version>
-        <springframework.version>5.2.7.RELEASE</springframework.version>
-    </properties>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-lifecycle</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-            <version>${spring-boot.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
-            <version>${springframework.version}</version>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-            <version>${springframework.version}</version>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-webmvc</artifactId>
-            <version>${springframework.version}</version>
-            <scope>compile</scope>
-            <exclusions>
-                <exclusion>
-                    <artifactId>spring-web</artifactId>
-                    <groupId>org.springframework</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>spring-context</artifactId>
-                    <groupId>org.springframework</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>commons-dbcp</groupId>
-            <artifactId>commons-dbcp</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-            <scope>compile</scope>
-        </dependency>
-    </dependencies>
-    
-    <build>
-        <resources>
-            <resource>
-               <directory>src/main/resources</directory>
-               <excludes>
-                   <exclude>bin/*</exclude>
-                   <exclude>assembly/*</exclude>
-               </excludes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <configuration>
-                    <descriptors>
-                        <descriptor>src/main/resources/assembly/assembly.xml</descriptor>
-                    </descriptors>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>console-bin</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>single</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
diff --git a/elastic-job-lite-console/src/main/resources/bin/start.sh b/elastic-job-lite-console/src/main/resources/bin/start.sh
deleted file mode 100644
index 0501206..0000000
--- a/elastic-job-lite-console/src/main/resources/bin/start.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-
-show_usage() {
-    echo "Usage: $0 [OPTIONS]"
-    echo "  -p <port>          Server port (default: 8899)"
-    exit 1
-}
-
-if [ $# -ne 0 ] && [ $# -ne 2 ]; then
-  show_usage
-fi
-
-port="8899"
-
-if [ $# -eq 2 ]; then
-  while getopts p: arg
-  do    case "$arg" in
-          p) port="$OPTARG";;
-          [?]) show_usage;;
-        esac
-  done
-fi
-
-if [ "$port" = "" ]; then
-  show_usage
-fi
-
-cd `dirname $0`
-cd ..
-DEPLOY_DIR=`pwd`
-CLASS_PATH=.:${DEPLOY_DIR}/conf:${DEPLOY_DIR}/lib/*:${DEPLOY_DIR}/ext-lib/*
-CONSOLE_MAIN=org.apache.shardingsphere.elasticjob.lite.console.ConsoleBootstrap
-
-exec java -classpath ${CLASS_PATH}:. ${CONSOLE_MAIN} ${port}
diff --git a/elastic-job-lite-console/src/main/resources/logback.xml b/elastic-job-lite-console/src/main/resources/logback.xml
deleted file mode 100644
index f6f1bae..0000000
--- a/elastic-job-lite-console/src/main/resources/logback.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<configuration>
-    <property name="log.directory" value="logs/" />
-    <property name="log.context.name" value="elastic-job-lite-console" />
-    <property name="log.charset" value="UTF-8" />
-    <property name="log.maxHistory" value="30" />
-    <property name="log.pattern" value="[%-5level] %date --%thread-- [%logger] %msg %n" />
-    <property name="log.error.log.level" value="WARN" />
-    <property name="log.async.queue.size" value="1024" />
-    
-    <include resource="includedLogbackConfig.xml" optional="true" />
-    <include resource="conf/includedLogbackConfig.xml" optional="true" />
-    
-    <contextName>${log.context.name}</contextName>
-    
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <fileNamePattern>${log.directory}${log.context.name}-log.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <maxHistory>${log.maxHistory}</maxHistory>
-        </rollingPolicy>
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    
-    <!-- Asynchronized log, for FILE only -->
-    <appender name ="ASYNC_FILE" class= "ch.qos.logback.classic.AsyncAppender">
-        <!-- Don't discard log, logback will discard TRACE, DEBUG, INFO log when queue 80% capacity reached by default. -->
-        <discardingThreshold >0</discardingThreshold>
-        <queueSize>${log.async.queue.size}</queueSize>
-        <appender-ref ref = "FILE"/>
-    </appender>
-     
-    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-          <level>${log.error.log.level}</level>
-        </filter>
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <fileNamePattern>${log.directory}${log.context.name}-error.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <maxHistory>${log.maxHistory}</maxHistory>
-        </rollingPolicy>
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    
-    <root>
-        <level value="INFO" />
-        <appender-ref ref="STDOUT" />
-        <appender-ref ref="ASYNC_FILE" />
-        <appender-ref ref="ERROR" />
-    </root>
-</configuration>
diff --git a/elastic-job-lite-core/pom.xml b/elastic-job-lite-core/pom.xml
deleted file mode 100644
index 91f4cff..0000000
--- a/elastic-job-lite-core/pom.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-core</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-tracing-rdb</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.yaml</groupId>
-            <artifactId>snakeyaml</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.quartz-scheduler</groupId>
-            <artifactId>quartz</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-exec</artifactId>
-            <version>${commons-exec.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-framework</artifactId>
-            <version>${curator.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-recipes</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-test</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-core/src/test/resources/logback-test.xml b/elastic-job-lite-core/src/test/resources/logback-test.xml
deleted file mode 100644
index 9faa73f..0000000
--- a/elastic-job-lite-core/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<configuration>
-    <property name="log.context.name" value="elastic-job-lite-core-test" />
-    <property name="log.charset" value="UTF-8" />
-    <property name="log.pattern" value="[%-5level] %date --%thread-- [%logger] %msg %n" />
-    
-    <contextName>${log.context.name}</contextName>
-    
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>ERROR</level>
-        </filter>
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    
-    <root>
-        <appender-ref ref="STDOUT" />
-    </root>
-    
-    <logger name="org.apache.curator.framework.recipes.leader.LeaderSelector" level="OFF" />
-    <logger name="org.apache.shardingsphere.elasticjob.lite.handler.error.impl.LogJobErrorHandler" level="OFF" />
-    <logger name="org.apache.shardingsphere.elasticjob.lite.internal.snapshot.SnapshotService" level="OFF" />
-</configuration>
diff --git a/elastic-job-lite-executor/elastic-job-lite-dataflow-executor/pom.xml b/elastic-job-lite-executor/elastic-job-lite-dataflow-executor/pom.xml
deleted file mode 100644
index e5f5bfe..0000000
--- a/elastic-job-lite-executor/elastic-job-lite-dataflow-executor/pom.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~  
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>elastic-job-lite-executor</artifactId>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-dataflow-executor</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-core</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-executor/elastic-job-lite-script-executor/pom.xml b/elastic-job-lite-executor/elastic-job-lite-script-executor/pom.xml
deleted file mode 100644
index 0214e7d..0000000
--- a/elastic-job-lite-executor/elastic-job-lite-script-executor/pom.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~  
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite-executor</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-script-executor</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-core</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-executor/elastic-job-lite-simple-executor/pom.xml b/elastic-job-lite-executor/elastic-job-lite-simple-executor/pom.xml
deleted file mode 100644
index 9fec728..0000000
--- a/elastic-job-lite-executor/elastic-job-lite-simple-executor/pom.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~  
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite-executor</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-simple-executor</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-core</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-executor/pom.xml b/elastic-job-lite-executor/pom.xml
deleted file mode 100644
index ee3c603..0000000
--- a/elastic-job-lite-executor/pom.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~  
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-executor</artifactId>
-    <packaging>pom</packaging>
-    <name>${project.artifactId}</name>
-    
-    <modules>
-        <module>elastic-job-lite-simple-executor</module>
-        <module>elastic-job-lite-dataflow-executor</module>
-        <module>elastic-job-lite-script-executor</module>
-    </modules>
-</project>
diff --git a/elastic-job-lite-lifecycle/pom.xml b/elastic-job-lite-lifecycle/pom.xml
deleted file mode 100644
index aa8c395..0000000
--- a/elastic-job-lite-lifecycle/pom.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>elastic-job-lite</artifactId>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-lifecycle</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-core</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-simple-executor</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-dataflow-executor</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-script-executor</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-json</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-client</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-test</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-lifecycle/src/test/resources/logback-test.xml b/elastic-job-lite-lifecycle/src/test/resources/logback-test.xml
deleted file mode 100644
index ed8f9ea..0000000
--- a/elastic-job-lite-lifecycle/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<configuration>
-    <property name="log.context.name" value="elastic-job-lite-lifecycle-core-test" />
-    <property name="log.charset" value="UTF-8" />
-    <property name="log.pattern" value="[%-5level] %date --%thread-- [%logger] %msg %n" />
-    
-    <contextName>${log.context.name}</contextName>
-    
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>ERROR</level>
-        </filter>
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    
-    <root>
-        <appender-ref ref="STDOUT" />
-    </root>
-</configuration>
diff --git a/elastic-job-lite-spring/pom.xml b/elastic-job-lite-spring/pom.xml
deleted file mode 100644
index 80dfe32..0000000
--- a/elastic-job-lite-spring/pom.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-spring</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-core</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-simple-executor</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-dataflow-executor</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-script-executor</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context-support</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>spring-context</artifactId>
-                    <groupId>org.springframework</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-test</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-test</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.aspectj</groupId>
-            <artifactId>aspectjweaver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>commons-dbcp</groupId>
-            <artifactId>commons-dbcp</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-spring/src/test/resources/conf/job/conf.properties b/elastic-job-lite-spring/src/test/resources/conf/job/conf.properties
deleted file mode 100644
index 4344ae1..0000000
--- a/elastic-job-lite-spring/src/test/resources/conf/job/conf.properties
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-regCenter.serverLists=localhost:3181
-regCenter.namespace=elastic-job-lite-spring-test
-regCenter.baseSleepTimeMilliseconds=1000
-regCenter.maxSleepTimeMilliseconds=3000
-regCenter.maxRetries=3
-
-simpleJob.id=simpleElasticJob_namespace_listener
-simpleJob.cron=0/1 * * * * ?
-simpleJob.shardingTotalCount=3
-simpleJob.shardingItemParameters=0=A,1=B,2=C
-simpleJob.disabled=false
-simpleJob.overwrite=true
-
-dataflowJob.cron=0/1 * * * * ?
-dataflowJob.shardingTotalCount=3
-dataflowJob.shardingItemParameters=0=A,1=B,2=C
-dataflowJob.monitorExecution=true
-dataflowJob.failover=true
-dataflowJob.description=Examples of jobs that do not stop running
-dataflowJob.disabled=false
-dataflowJob.overwrite=true
-dataflowJob.streamingProcess=true
diff --git a/elastic-job-lite-tracing/elastic-job-lite-tracing-api/pom.xml b/elastic-job-lite-tracing/elastic-job-lite-tracing-api/pom.xml
deleted file mode 100644
index bb9cc52..0000000
--- a/elastic-job-lite-tracing/elastic-job-lite-tracing-api/pom.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite-tracing</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-tracing-api</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <version>${slf4j.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-tracing/elastic-job-lite-tracing-api/src/test/resources/logback-test.xml b/elastic-job-lite-tracing/elastic-job-lite-tracing-api/src/test/resources/logback-test.xml
deleted file mode 100644
index bb2bcb0..0000000
--- a/elastic-job-lite-tracing/elastic-job-lite-tracing-api/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<configuration>
-    <property name="log.context.name" value="elastic-job-lite-core-test" />
-    <property name="log.charset" value="UTF-8" />
-    <property name="log.pattern" value="[%-5level] %date --%thread-- [%logger] %msg %n" />
-    
-    <contextName>${log.context.name}</contextName>
-    
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>ERROR</level>
-        </filter>
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    
-    <root>
-        <appender-ref ref="STDOUT" />
-    </root>
-    
-    <logger name="org.apache.shardingsphere.elasticjob.lite.tracing.rdb.config.RDBTracingListenerConfiguration" level="OFF" />
-    <logger name="org.apache.shardingsphere.elasticjob.lite.tracing.JobEventBus" level="OFF" />
-</configuration>
diff --git a/elastic-job-lite-tracing/elastic-job-lite-tracing-rdb/pom.xml b/elastic-job-lite-tracing/elastic-job-lite-tracing-rdb/pom.xml
deleted file mode 100644
index b44ec30..0000000
--- a/elastic-job-lite-tracing/elastic-job-lite-tracing-rdb/pom.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite-tracing</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-tracing-rdb</artifactId>
-    <name>${project.artifactId}</name>
-    
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elastic-job-lite-tracing-api</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>commons-dbcp</groupId>
-            <artifactId>commons-dbcp</artifactId>
-            <version>${commons-dbcp.version}</version>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/elastic-job-lite-tracing/elastic-job-lite-tracing-rdb/src/test/resources/logback-test.xml b/elastic-job-lite-tracing/elastic-job-lite-tracing-rdb/src/test/resources/logback-test.xml
deleted file mode 100644
index 3a12ed9..0000000
--- a/elastic-job-lite-tracing/elastic-job-lite-tracing-rdb/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<configuration>
-    <property name="log.context.name" value="elastic-job-lite-core-test" />
-    <property name="log.charset" value="UTF-8" />
-    <property name="log.pattern" value="[%-5level] %date --%thread-- [%logger] %msg %n" />
-    
-    <contextName>${log.context.name}</contextName>
-    
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>ERROR</level>
-        </filter>
-        <encoder charset="${log.charset}">
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-    
-    <root>
-        <appender-ref ref="STDOUT" />
-    </root>
-</configuration>
diff --git a/elastic-job-lite-tracing/pom.xml b/elastic-job-lite-tracing/pom.xml
deleted file mode 100644
index 9483e5e..0000000
--- a/elastic-job-lite-tracing/pom.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.shardingsphere.elasticjob</groupId>
-        <artifactId>elastic-job-lite</artifactId>
-        <version>3.0.0.M1-SNAPSHOT</version>
-    </parent>
-    <artifactId>elastic-job-lite-tracing</artifactId>
-    <packaging>pom</packaging>
-    <name>${project.artifactId}</name>
-    
-    <modules>
-        <module>elastic-job-lite-tracing-api</module>
-        <module>elastic-job-lite-tracing-rdb</module>
-    </modules>
-</project>
diff --git a/elasticjob-cloud/elasticjob-cloud-common/pom.xml b/elasticjob-cloud/elasticjob-cloud-common/pom.xml
new file mode 100755
index 0000000..1c913b3
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~  
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.shardingsphere.elasticjob</groupId>
+        <artifactId>elasticjob-cloud</artifactId>
+        <version>3.0.0.M1-SNAPSHOT</version>
+    </parent>
+    <artifactId>elasticjob-cloud-common</artifactId>
+    <name>${project.artifactId}</name>
+    
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-framework</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-recipes</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-exec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.unitils</groupId>
+            <artifactId>unitils-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-dbcp</groupId>
+            <artifactId>commons-dbcp</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/ElasticJob.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/ElasticJob.java
new file mode 100755
index 0000000..32e1636
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/ElasticJob.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api;
+
+/**
+ * ElasticJob interface.
+ */
+public interface ElasticJob {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/JobType.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/JobType.java
new file mode 100755
index 0000000..b44b445
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/JobType.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api;
+
+/**
+ * Job type.
+ */
+public enum JobType {
+    
+    SIMPLE, DATAFLOW, SCRIPT
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/ShardingContext.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/ShardingContext.java
new file mode 100755
index 0000000..4f8ae8b
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/ShardingContext.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api;
+
+import org.apache.shardingsphere.elasticjob.cloud.executor.ShardingContexts;
+import lombok.Getter;
+import lombok.ToString;
+
+/**
+ * Sharding context.
+ */
+@Getter
+@ToString
+public final class ShardingContext {
+    
+    /**
+     * job name.
+     */
+    private final String jobName;
+    
+    /**
+     * task ID.
+     */
+    private final String taskId;
+    
+    /**
+     * sharding total count.
+     */
+    private final int shardingTotalCount;
+
+    /**
+     * job parameter.
+     *
+     * <p>Can configure for same job class, but use different parameter for different job schedule instance.</p>
+     *
+     */
+    private final String jobParameter;
+
+    /**
+     * Sharding item assigned for this sharding.
+     */
+    private final int shardingItem;
+
+    /**
+     * Sharding parameter assigned for this sharding.
+     */
+    private final String shardingParameter;
+    
+    public ShardingContext(final ShardingContexts shardingContexts, final int shardingItem) {
+        jobName = shardingContexts.getJobName();
+        taskId = shardingContexts.getTaskId();
+        shardingTotalCount = shardingContexts.getShardingTotalCount();
+        jobParameter = shardingContexts.getJobParameter();
+        this.shardingItem = shardingItem;
+        shardingParameter = shardingContexts.getShardingItemParameters().get(shardingItem);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/dataflow/DataflowJob.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/dataflow/DataflowJob.java
new file mode 100755
index 0000000..d2157c1
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/dataflow/DataflowJob.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api.dataflow;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ElasticJob;
+import org.apache.shardingsphere.elasticjob.cloud.api.ShardingContext;
+
+import java.util.List;
+
+/**
+ * Dataflow job.
+ * 
+ * @param <T> type of data
+ */
+public interface DataflowJob<T> extends ElasticJob {
+    
+    /**
+     * Fetch to be processed data.
+     *
+     * @param shardingContext sharding context
+     * @return to be processed data
+     */
+    List<T> fetchData(ShardingContext shardingContext);
+    
+    /**
+     * Process data.
+     *
+     * @param shardingContext sharding context
+     * @param data to be processed data
+     */
+    void processData(ShardingContext shardingContext, List<T> data);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/script/ScriptJob.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/script/ScriptJob.java
new file mode 100755
index 0000000..0c32588
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/script/ScriptJob.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api.script;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ElasticJob;
+
+/**
+ * Script job.
+ */
+public interface ScriptJob extends ElasticJob {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/simple/SimpleJob.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/simple/SimpleJob.java
new file mode 100755
index 0000000..a2ac08e
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/api/simple/SimpleJob.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api.simple;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ElasticJob;
+import org.apache.shardingsphere.elasticjob.cloud.api.ShardingContext;
+
+/**
+ * Simple job.
+ */
+public interface SimpleJob extends ElasticJob {
+    
+    /**
+     * Execute job.
+     *
+     * @param shardingContext sharding context
+     */
+    void execute(ShardingContext shardingContext);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobCoreConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobCoreConfiguration.java
new file mode 100755
index 0000000..72cf1f4
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobCoreConfiguration.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.JobProperties;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Job core configuration.
+ */
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
+@Getter
+public final class JobCoreConfiguration {
+    
+    private final String jobName;
+    
+    private final String cron;
+    
+    private final int shardingTotalCount;
+    
+    private final String shardingItemParameters;
+    
+    private final String jobParameter;
+    
+    private final boolean failover;
+    
+    private final boolean misfire;
+    
+    private final String description;
+    
+    private final JobProperties jobProperties;
+
+    /**
+     * Create simple job configuration builder.
+     *
+     * @param jobName job name
+     * @param cron cron expression for job trigger
+     * @param shardingTotalCount sharding total count
+     * @return simple job configuration builder
+     */
+    public static Builder newBuilder(final String jobName, final String cron, final int shardingTotalCount) {
+        return new Builder(jobName, cron, shardingTotalCount);
+    }
+    
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    public static class Builder {
+        
+        private final String jobName;
+        
+        private final String cron;
+        
+        private final int shardingTotalCount;
+        
+        private String shardingItemParameters = "";
+        
+        private String jobParameter = "";
+        
+        private boolean failover;
+        
+        private boolean misfire = true;
+        
+        private String description = "";
+        
+        private final JobProperties jobProperties = new JobProperties();
+
+        /**
+         * Set mapper of sharding items and sharding parameters.
+         *
+         * <p>
+         * sharding item and sharding parameter split by =, multiple sharding items and sharding parameters split by comma, just like map.
+         * Sharding item start from zero, cannot equal to great than sharding total count.
+         *
+         * For example:
+         * 0=a,1=b,2=c
+         * </p>
+         *
+         * @param shardingItemParameters mapper of sharding items and sharding parameters
+         *
+         * @return job configuration builder
+         */
+        public Builder shardingItemParameters(final String shardingItemParameters) {
+            if (null != shardingItemParameters) {
+                this.shardingItemParameters = shardingItemParameters;
+            }
+            return this;
+        }
+
+        /**
+         * Set job parameter.
+         *
+         * @param jobParameter job parameter
+         *
+         * @return job configuration builder
+         */
+        public Builder jobParameter(final String jobParameter) {
+            if (null != jobParameter) {
+                this.jobParameter = jobParameter;
+            }
+            return this;
+        }
+
+        /**
+         * Set enable failover.
+         *
+         * <p>
+         * Only for `monitorExecution` enabled.
+         * </p>
+         *
+         * @param failover enable or disable failover
+         *
+         * @return job configuration builder
+         */
+        public Builder failover(final boolean failover) {
+            this.failover = failover;
+            return this;
+        }
+
+        /**
+         * Set enable misfire.
+         *
+         * @param misfire enable or disable misfire
+         *
+         * @return job configuration builder
+         */
+        public Builder misfire(final boolean misfire) {
+            this.misfire = misfire;
+            return this;
+        }
+
+        /**
+         * Set job description.
+         *
+         * @param description job description
+         *
+         * @return job configuration builder
+         */
+        public Builder description(final String description) {
+            if (null != description) {
+                this.description = description;
+            }
+            return this;
+        }
+
+        /**
+         * Set job properties.
+         *
+         * @param key property key
+         * @param value property value
+         *
+         * @return job configuration builder
+         */
+        public Builder jobProperties(final String key, final String value) {
+            jobProperties.put(key, value);
+            return this;
+        }
+
+        /**
+         * Build Job.
+         *
+         * @return job configuration builder
+         */
+        public final JobCoreConfiguration build() {
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(jobName), "jobName can not be empty.");
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(cron), "cron can not be empty.");
+            Preconditions.checkArgument(shardingTotalCount > 0, "shardingTotalCount should larger than zero.");
+            return new JobCoreConfiguration(jobName, cron, shardingTotalCount, shardingItemParameters, jobParameter, failover, misfire, description, jobProperties);
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobRootConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobRootConfiguration.java
new file mode 100755
index 0000000..1be7357
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobRootConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config;
+
+/**
+ * Job root configuration.
+ */
+public interface JobRootConfiguration {
+
+    /**
+     * Get type Configuration.
+     *
+     * @return Job type configuration
+     */
+    JobTypeConfiguration getTypeConfig();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobTypeConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobTypeConfiguration.java
new file mode 100755
index 0000000..0c8bfda
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/JobTypeConfiguration.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.JobType;
+
+/**
+ * Job type configuration.
+ */
+public interface JobTypeConfiguration {
+
+    /**
+     * Get job type.
+     *
+     * @return job type
+     */
+    JobType getJobType();
+
+    /**
+     * Get job class name.
+     *
+     * @return job class name
+     */
+    String getJobClass();
+
+    /**
+     * Get job core configuration.
+     *
+     * @return job core configuration
+     */
+    JobCoreConfiguration getCoreConfig();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/dataflow/DataflowJobConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/dataflow/DataflowJobConfiguration.java
new file mode 100755
index 0000000..04aa42c
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/dataflow/DataflowJobConfiguration.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config.dataflow;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.JobType;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobCoreConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobTypeConfiguration;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Dataflow job configuration.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class DataflowJobConfiguration implements JobTypeConfiguration {
+    
+    private final JobCoreConfiguration coreConfig;
+    
+    private final JobType jobType = JobType.DATAFLOW;
+    
+    private final String jobClass;
+    
+    private final boolean streamingProcess;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/script/ScriptJobConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/script/ScriptJobConfiguration.java
new file mode 100755
index 0000000..acd0289
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/script/ScriptJobConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config.script;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.JobType;
+import org.apache.shardingsphere.elasticjob.cloud.api.script.ScriptJob;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobTypeConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobCoreConfiguration;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Script job configuration.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class ScriptJobConfiguration implements JobTypeConfiguration {
+    
+    private final JobCoreConfiguration coreConfig;
+    
+    private final JobType jobType = JobType.SCRIPT;
+    
+    private final String jobClass = ScriptJob.class.getCanonicalName();
+    
+    private final String scriptCommandLine;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/simple/SimpleJobConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/simple/SimpleJobConfiguration.java
new file mode 100755
index 0000000..856bd35
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/config/simple/SimpleJobConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config.simple;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.JobType;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobCoreConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobTypeConfiguration;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Simple job configuration.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class SimpleJobConfiguration implements JobTypeConfiguration {
+    
+    private final JobCoreConfiguration coreConfig;
+    
+    private final JobType jobType = JobType.SIMPLE;
+    
+    private final String jobClass;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/context/ExecutionType.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/context/ExecutionType.java
new file mode 100755
index 0000000..08444b2
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/context/ExecutionType.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.context;
+
+/**
+ * Execution type.
+ */
+public enum ExecutionType {
+
+    /**
+     * Ready of execute.
+     */
+    READY,
+
+    /**
+     * Failover execution.
+     */
+    FAILOVER
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/context/TaskContext.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/context/TaskContext.java
new file mode 100755
index 0000000..55403ca
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/context/TaskContext.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.context;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Task runtime context.
+ */
+@Getter
+@EqualsAndHashCode(of = "id")
+@ToString(of = "id")
+public final class TaskContext {
+    
+    private static final String DELIMITER = "@-@";
+    
+    private static final String UNASSIGNED_SLAVE_ID = "unassigned-slave";
+    
+    private String id;
+    
+    private final MetaInfo metaInfo;
+    
+    private final ExecutionType type;
+    
+    private String slaveId;
+    
+    @Setter
+    private boolean idle;
+    
+    public TaskContext(final String jobName, final List<Integer> shardingItem, final ExecutionType type) {
+        this(jobName, shardingItem, type, UNASSIGNED_SLAVE_ID);
+    }
+    
+    public TaskContext(final String jobName, final List<Integer> shardingItem, final ExecutionType type, final String slaveId) {
+        metaInfo = new MetaInfo(jobName, shardingItem);
+        this.type = type;
+        this.slaveId = slaveId;
+        id = Joiner.on(DELIMITER).join(metaInfo, type, slaveId, UUID.randomUUID().toString());
+    }
+    
+    private TaskContext(final String id, final MetaInfo metaInfo, final ExecutionType type, final String slaveId) {
+        this.id = id;
+        this.metaInfo = metaInfo;
+        this.type = type;
+        this.slaveId = slaveId;
+    }
+
+    /**
+     * Get task context via task ID.
+     *
+     * @param id task ID
+     * @return task context
+     */
+    public static TaskContext from(final String id) {
+        String[] result = id.split(DELIMITER);
+        Preconditions.checkState(5 == result.length);
+        return new TaskContext(id, MetaInfo.from(result[0] + DELIMITER + result[1]), ExecutionType.valueOf(result[2]), result[3]);
+    }
+
+    /**
+     * Get unassigned task ID before job execute.
+     *
+     * @param id task ID
+     * @return unassigned task ID before job execute
+     */
+    public static String getIdForUnassignedSlave(final String id) {
+        return id.replaceAll(TaskContext.from(id).getSlaveId(), UNASSIGNED_SLAVE_ID);
+    }
+
+    /**
+     * Set job server ID.
+     *
+     * @param slaveId job server ID
+     */
+    public void setSlaveId(final String slaveId) {
+        id = id.replaceAll(this.slaveId, slaveId);
+        this.slaveId = slaveId;
+    }
+
+    /**
+     * Get task name.
+     *
+     * @return task name
+     */
+    public String getTaskName() {
+        return Joiner.on(DELIMITER).join(metaInfo, type, slaveId);
+    }
+
+    /**
+     * Get executor ID.
+     *
+     * @param appName application name
+     * @return executor ID
+     */
+    public String getExecutorId(final String appName) {
+        return Joiner.on(DELIMITER).join(appName, slaveId);
+    }
+
+    /**
+     * Task meta data.
+     */
+    @RequiredArgsConstructor
+    @Getter
+    @EqualsAndHashCode
+    public static class MetaInfo {
+        
+        private final String jobName;
+        
+        private final List<Integer> shardingItems;
+
+        /**
+         * Get task meta data info via string.
+         *
+         * @param value task meta data info string
+         * @return task meta data info
+         */
+        public static MetaInfo from(final String value) {
+            String[] result = value.split(DELIMITER);
+            Preconditions.checkState(1 == result.length || 2 == result.length || 5 == result.length);
+            return new MetaInfo(result[0], 1 == result.length || "".equals(result[1]) ? Collections.<Integer>emptyList() : Lists.transform(Splitter.on(",").splitToList(result[1]), 
+                    new Function<String, Integer>() {
+                        
+                        @Override
+                        public Integer apply(final String input) {
+                            return Integer.parseInt(input);
+                        }
+                    }));
+        }
+        
+        @Override
+        public String toString() {
+            return Joiner.on(DELIMITER).join(jobName, Joiner.on(",").join(shardingItems));
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEvent.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEvent.java
new file mode 100755
index 0000000..95223b6
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+/**
+ * Job event.
+ */
+public interface JobEvent {
+
+    /**
+     * Get job name.
+     *
+     * @return job name
+     */
+    String getJobName();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventBus.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventBus.java
new file mode 100755
index 0000000..4bffc03
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventBus.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+import com.google.common.eventbus.AsyncEventBus;
+import com.google.common.eventbus.EventBus;
+import org.apache.shardingsphere.elasticjob.cloud.util.concurrent.ExecutorServiceObject;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Job event bus.
+ */
+@Slf4j
+public final class JobEventBus {
+    
+    private final JobEventConfiguration jobEventConfig;
+    
+    private final ExecutorServiceObject executorServiceObject;
+    
+    private final EventBus eventBus;
+    
+    private boolean isRegistered;
+    
+    public JobEventBus() {
+        jobEventConfig = null;
+        executorServiceObject = null;
+        eventBus = null;
+    }
+    
+    public JobEventBus(final JobEventConfiguration jobEventConfig) {
+        this.jobEventConfig = jobEventConfig;
+        executorServiceObject = new ExecutorServiceObject("job-event", Runtime.getRuntime().availableProcessors() * 2);
+        eventBus = new AsyncEventBus(executorServiceObject.createExecutorService());
+        register();
+    }
+    
+    private void register() {
+        try {
+            eventBus.register(jobEventConfig.createJobEventListener());
+            isRegistered = true;
+        } catch (final JobEventListenerConfigurationException ex) {
+            log.error("Elastic job: create JobEventListener failure, error is: ", ex);
+        }
+    }
+
+    /**
+     * Post event.
+     *
+     * @param event job event
+     */
+    public void post(final JobEvent event) {
+        if (isRegistered && !executorServiceObject.isShutdown()) {
+            eventBus.post(event);
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventConfiguration.java
new file mode 100755
index 0000000..8de6952
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+/**
+ * Job event configuration.
+ */
+public interface JobEventConfiguration extends JobEventIdentity {
+
+    /**
+     * Create job event listener.
+     *
+     * @return Job event listener
+     * @throws JobEventListenerConfigurationException job event listener configuration exception
+     */
+    JobEventListener createJobEventListener() throws JobEventListenerConfigurationException;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventIdentity.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventIdentity.java
new file mode 100755
index 0000000..a3367fb
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventIdentity.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+/**
+ * Job event identity.
+ */
+public interface JobEventIdentity {
+
+    /**
+     * Get identity.
+     *
+     * @return identity
+     */
+    String getIdentity();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventListener.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventListener.java
new file mode 100755
index 0000000..36a2111
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventListener.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+import com.google.common.eventbus.AllowConcurrentEvents;
+import com.google.common.eventbus.Subscribe;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+
+/**
+ * Job event listener.
+ */
+public interface JobEventListener extends JobEventIdentity {
+
+    /**
+     * Listen job execution event.
+     *
+     * @param jobExecutionEvent job execution event
+     */
+    @Subscribe
+    @AllowConcurrentEvents
+    void listen(JobExecutionEvent jobExecutionEvent);
+
+    /**
+     * Listen job status trace event.
+     *
+     * @param jobStatusTraceEvent job status trace event
+     */
+    @Subscribe
+    @AllowConcurrentEvents
+    void listen(JobStatusTraceEvent jobStatusTraceEvent);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventListenerConfigurationException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventListenerConfigurationException.java
new file mode 100755
index 0000000..ac33ae6
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventListenerConfigurationException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+/**
+ * Job event listener configuration exception.
+ */
+public final class JobEventListenerConfigurationException extends Exception {
+    
+    private static final long serialVersionUID = 4069519372148227761L;
+    
+    public JobEventListenerConfigurationException(final Exception ex) {
+        super(ex);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/DatabaseType.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/DatabaseType.java
new file mode 100755
index 0000000..126ebdf
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/DatabaseType.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+import java.util.Arrays;
+
+/**
+ * Database type.
+ */
+public enum DatabaseType {
+    
+    H2("H2"), MySQL("MySQL"), Oracle("Oracle"), SQLServer("Microsoft SQL Server"), DB2("DB2"), PostgreSQL("PostgreSQL");
+    
+    private final String productName;
+    
+    DatabaseType(final String productName) {
+        this.productName = productName;
+    }
+
+    /**
+     * Get database type.
+     *
+     * @param databaseProductName database product name
+     * @return database type
+     */
+    public static DatabaseType valueFrom(final String databaseProductName) {
+        Optional<DatabaseType> databaseTypeOptional = Iterators.tryFind(Arrays.asList(DatabaseType.values()).iterator(), new Predicate<DatabaseType>() {
+            @Override
+            public boolean apply(final DatabaseType input) {
+                return input.productName.equals(databaseProductName);
+            }
+        });
+        if (databaseTypeOptional.isPresent()) {
+            return databaseTypeOptional.get();
+        } else {
+            throw new RuntimeException("Unsupported database:" + databaseProductName);
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbConfiguration.java
new file mode 100755
index 0000000..f608caf
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListener;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListenerConfigurationException;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import javax.sql.DataSource;
+import java.io.Serializable;
+import java.sql.SQLException;
+
+/**
+ * Job event RDB configuration.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class JobEventRdbConfiguration extends JobEventRdbIdentity implements JobEventConfiguration, Serializable {
+    
+    private static final long serialVersionUID = 3344410699286435226L;
+    
+    private final transient DataSource dataSource;
+    
+    @Override
+    public JobEventListener createJobEventListener() throws JobEventListenerConfigurationException {
+        try {
+            return new JobEventRdbListener(dataSource);
+        } catch (final SQLException ex) {
+            throw new JobEventListenerConfigurationException(ex);
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbIdentity.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbIdentity.java
new file mode 100755
index 0000000..1857f44
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbIdentity.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventIdentity;
+
+/**
+ * Job event RDB identity.
+ */
+public class JobEventRdbIdentity implements JobEventIdentity {
+    
+    @Override
+    public String getIdentity() {
+        return "rdb";
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbListener.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbListener.java
new file mode 100755
index 0000000..9027db0
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbListener.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListener;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+/**
+ * Job event RDB listener.
+ */
+public final class JobEventRdbListener extends JobEventRdbIdentity implements JobEventListener {
+    
+    private final JobEventRdbStorage repository;
+    
+    public JobEventRdbListener(final DataSource dataSource) throws SQLException {
+        repository = new JobEventRdbStorage(dataSource);
+    }
+    
+    @Override
+    public void listen(final JobExecutionEvent executionEvent) {
+        repository.addJobExecutionEvent(executionEvent);
+    }
+    
+    @Override
+    public void listen(final JobStatusTraceEvent jobStatusTraceEvent) {
+        repository.addJobStatusTraceEvent(jobStatusTraceEvent);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbSearch.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbSearch.java
new file mode 100755
index 0000000..54fa230
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbSearch.java
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEventThrowable;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Job event RDB search.
+ */
+@RequiredArgsConstructor
+@Slf4j
+public final class JobEventRdbSearch {
+    
+    private static final String TABLE_JOB_EXECUTION_LOG = "JOB_EXECUTION_LOG";
+    
+    private static final String TABLE_JOB_STATUS_TRACE_LOG = "JOB_STATUS_TRACE_LOG";
+    
+    private static final List<String> FIELDS_JOB_EXECUTION_LOG = 
+            Lists.newArrayList("id", "hostname", "ip", "task_id", "job_name", "execution_source", "sharding_item", "start_time", "complete_time", "is_success", "failure_cause");
+    
+    private static final List<String> FIELDS_JOB_STATUS_TRACE_LOG = 
+            Lists.newArrayList("id", "job_name", "original_task_id", "task_id", "slave_id", "source", "execution_type", "sharding_item", "state", "message", "creation_time");
+    
+    private final DataSource dataSource;
+
+    /**
+     * Find job execution events.
+     *
+     * @param condition query condition
+     * @return job execution events
+     */
+    public Result<JobExecutionEvent> findJobExecutionEvents(final Condition condition) {
+        return new Result<>(getEventCount(TABLE_JOB_EXECUTION_LOG, FIELDS_JOB_EXECUTION_LOG, condition), getJobExecutionEvents(condition));
+    }
+
+    /**
+     * Find job status trace events.
+     *
+     * @param condition query condition
+     * @return job status trace events
+     */
+    public Result<JobStatusTraceEvent> findJobStatusTraceEvents(final Condition condition) {
+        return new Result<>(getEventCount(TABLE_JOB_STATUS_TRACE_LOG, FIELDS_JOB_STATUS_TRACE_LOG, condition), getJobStatusTraceEvents(condition));
+    }
+    
+    private List<JobExecutionEvent> getJobExecutionEvents(final Condition condition) {
+        List<JobExecutionEvent> result = new LinkedList<>();
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = createDataPreparedStatement(conn, TABLE_JOB_EXECUTION_LOG, FIELDS_JOB_EXECUTION_LOG, condition);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobExecutionEvent jobExecutionEvent = new JobExecutionEvent(resultSet.getString(1), resultSet.getString(2), resultSet.getString(3), resultSet.getString(4),
+                        resultSet.getString(5), JobExecutionEvent.ExecutionSource.valueOf(resultSet.getString(6)), Integer.valueOf(resultSet.getString(7)), 
+                        new Date(resultSet.getTimestamp(8).getTime()), resultSet.getTimestamp(9) == null ? null : new Date(resultSet.getTimestamp(9).getTime()), 
+                        resultSet.getBoolean(10), new JobExecutionEventThrowable(null, resultSet.getString(11))
+                        );
+                result.add(jobExecutionEvent);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch JobExecutionEvent from DB error:", ex);
+        }
+        return result;
+    }
+    
+    private List<JobStatusTraceEvent> getJobStatusTraceEvents(final Condition condition) {
+        List<JobStatusTraceEvent> result = new LinkedList<>();
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = createDataPreparedStatement(conn, TABLE_JOB_STATUS_TRACE_LOG, FIELDS_JOB_STATUS_TRACE_LOG, condition);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobStatusTraceEvent jobStatusTraceEvent = new JobStatusTraceEvent(resultSet.getString(1), resultSet.getString(2), resultSet.getString(3), resultSet.getString(4),
+                        resultSet.getString(5), JobStatusTraceEvent.Source.valueOf(resultSet.getString(6)), ExecutionType.valueOf(resultSet.getString(7)), resultSet.getString(8),
+                        JobStatusTraceEvent.State.valueOf(resultSet.getString(9)), resultSet.getString(10), new Date(resultSet.getTimestamp(11).getTime()));
+                result.add(jobStatusTraceEvent);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch JobStatusTraceEvent from DB error:", ex);
+        }
+        return result;
+    }
+    
+    private int getEventCount(final String tableName, final Collection<String> tableFields, final Condition condition) {
+        int result = 0;
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = createCountPreparedStatement(conn, tableName, tableFields, condition);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            resultSet.next();
+            result = resultSet.getInt(1);
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch EventCount from DB error:", ex);
+        }
+        return result;
+    }
+    
+    private PreparedStatement createDataPreparedStatement(final Connection conn, final String tableName, final Collection<String> tableFields, final Condition condition) throws SQLException {
+        String sql = buildDataSql(tableName, tableFields, condition);
+        PreparedStatement preparedStatement = conn.prepareStatement(sql);
+        setBindValue(preparedStatement, tableFields, condition);
+        return preparedStatement;
+    }
+    
+    private PreparedStatement createCountPreparedStatement(final Connection conn, final String tableName, final Collection<String> tableFields, final Condition condition) throws SQLException {
+        String sql = buildCountSql(tableName, tableFields, condition);
+        PreparedStatement preparedStatement = conn.prepareStatement(sql);
+        setBindValue(preparedStatement, tableFields, condition);
+        return preparedStatement;
+    }
+    
+    private String buildDataSql(final String tableName, final Collection<String> tableFields, final Condition condition) {
+        StringBuilder sqlBuilder = new StringBuilder();
+        String selectSql = buildSelect(tableName, tableFields);
+        String whereSql = buildWhere(tableName, tableFields, condition);
+        String orderSql = buildOrder(tableFields, condition.getSort(), condition.getOrder());
+        String limitSql = buildLimit(condition.getPage(), condition.getPerPage());
+        sqlBuilder.append(selectSql).append(whereSql).append(orderSql).append(limitSql);
+        return sqlBuilder.toString();
+    }
+    
+    private String buildCountSql(final String tableName, final Collection<String> tableFields, final Condition condition) {
+        StringBuilder sqlBuilder = new StringBuilder();
+        String selectSql = buildSelectCount(tableName);
+        String whereSql = buildWhere(tableName, tableFields, condition);
+        sqlBuilder.append(selectSql).append(whereSql);
+        return sqlBuilder.toString();
+    }
+    
+    private String buildSelectCount(final String tableName) {
+        return String.format("SELECT COUNT(1) FROM %s", tableName);
+    }
+    
+    private String buildSelect(final String tableName, final Collection<String> tableFields) {
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("SELECT ");
+        for (String each : tableFields) {
+            sqlBuilder.append(each).append(",");
+        }
+        sqlBuilder.deleteCharAt(sqlBuilder.length() - 1);
+        sqlBuilder.append(" FROM ").append(tableName);
+        return sqlBuilder.toString();
+    }
+    
+    private String buildWhere(final String tableName, final Collection<String> tableFields, final Condition condition) {
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append(" WHERE 1=1");
+        if (null != condition.getFields() && !condition.getFields().isEmpty()) {
+            for (Map.Entry<String, Object> entry : condition.getFields().entrySet()) {
+                String lowerUnderscore = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey());
+                if (null != entry.getValue() && tableFields.contains(lowerUnderscore)) {
+                    sqlBuilder.append(" AND ").append(lowerUnderscore).append("=?");
+                }
+            }
+        }
+        if (null != condition.getStartTime()) {
+            sqlBuilder.append(" AND ").append(getTableTimeField(tableName)).append(">=?");
+        }
+        if (null != condition.getEndTime()) {
+            sqlBuilder.append(" AND ").append(getTableTimeField(tableName)).append("<=?");
+        }
+        return sqlBuilder.toString();
+    }
+    
+    private void setBindValue(final PreparedStatement preparedStatement, final Collection<String> tableFields, final Condition condition) throws SQLException {
+        int index = 1;
+        if (null != condition.getFields() && !condition.getFields().isEmpty()) {
+            for (Map.Entry<String, Object> entry : condition.getFields().entrySet()) {
+                String lowerUnderscore = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey());
+                if (null != entry.getValue() && tableFields.contains(lowerUnderscore)) {
+                    preparedStatement.setString(index++, String.valueOf(entry.getValue()));
+                }
+            }
+        }
+        if (null != condition.getStartTime()) {
+            preparedStatement.setTimestamp(index++, new Timestamp(condition.getStartTime().getTime()));
+        }
+        if (null != condition.getEndTime()) {
+            preparedStatement.setTimestamp(index, new Timestamp(condition.getEndTime().getTime()));
+        }
+    }
+    
+    private String getTableTimeField(final String tableName) {
+        String result = "";
+        if (TABLE_JOB_EXECUTION_LOG.equals(tableName)) {
+            result = "start_time";
+        } else if (TABLE_JOB_STATUS_TRACE_LOG.equals(tableName)) {
+            result = "creation_time";
+        }
+        return result;
+    }
+    
+    private String buildOrder(final Collection<String> tableFields, final String sortName, final String sortOrder) {
+        if (Strings.isNullOrEmpty(sortName)) {
+            return "";
+        }
+        String lowerUnderscore = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, sortName);
+        if (!tableFields.contains(lowerUnderscore)) {
+            return "";
+        }
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append(" ORDER BY ").append(lowerUnderscore);
+        switch (sortOrder.toUpperCase()) {
+            case "ASC":
+                sqlBuilder.append(" ASC");
+                break;
+            case "DESC":
+                sqlBuilder.append(" DESC");
+                break;
+            default :
+                sqlBuilder.append(" ASC");
+        }
+        return sqlBuilder.toString();
+    }
+    
+    private String buildLimit(final int page, final int perPage) {
+        StringBuilder sqlBuilder = new StringBuilder();
+        if (page > 0 && perPage > 0) {
+            sqlBuilder.append(" LIMIT ").append((page - 1) * perPage).append(",").append(perPage);
+        } else {
+            sqlBuilder.append(" LIMIT ").append(Condition.DEFAULT_PAGE_SIZE);
+        }
+        return sqlBuilder.toString();
+    }
+
+    /**
+     * Query condition.
+     */
+    @RequiredArgsConstructor
+    @Getter
+    public static class Condition {
+        
+        private static final int DEFAULT_PAGE_SIZE = 10;
+        
+        private final int perPage;
+        
+        private final int page;
+        
+        private final String sort;
+        
+        private final String order;
+        
+        private final Date startTime;
+        
+        private final Date endTime;
+        
+        private final Map<String, Object> fields;
+    }
+    
+    @RequiredArgsConstructor
+    @Getter
+    public static class Result<T> {
+        
+        private final Integer total;
+        
+        private final List<T> rows;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbStorage.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbStorage.java
new file mode 100755
index 0000000..7dd30ce
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbStorage.java
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Job event RDB storage.
+ */
+@Slf4j
+final class JobEventRdbStorage {
+    
+    private static final String TABLE_JOB_EXECUTION_LOG = "JOB_EXECUTION_LOG";
+    
+    private static final String TABLE_JOB_STATUS_TRACE_LOG = "JOB_STATUS_TRACE_LOG";
+    
+    private static final String TASK_ID_STATE_INDEX = "TASK_ID_STATE_INDEX";
+    
+    private final DataSource dataSource;
+    
+    private DatabaseType databaseType;
+    
+    JobEventRdbStorage(final DataSource dataSource) throws SQLException {
+        this.dataSource = dataSource;
+        initTablesAndIndexes();
+    }
+    
+    private void initTablesAndIndexes() throws SQLException {
+        try (Connection conn = dataSource.getConnection()) {
+            createJobExecutionTableAndIndexIfNeeded(conn);
+            createJobStatusTraceTableAndIndexIfNeeded(conn);
+            databaseType = DatabaseType.valueFrom(conn.getMetaData().getDatabaseProductName());
+        }
+    }
+    
+    private void createJobExecutionTableAndIndexIfNeeded(final Connection conn) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        try (ResultSet resultSet = dbMetaData.getTables(null, null, TABLE_JOB_EXECUTION_LOG, new String[]{"TABLE"})) {
+            if (!resultSet.next()) {
+                createJobExecutionTable(conn);
+            }
+        }
+    }
+    
+    private void createJobStatusTraceTableAndIndexIfNeeded(final Connection conn) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        try (ResultSet resultSet = dbMetaData.getTables(null, null, TABLE_JOB_STATUS_TRACE_LOG, new String[]{"TABLE"})) {
+            if (!resultSet.next()) {
+                createJobStatusTraceTable(conn);
+            }
+        }
+        createTaskIdIndexIfNeeded(conn, TABLE_JOB_STATUS_TRACE_LOG, TASK_ID_STATE_INDEX);
+    }
+    
+    private void createTaskIdIndexIfNeeded(final Connection conn, final String tableName, final String indexName) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        try (ResultSet resultSet = dbMetaData.getIndexInfo(null, null, tableName, false, false)) {
+            boolean hasTaskIdIndex = false;
+            while (resultSet.next()) {
+                if (indexName.equals(resultSet.getString("INDEX_NAME"))) {
+                    hasTaskIdIndex = true;    
+                }
+            }
+            if (!hasTaskIdIndex) {
+                createTaskIdAndStateIndex(conn, tableName);
+            }
+        }
+    }
+    
+    private void createJobExecutionTable(final Connection conn) throws SQLException {
+        String dbSchema = "CREATE TABLE `" + TABLE_JOB_EXECUTION_LOG + "` ("
+                + "`id` VARCHAR(40) NOT NULL, "
+                + "`job_name` VARCHAR(100) NOT NULL, "
+                + "`task_id` VARCHAR(255) NOT NULL, "
+                + "`hostname` VARCHAR(255) NOT NULL, "
+                + "`ip` VARCHAR(50) NOT NULL, "
+                + "`sharding_item` INT NOT NULL, "
+                + "`execution_source` VARCHAR(20) NOT NULL, "
+                + "`failure_cause` VARCHAR(4000) NULL, "
+                + "`is_success` INT NOT NULL, "
+                + "`start_time` TIMESTAMP NULL, "
+                + "`complete_time` TIMESTAMP NULL, "
+                + "PRIMARY KEY (`id`));";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
+            preparedStatement.execute();
+        }
+    }
+    
+    private void createJobStatusTraceTable(final Connection conn) throws SQLException {
+        String dbSchema = "CREATE TABLE `" + TABLE_JOB_STATUS_TRACE_LOG + "` ("
+                + "`id` VARCHAR(40) NOT NULL, "
+                + "`job_name` VARCHAR(100) NOT NULL, "
+                + "`original_task_id` VARCHAR(255) NOT NULL, "
+                + "`task_id` VARCHAR(255) NOT NULL, "
+                + "`slave_id` VARCHAR(50) NOT NULL, "
+                + "`source` VARCHAR(50) NOT NULL, "
+                + "`execution_type` VARCHAR(20) NOT NULL, "
+                + "`sharding_item` VARCHAR(100) NOT NULL, "
+                + "`state` VARCHAR(20) NOT NULL, "
+                + "`message` VARCHAR(4000) NULL, "
+                + "`creation_time` TIMESTAMP NULL, "
+                + "PRIMARY KEY (`id`));";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
+            preparedStatement.execute();
+        }
+    }
+    
+    private void createTaskIdAndStateIndex(final Connection conn, final String tableName) throws SQLException {
+        String sql = "CREATE INDEX " + TASK_ID_STATE_INDEX + " ON " + tableName + " (`task_id`, `state`);";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.execute();
+        }
+    }
+    
+    boolean addJobExecutionEvent(final JobExecutionEvent jobExecutionEvent) {
+        if (null == jobExecutionEvent.getCompleteTime()) {
+            return insertJobExecutionEvent(jobExecutionEvent);
+        } else {
+            if (jobExecutionEvent.isSuccess()) {
+                return updateJobExecutionEventWhenSuccess(jobExecutionEvent);
+            } else {
+                return updateJobExecutionEventFailure(jobExecutionEvent);
+            }
+        }
+    }
+    
+    private boolean insertJobExecutionEvent(final JobExecutionEvent jobExecutionEvent) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_EXECUTION_LOG + "` (`id`, `job_name`, `task_id`, `hostname`, `ip`, `sharding_item`, `execution_source`, `is_success`, `start_time`) "
+                + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setString(1, jobExecutionEvent.getId());
+            preparedStatement.setString(2, jobExecutionEvent.getJobName());
+            preparedStatement.setString(3, jobExecutionEvent.getTaskId());
+            preparedStatement.setString(4, jobExecutionEvent.getHostname());
+            preparedStatement.setString(5, jobExecutionEvent.getIp());
+            preparedStatement.setInt(6, jobExecutionEvent.getShardingItem());
+            preparedStatement.setString(7, jobExecutionEvent.getSource().toString());
+            preparedStatement.setBoolean(8, jobExecutionEvent.isSuccess());
+            preparedStatement.setTimestamp(9, new Timestamp(jobExecutionEvent.getStartTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            if (!isDuplicateRecord(ex)) {
+                // TODO log failure directly to output log, consider to be configurable in the future
+                log.error(ex.getMessage());    
+            }
+        }
+        return result;
+    }
+    
+    private boolean isDuplicateRecord(final SQLException ex) {
+        return DatabaseType.MySQL.equals(databaseType) && 1062 == ex.getErrorCode() || DatabaseType.H2.equals(databaseType) && 23505 == ex.getErrorCode() 
+                || DatabaseType.SQLServer.equals(databaseType) && 1 == ex.getErrorCode() || DatabaseType.DB2.equals(databaseType) && -803 == ex.getErrorCode()
+                || DatabaseType.PostgreSQL.equals(databaseType) && 0 == ex.getErrorCode() || DatabaseType.Oracle.equals(databaseType) && 1 == ex.getErrorCode();
+    }
+    
+    private boolean updateJobExecutionEventWhenSuccess(final JobExecutionEvent jobExecutionEvent) {
+        boolean result = false;
+        String sql = "UPDATE `" + TABLE_JOB_EXECUTION_LOG + "` SET `is_success` = ?, `complete_time` = ? WHERE id = ?";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setBoolean(1, jobExecutionEvent.isSuccess());
+            preparedStatement.setTimestamp(2, new Timestamp(jobExecutionEvent.getCompleteTime().getTime()));
+            preparedStatement.setString(3, jobExecutionEvent.getId());
+            if (0 == preparedStatement.executeUpdate()) {
+                return insertJobExecutionEventWhenSuccess(jobExecutionEvent);
+            }
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+    
+    private boolean insertJobExecutionEventWhenSuccess(final JobExecutionEvent jobExecutionEvent) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_EXECUTION_LOG + "` (`id`, `job_name`, `task_id`, `hostname`, `ip`, `sharding_item`, `execution_source`, `is_success`, `start_time`, `complete_time`) "
+                + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setString(1, jobExecutionEvent.getId());
+            preparedStatement.setString(2, jobExecutionEvent.getJobName());
+            preparedStatement.setString(3, jobExecutionEvent.getTaskId());
+            preparedStatement.setString(4, jobExecutionEvent.getHostname());
+            preparedStatement.setString(5, jobExecutionEvent.getIp());
+            preparedStatement.setInt(6, jobExecutionEvent.getShardingItem());
+            preparedStatement.setString(7, jobExecutionEvent.getSource().toString());
+            preparedStatement.setBoolean(8, jobExecutionEvent.isSuccess());
+            preparedStatement.setTimestamp(9, new Timestamp(jobExecutionEvent.getStartTime().getTime()));
+            preparedStatement.setTimestamp(10, new Timestamp(jobExecutionEvent.getCompleteTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            if (isDuplicateRecord(ex)) {
+                return updateJobExecutionEventWhenSuccess(jobExecutionEvent);
+            }
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+    
+    private boolean updateJobExecutionEventFailure(final JobExecutionEvent jobExecutionEvent) {
+        boolean result = false;
+        String sql = "UPDATE `" + TABLE_JOB_EXECUTION_LOG + "` SET `is_success` = ?, `complete_time` = ?, `failure_cause` = ? WHERE id = ?";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setBoolean(1, jobExecutionEvent.isSuccess());
+            preparedStatement.setTimestamp(2, new Timestamp(jobExecutionEvent.getCompleteTime().getTime()));
+            preparedStatement.setString(3, truncateString(jobExecutionEvent.getFailureCause()));
+            preparedStatement.setString(4, jobExecutionEvent.getId());
+            if (0 == preparedStatement.executeUpdate()) {
+                return insertJobExecutionEventWhenFailure(jobExecutionEvent);
+            }
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+    
+    private boolean insertJobExecutionEventWhenFailure(final JobExecutionEvent jobExecutionEvent) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_EXECUTION_LOG + "` (`id`, `job_name`, `task_id`, `hostname`, `ip`, `sharding_item`, `execution_source`, `failure_cause`, `is_success`, `start_time`) "
+                + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setString(1, jobExecutionEvent.getId());
+            preparedStatement.setString(2, jobExecutionEvent.getJobName());
+            preparedStatement.setString(3, jobExecutionEvent.getTaskId());
+            preparedStatement.setString(4, jobExecutionEvent.getHostname());
+            preparedStatement.setString(5, jobExecutionEvent.getIp());
+            preparedStatement.setInt(6, jobExecutionEvent.getShardingItem());
+            preparedStatement.setString(7, jobExecutionEvent.getSource().toString());
+            preparedStatement.setString(8, truncateString(jobExecutionEvent.getFailureCause()));
+            preparedStatement.setBoolean(9, jobExecutionEvent.isSuccess());
+            preparedStatement.setTimestamp(10, new Timestamp(jobExecutionEvent.getStartTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            if (isDuplicateRecord(ex)) {
+                return updateJobExecutionEventFailure(jobExecutionEvent);
+            }
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+    
+    boolean addJobStatusTraceEvent(final JobStatusTraceEvent jobStatusTraceEvent) {
+        String originalTaskId = jobStatusTraceEvent.getOriginalTaskId();
+        if (JobStatusTraceEvent.State.TASK_STAGING != jobStatusTraceEvent.getState()) {
+            originalTaskId = getOriginalTaskId(jobStatusTraceEvent.getTaskId());
+        }
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_STATUS_TRACE_LOG + "` (`id`, `job_name`, `original_task_id`, `task_id`, `slave_id`, `source`, `execution_type`, `sharding_item`,  " 
+                + "`state`, `message`, `creation_time`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setString(1, UUID.randomUUID().toString());
+            preparedStatement.setString(2, jobStatusTraceEvent.getJobName());
+            preparedStatement.setString(3, originalTaskId);
+            preparedStatement.setString(4, jobStatusTraceEvent.getTaskId());
+            preparedStatement.setString(5, jobStatusTraceEvent.getSlaveId());
+            preparedStatement.setString(6, jobStatusTraceEvent.getSource().toString());
+            preparedStatement.setString(7, jobStatusTraceEvent.getExecutionType().name());
+            preparedStatement.setString(8, jobStatusTraceEvent.getShardingItems());
+            preparedStatement.setString(9, jobStatusTraceEvent.getState().toString());
+            preparedStatement.setString(10, truncateString(jobStatusTraceEvent.getMessage()));
+            preparedStatement.setTimestamp(11, new Timestamp(jobStatusTraceEvent.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+    
+    private String getOriginalTaskId(final String taskId) {
+        String sql = String.format("SELECT original_task_id FROM %s WHERE task_id = '%s' and state='%s' LIMIT 1", TABLE_JOB_STATUS_TRACE_LOG, taskId, JobStatusTraceEvent.State.TASK_STAGING);
+        String result = "";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+        ) {
+            if (resultSet.next()) {
+                return resultSet.getString("original_task_id");
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+    
+    private String truncateString(final String str) {
+        return !Strings.isNullOrEmpty(str) && str.length() > 4000 ? str.substring(0, 4000) : str;
+    }
+    
+    List<JobStatusTraceEvent> getJobStatusTraceEvents(final String taskId) {
+        String sql = String.format("SELECT * FROM %s WHERE task_id = '%s'", TABLE_JOB_STATUS_TRACE_LOG, taskId);
+        List<JobStatusTraceEvent> result = new ArrayList<>();
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobStatusTraceEvent jobStatusTraceEvent = new JobStatusTraceEvent(resultSet.getString(1), resultSet.getString(2), resultSet.getString(3), resultSet.getString(4),
+                        resultSet.getString(5), JobStatusTraceEvent.Source.valueOf(resultSet.getString(6)), ExecutionType.valueOf(resultSet.getString(7)), resultSet.getString(8),
+                        JobStatusTraceEvent.State.valueOf(resultSet.getString(9)), resultSet.getString(10), new SimpleDateFormat("yyyy-mm-dd HH:MM:SS").parse(resultSet.getString(11)));
+                result.add(jobStatusTraceEvent);
+            }
+        } catch (final SQLException | ParseException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error(ex.getMessage());
+        }
+        return result;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobExecutionEvent.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobExecutionEvent.java
new file mode 100755
index 0000000..931c656
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobExecutionEvent.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.type;
+
+import org.apache.shardingsphere.elasticjob.cloud.exception.ExceptionUtil;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEvent;
+import org.apache.shardingsphere.elasticjob.cloud.util.env.IpUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * Job execution event.
+ */
+@RequiredArgsConstructor
+@AllArgsConstructor
+@Getter
+public final class JobExecutionEvent implements JobEvent {
+    
+    private String id = UUID.randomUUID().toString();
+    
+    private String hostname = IpUtils.getHostName();
+    
+    private String ip = IpUtils.getIp();
+    
+    private final String taskId;
+    
+    private final String jobName;
+    
+    private final ExecutionSource source;
+    
+    private final int shardingItem;
+    
+    private Date startTime = new Date();
+    
+    @Setter
+    private Date completeTime;
+    
+    @Setter
+    private boolean success;
+    
+    @Setter
+    private JobExecutionEventThrowable failureCause;
+
+    /**
+     * Execution success.
+     *
+     * @return job execution event
+     */
+    public JobExecutionEvent executionSuccess() {
+        JobExecutionEvent result = new JobExecutionEvent(id, hostname, ip, taskId, jobName, source, shardingItem, startTime, completeTime, success, failureCause);
+        result.setCompleteTime(new Date());
+        result.setSuccess(true);
+        return result;
+    }
+
+    /**
+     * execution failure.
+     *
+     * @param failureCause failure cause
+     * @return job execution event
+     */
+    public JobExecutionEvent executionFailure(final Throwable failureCause) {
+        JobExecutionEvent result = new JobExecutionEvent(id, hostname, ip, taskId, jobName, source, shardingItem, startTime, completeTime, success, new JobExecutionEventThrowable(failureCause));
+        result.setCompleteTime(new Date());
+        result.setSuccess(false);
+        return result;
+    }
+
+    /**
+     * Get failure cause.
+     *
+     * @return failure cause
+     */
+    public String getFailureCause() {
+        return ExceptionUtil.transform(failureCause == null ? null : failureCause.getThrowable());
+    }
+
+    /**
+     * Execution source.
+     */
+    public enum ExecutionSource {
+        NORMAL_TRIGGER, MISFIRE, FAILOVER
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobExecutionEventThrowable.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobExecutionEventThrowable.java
new file mode 100755
index 0000000..a0d0a17
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobExecutionEventThrowable.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.type;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+/**
+ * Job execution event throwable.
+ */
+@RequiredArgsConstructor
+@AllArgsConstructor
+@Getter
+@ToString(of = "plainText")
+public final class JobExecutionEventThrowable {
+    
+    private final Throwable throwable;
+    
+    private String plainText;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobStatusTraceEvent.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobStatusTraceEvent.java
new file mode 100755
index 0000000..70f1229
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/event/type/JobStatusTraceEvent.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.type;
+
+import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEvent;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * Job status trace event.
+ */
+@RequiredArgsConstructor
+@AllArgsConstructor
+@Getter
+public final class JobStatusTraceEvent implements JobEvent {
+    
+    private String id = UUID.randomUUID().toString();
+    
+    private final String jobName;
+    
+    @Setter
+    private String originalTaskId = "";
+    
+    private final String taskId;
+    
+    private final String slaveId;
+    
+    private final Source source;
+    
+    private final ExecutionType executionType;
+    
+    private final String shardingItems;
+    
+    private final State state;
+    
+    private final String message;
+    
+    private Date creationTime = new Date();
+    
+    public enum State {
+        TASK_STAGING, TASK_RUNNING, TASK_FINISHED, TASK_KILLED, TASK_LOST, TASK_FAILED, TASK_ERROR, TASK_DROPPED, TASK_GONE, TASK_GONE_BY_OPERATOR, TASK_UNREACHABLE, TASK_UNKNOWN
+    }
+    
+    public enum Source {
+        CLOUD_SCHEDULER, CLOUD_EXECUTOR, LITE_EXECUTOR
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/AppConfigurationException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/AppConfigurationException.java
new file mode 100755
index 0000000..1e6c661
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/AppConfigurationException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.exception;
+
+/**
+ * Application configuration exception.
+ */
+public final class AppConfigurationException extends RuntimeException {
+    
+    private static final long serialVersionUID = -1466479389299512371L;
+    
+    public AppConfigurationException(final String errorMessage, final Object... args) {
+        super(String.format(errorMessage, args));
+    }
+    
+    public AppConfigurationException(final Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/ExceptionUtil.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/ExceptionUtil.java
new file mode 100755
index 0000000..ec6a710
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/ExceptionUtil.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.exception;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Exception utility.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ExceptionUtil {
+
+    /**
+     * Transform throwable to string.
+     *
+     * @param cause cause
+     * @return string
+     */
+    public static String transform(final Throwable cause) {
+        if (null == cause) {
+            return "";
+        }
+        StringWriter result = new StringWriter();
+        try (PrintWriter writer = new PrintWriter(result)) {
+            cause.printStackTrace(writer);
+        }
+        return result.toString();
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobConfigurationException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobConfigurationException.java
new file mode 100755
index 0000000..e82e205
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobConfigurationException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.exception;
+
+/**
+ * Job configuration exception.
+ */
+public final class JobConfigurationException extends RuntimeException {
+    
+    private static final long serialVersionUID = 3244988974343209468L;
+    
+    public JobConfigurationException(final String errorMessage, final Object... args) {
+        super(String.format(errorMessage, args));
+    }
+    
+    public JobConfigurationException(final Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobExecutionEnvironmentException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobExecutionEnvironmentException.java
new file mode 100755
index 0000000..f29c232
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobExecutionEnvironmentException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.exception;
+
+/**
+ * Job execution environment exception.
+ */
+public final class JobExecutionEnvironmentException extends Exception {
+    
+    private static final long serialVersionUID = -6670738108926897433L;
+    
+    public JobExecutionEnvironmentException(final String errorMessage, final Object... args) {
+        super(String.format(errorMessage, args));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobStatisticException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobStatisticException.java
new file mode 100755
index 0000000..9bfcd18
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobStatisticException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.exception;
+
+/**
+ * Job statistic exception.
+ */
+public final class JobStatisticException extends RuntimeException {
+    
+    private static final long serialVersionUID = -2502533914008085601L;
+    
+    public JobStatisticException(final Exception ex) {
+        super(ex);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobSystemException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobSystemException.java
new file mode 100755
index 0000000..b52ff05
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/exception/JobSystemException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.exception;
+
+/**
+ * Job system exception.
+ */
+public final class JobSystemException extends RuntimeException {
+    
+    private static final long serialVersionUID = 5018901344199973515L;
+    
+    public JobSystemException(final String errorMessage, final Object... args) {
+        super(String.format(errorMessage, args));
+    }
+    
+    public JobSystemException(final Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/AbstractElasticJobExecutor.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/AbstractElasticJobExecutor.java
new file mode 100755
index 0000000..8e0d2a3
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/AbstractElasticJobExecutor.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.cloud.exception.ExceptionUtil;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.JobExceptionHandler;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobRootConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobExecutionEnvironmentException;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobSystemException;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.ExecutorServiceHandler;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.ExecutorServiceHandlerRegistry;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.JobProperties;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * ElasticJob executor.
+ */
+@Slf4j
+public abstract class AbstractElasticJobExecutor {
+    
+    @Getter(AccessLevel.PROTECTED)
+    private final JobFacade jobFacade;
+    
+    @Getter(AccessLevel.PROTECTED)
+    private final JobRootConfiguration jobRootConfig;
+    
+    private final String jobName;
+    
+    private final ExecutorService executorService;
+    
+    private final JobExceptionHandler jobExceptionHandler;
+    
+    private final Map<Integer, String> itemErrorMessages;
+    
+    protected AbstractElasticJobExecutor(final JobFacade jobFacade) {
+        this.jobFacade = jobFacade;
+        jobRootConfig = jobFacade.loadJobRootConfiguration(true);
+        jobName = jobRootConfig.getTypeConfig().getCoreConfig().getJobName();
+        executorService = ExecutorServiceHandlerRegistry.getExecutorServiceHandler(jobName, (ExecutorServiceHandler) getHandler(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER));
+        jobExceptionHandler = (JobExceptionHandler) getHandler(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER);
+        itemErrorMessages = new ConcurrentHashMap<>(jobRootConfig.getTypeConfig().getCoreConfig().getShardingTotalCount(), 1);
+    }
+    
+    private Object getHandler(final JobProperties.JobPropertiesEnum jobPropertiesEnum) {
+        String handlerClassName = jobRootConfig.getTypeConfig().getCoreConfig().getJobProperties().get(jobPropertiesEnum);
+        try {
+            Class<?> handlerClass = Class.forName(handlerClassName);
+            if (jobPropertiesEnum.getClassType().isAssignableFrom(handlerClass)) {
+                return handlerClass.newInstance();
+            }
+            return getDefaultHandler(jobPropertiesEnum, handlerClassName);
+        } catch (final ReflectiveOperationException ex) {
+            return getDefaultHandler(jobPropertiesEnum, handlerClassName);
+        }
+    }
+    
+    private Object getDefaultHandler(final JobProperties.JobPropertiesEnum jobPropertiesEnum, final String handlerClassName) {
+        log.warn("Cannot instantiation class '{}', use default '{}' class.", handlerClassName, jobPropertiesEnum.getKey());
+        try {
+            return Class.forName(jobPropertiesEnum.getDefaultValue()).newInstance();
+        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+            throw new JobSystemException(e);
+        }
+    }
+
+    /**
+     * Execute job.
+     */
+    public final void execute() {
+        try {
+            jobFacade.checkJobExecutionEnvironment();
+        } catch (final JobExecutionEnvironmentException cause) {
+            jobExceptionHandler.handleException(jobName, cause);
+        }
+        ShardingContexts shardingContexts = jobFacade.getShardingContexts();
+        if (shardingContexts.isAllowSendJobEvent()) {
+            jobFacade.postJobStatusTraceEvent(shardingContexts.getTaskId(), JobStatusTraceEvent.State.TASK_STAGING, String.format("Job '%s' execute begin.", jobName));
+        }
+        if (jobFacade.misfireIfRunning(shardingContexts.getShardingItemParameters().keySet())) {
+            if (shardingContexts.isAllowSendJobEvent()) {
+                jobFacade.postJobStatusTraceEvent(shardingContexts.getTaskId(), JobStatusTraceEvent.State.TASK_FINISHED, String.format(
+                        "Previous job '%s' - shardingItems '%s' is still running, misfired job will start after previous job completed.", jobName, 
+                        shardingContexts.getShardingItemParameters().keySet()));
+            }
+            return;
+        }
+        try {
+            jobFacade.beforeJobExecuted(shardingContexts);
+            //CHECKSTYLE:OFF
+        } catch (final Throwable cause) {
+            //CHECKSTYLE:ON
+            jobExceptionHandler.handleException(jobName, cause);
+        }
+        execute(shardingContexts, JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER);
+        while (jobFacade.isExecuteMisfired(shardingContexts.getShardingItemParameters().keySet())) {
+            jobFacade.clearMisfire(shardingContexts.getShardingItemParameters().keySet());
+            execute(shardingContexts, JobExecutionEvent.ExecutionSource.MISFIRE);
+        }
+        jobFacade.failoverIfNecessary();
+        try {
+            jobFacade.afterJobExecuted(shardingContexts);
+            //CHECKSTYLE:OFF
+        } catch (final Throwable cause) {
+            //CHECKSTYLE:ON
+            jobExceptionHandler.handleException(jobName, cause);
+        }
+    }
+    
+    private void execute(final ShardingContexts shardingContexts, final JobExecutionEvent.ExecutionSource executionSource) {
+        if (shardingContexts.getShardingItemParameters().isEmpty()) {
+            if (shardingContexts.isAllowSendJobEvent()) {
+                jobFacade.postJobStatusTraceEvent(shardingContexts.getTaskId(), JobStatusTraceEvent.State.TASK_FINISHED, String.format("Sharding item for job '%s' is empty.", jobName));
+            }
+            return;
+        }
+        jobFacade.registerJobBegin(shardingContexts);
+        String taskId = shardingContexts.getTaskId();
+        if (shardingContexts.isAllowSendJobEvent()) {
+            jobFacade.postJobStatusTraceEvent(taskId, JobStatusTraceEvent.State.TASK_RUNNING, "");
+        }
+        try {
+            process(shardingContexts, executionSource);
+        } finally {
+            // TODO Consider increasing the status of job failure, and how to handle the overall loop of job failure
+            jobFacade.registerJobCompleted(shardingContexts);
+            if (itemErrorMessages.isEmpty()) {
+                if (shardingContexts.isAllowSendJobEvent()) {
+                    jobFacade.postJobStatusTraceEvent(taskId, JobStatusTraceEvent.State.TASK_FINISHED, "");
+                }
+            } else {
+                if (shardingContexts.isAllowSendJobEvent()) {
+                    jobFacade.postJobStatusTraceEvent(taskId, JobStatusTraceEvent.State.TASK_ERROR, itemErrorMessages.toString());
+                }
+            }
+        }
+    }
+    
+    private void process(final ShardingContexts shardingContexts, final JobExecutionEvent.ExecutionSource executionSource) {
+        Collection<Integer> items = shardingContexts.getShardingItemParameters().keySet();
+        if (1 == items.size()) {
+            int item = shardingContexts.getShardingItemParameters().keySet().iterator().next();
+            JobExecutionEvent jobExecutionEvent = new JobExecutionEvent(shardingContexts.getTaskId(), jobName, executionSource, item);
+            process(shardingContexts, item, jobExecutionEvent);
+            return;
+        }
+        final CountDownLatch latch = new CountDownLatch(items.size());
+        for (final int each : items) {
+            final JobExecutionEvent jobExecutionEvent = new JobExecutionEvent(shardingContexts.getTaskId(), jobName, executionSource, each);
+            if (executorService.isShutdown()) {
+                return;
+            }
+            executorService.submit(new Runnable() {
+                
+                @Override
+                public void run() {
+                    try {
+                        process(shardingContexts, each, jobExecutionEvent);
+                    } finally {
+                        latch.countDown();
+                    }
+                }
+            });
+        }
+        try {
+            latch.await();
+        } catch (final InterruptedException ex) {
+            Thread.currentThread().interrupt();
+        }
+    }
+    
+    private void process(final ShardingContexts shardingContexts, final int item, final JobExecutionEvent startEvent) {
+        if (shardingContexts.isAllowSendJobEvent()) {
+            jobFacade.postJobExecutionEvent(startEvent);
+        }
+        log.trace("Job '{}' executing, item is: '{}'.", jobName, item);
+        JobExecutionEvent completeEvent;
+        try {
+            process(new ShardingContext(shardingContexts, item));
+            completeEvent = startEvent.executionSuccess();
+            log.trace("Job '{}' executed, item is: '{}'.", jobName, item);
+            if (shardingContexts.isAllowSendJobEvent()) {
+                jobFacade.postJobExecutionEvent(completeEvent);
+            }
+            // CHECKSTYLE:OFF
+        } catch (final Throwable cause) {
+            // CHECKSTYLE:ON
+            completeEvent = startEvent.executionFailure(cause);
+            jobFacade.postJobExecutionEvent(completeEvent);
+            itemErrorMessages.put(item, ExceptionUtil.transform(cause));
+            jobExceptionHandler.handleException(jobName, cause);
+        }
+    }
+    
+    protected abstract void process(ShardingContext shardingContext);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/JobExecutorFactory.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/JobExecutorFactory.java
new file mode 100755
index 0000000..2ed1aa7
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/JobExecutorFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ElasticJob;
+import org.apache.shardingsphere.elasticjob.cloud.api.dataflow.DataflowJob;
+import org.apache.shardingsphere.elasticjob.cloud.api.simple.SimpleJob;
+import org.apache.shardingsphere.elasticjob.cloud.executor.type.DataflowJobExecutor;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobConfigurationException;
+import org.apache.shardingsphere.elasticjob.cloud.executor.type.ScriptJobExecutor;
+import org.apache.shardingsphere.elasticjob.cloud.executor.type.SimpleJobExecutor;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * Job executor factory.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class JobExecutorFactory {
+
+    /**
+     * Get job executor.
+     *
+     * @param elasticJob elasticJob object
+     * @param jobFacade job facade
+     * @return job executor
+     */
+    @SuppressWarnings("unchecked")
+    public static AbstractElasticJobExecutor getJobExecutor(final ElasticJob elasticJob, final JobFacade jobFacade) {
+        if (null == elasticJob) {
+            return new ScriptJobExecutor(jobFacade);
+        }
+        if (elasticJob instanceof SimpleJob) {
+            return new SimpleJobExecutor((SimpleJob) elasticJob, jobFacade);
+        }
+        if (elasticJob instanceof DataflowJob) {
+            return new DataflowJobExecutor((DataflowJob) elasticJob, jobFacade);
+        }
+        throw new JobConfigurationException("Cannot support job type '%s'", elasticJob.getClass().getCanonicalName());
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/JobFacade.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/JobFacade.java
new file mode 100755
index 0000000..8f00324
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/JobFacade.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor;
+
+import org.apache.shardingsphere.elasticjob.cloud.config.JobRootConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent.State;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobExecutionEnvironmentException;
+
+import java.util.Collection;
+
+/**
+ * Job facade.
+ */
+public interface JobFacade {
+
+    /**
+     * Load job root configuration.
+     *
+     * @param fromCache load from cache or not
+     * @return job root configuration
+     */
+    JobRootConfiguration loadJobRootConfiguration(boolean fromCache);
+
+    /**
+     * check job execution environment.
+     *
+     * @throws JobExecutionEnvironmentException job execution environment exception
+     */
+    void checkJobExecutionEnvironment() throws JobExecutionEnvironmentException;
+
+    /**
+     * Failover If necessary.
+     */
+    void failoverIfNecessary();
+
+    /**
+     * Register job begin.
+     *
+     * @param shardingContexts sharding contexts
+     */
+    void registerJobBegin(ShardingContexts shardingContexts);
+
+    /**
+     * Register job completed.
+     *
+     * @param shardingContexts sharding contexts
+     */
+    void registerJobCompleted(ShardingContexts shardingContexts);
+
+    /**
+     * Get sharding contexts.
+     *
+     * @return sharding contexts
+     */
+    ShardingContexts getShardingContexts();
+
+    /**
+     * Set task misfire flag.
+     *
+     * @param shardingItems sharding items to be set misfire flag
+     * @return whether satisfy misfire condition
+     */
+    boolean misfireIfRunning(Collection<Integer> shardingItems);
+
+    /**
+     * Clear misfire flag.
+     *
+     * @param shardingItems sharding items to be cleared misfire flag
+     */
+    void clearMisfire(Collection<Integer> shardingItems);
+
+    /**
+     * Judge job whether need to execute misfire tasks.
+     *
+     * @param shardingItems sharding items
+     * @return whether need to execute misfire tasks
+     */
+    boolean isExecuteMisfired(Collection<Integer> shardingItems);
+
+    /**
+     * Judge job whether eligible running.
+     *
+     * <p>The ineligible job includes:
+     * 1. Need to shutdown;
+     * 2. Need to resharding;
+     * 3. Not stream job.
+     *
+     * @return job is eligible running or not
+     */
+    boolean isEligibleForJobRunning();
+
+    /**
+     * Judge job whether need resharding.
+     *
+     * @return whether need resharding
+     */
+    boolean isNeedSharding();
+
+    /**
+     * Call before job executed.
+     *
+     * @param shardingContexts sharding contexts
+     */
+    void beforeJobExecuted(ShardingContexts shardingContexts);
+
+    /**
+     * Call after job executed.
+     *
+     * @param shardingContexts sharding contexts
+     */
+    void afterJobExecuted(ShardingContexts shardingContexts);
+
+    /**
+     * Post job execution event.
+     *
+     * @param jobExecutionEvent job execution event
+     */
+    void postJobExecutionEvent(JobExecutionEvent jobExecutionEvent);
+
+    /**
+     * Post job status trace event.
+     *
+     * @param taskId task Id
+     * @param state job state
+     * @param message job message
+     */
+    void postJobStatusTraceEvent(String taskId, State state, String message);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/ShardingContexts.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/ShardingContexts.java
new file mode 100755
index 0000000..48be43f
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/ShardingContexts.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Sharding contexts.
+ */
+@RequiredArgsConstructor
+@Getter
+@ToString
+public final class ShardingContexts implements Serializable {
+    
+    private static final long serialVersionUID = -4585977349142082152L;
+    
+    /**
+     * task ID.
+     */
+    private final String taskId;
+    
+    /**
+     * job name.
+     */
+    private final String jobName;
+
+    /**
+     * sharding total count.
+     */
+    private final int shardingTotalCount;
+
+    /**
+     * Job parameter.
+     * Can configure multiple identical jobs, but use different parameters as different scheduling instances
+     */
+    private final String jobParameter;
+
+    /**
+     * Sharding items and parameters map.
+     */
+    private final Map<Integer, String> shardingItemParameters;
+
+    /**
+     * Job event sampling count.
+     */
+    private int jobEventSamplingCount;
+
+    /**
+     * Current job event sampling count.
+     */
+    @Setter
+    private int currentJobEventSamplingCount;
+    
+    /**
+     * Whether allow send job event.
+     */
+    @Setter
+    private boolean allowSendJobEvent = true;
+    
+    public ShardingContexts(final String taskId, final String jobName, final int shardingTotalCount, final String jobParameter, 
+                            final Map<Integer, String> shardingItemParameters, final int jobEventSamplingCount) {
+        this.taskId = taskId;
+        this.jobName = jobName;
+        this.shardingTotalCount = shardingTotalCount;
+        this.jobParameter = jobParameter;
+        this.shardingItemParameters = shardingItemParameters;
+        this.jobEventSamplingCount = jobEventSamplingCount;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/ExecutorServiceHandler.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/ExecutorServiceHandler.java
new file mode 100755
index 0000000..0018d36
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/ExecutorServiceHandler.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.handler;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Executor service handler.
+ */
+public interface ExecutorServiceHandler {
+
+    /**
+     * Create executor service.
+     *
+     * @param jobName job name
+     *
+     * @return executor service
+     */
+    ExecutorService createExecutorService(String jobName);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/ExecutorServiceHandlerRegistry.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/ExecutorServiceHandlerRegistry.java
new file mode 100755
index 0000000..e36dd94
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/ExecutorServiceHandlerRegistry.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.handler;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Executor service handler registry.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ExecutorServiceHandlerRegistry {
+    
+    private static final Map<String, ExecutorService> REGISTRY = new HashMap<>();
+
+    /**
+     * Get executor service handler.
+     *
+     * @param jobName job name
+     * @param executorServiceHandler executor service handler
+     * @return executor service
+     */
+    public static synchronized ExecutorService getExecutorServiceHandler(final String jobName, final ExecutorServiceHandler executorServiceHandler) {
+        if (!REGISTRY.containsKey(jobName)) {
+            REGISTRY.put(jobName, executorServiceHandler.createExecutorService(jobName));
+        }
+        return REGISTRY.get(jobName);
+    }
+
+    /**
+     * Remove executor service from executor service handler registry.
+     *
+     * @param jobName job name
+     */
+    public static synchronized void remove(final String jobName) {
+        REGISTRY.remove(jobName);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/JobExceptionHandler.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/JobExceptionHandler.java
new file mode 100755
index 0000000..51ede85
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/JobExceptionHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.handler;
+
+/**
+ * Job exception handler.
+ */
+public interface JobExceptionHandler {
+
+    /**
+     * Handle exception.
+     *
+     * @param jobName job name
+     * @param cause cause
+     */
+    void handleException(String jobName, Throwable cause);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/JobProperties.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/JobProperties.java
new file mode 100755
index 0000000..2fbf548
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/JobProperties.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.handler;
+
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.impl.DefaultJobExceptionHandler;
+import org.apache.shardingsphere.elasticjob.cloud.util.json.GsonFactory;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.impl.DefaultExecutorServiceHandler;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.RequiredArgsConstructor;
+
+import java.util.EnumMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Job properties.
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+public final class JobProperties {
+    
+    private EnumMap<JobPropertiesEnum, String> map = new EnumMap<>(JobPropertiesEnum.class);
+
+    /**
+     * Put job property.
+     *
+     * @param key property key
+     * @param value property value
+     */
+    public void put(final String key, final String value) {
+        JobPropertiesEnum jobPropertiesEnum = JobPropertiesEnum.from(key);
+        if (null == jobPropertiesEnum || null == value) {
+            return;
+        }
+        map.put(jobPropertiesEnum, value);
+    }
+
+    /**
+     * Get job property.
+     *
+     * @param jobPropertiesEnum job properties enum
+     * @return property value
+     */
+    public String get(final JobPropertiesEnum jobPropertiesEnum) {
+        return map.containsKey(jobPropertiesEnum) ? map.get(jobPropertiesEnum) : jobPropertiesEnum.getDefaultValue();
+    }
+
+    /**
+     * Get all keys.
+     *
+     * @return all keys
+     */
+    public String json() {
+        Map<String, String> jsonMap = new LinkedHashMap<>(JobPropertiesEnum.values().length, 1);
+        for (JobPropertiesEnum each : JobPropertiesEnum.values()) {
+            jsonMap.put(each.getKey(), get(each));
+        }
+        return GsonFactory.getGson().toJson(jsonMap);
+    }
+
+    /**
+     * Job properties enum.
+     */
+    @RequiredArgsConstructor
+    @Getter
+    public enum JobPropertiesEnum {
+
+        /**
+         * Job execution handler.
+         */
+        JOB_EXCEPTION_HANDLER("job_exception_handler", JobExceptionHandler.class, DefaultJobExceptionHandler.class.getCanonicalName()),
+
+        /**
+         * Executor service handler.
+         */
+        EXECUTOR_SERVICE_HANDLER("executor_service_handler", ExecutorServiceHandler.class, DefaultExecutorServiceHandler.class.getCanonicalName());
+        
+        private final String key;
+    
+        private final Class<?> classType;
+        
+        private final String defaultValue;
+
+        /**
+         * Get job properties enum via key.
+         *
+         * @param key property key
+         * @return job properties enum
+         */
+        public static JobPropertiesEnum from(final String key) {
+            for (JobPropertiesEnum each : JobPropertiesEnum.values()) {
+                if (each.getKey().equals(key)) {
+                    return each;
+                }
+            }
+            return null;
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/impl/DefaultExecutorServiceHandler.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/impl/DefaultExecutorServiceHandler.java
new file mode 100755
index 0000000..e9f6eac
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/impl/DefaultExecutorServiceHandler.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.handler.impl;
+
+import org.apache.shardingsphere.elasticjob.cloud.util.concurrent.ExecutorServiceObject;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.ExecutorServiceHandler;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Default executor service handler.
+ */
+public final class DefaultExecutorServiceHandler implements ExecutorServiceHandler {
+    
+    @Override
+    public ExecutorService createExecutorService(final String jobName) {
+        return new ExecutorServiceObject("inner-job-" + jobName, Runtime.getRuntime().availableProcessors() * 2).createExecutorService();
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/impl/DefaultJobExceptionHandler.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/impl/DefaultJobExceptionHandler.java
new file mode 100755
index 0000000..6402bf7
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/handler/impl/DefaultJobExceptionHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.handler.impl;
+
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.JobExceptionHandler;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Default job exception handler.
+ */
+@Slf4j
+public final class DefaultJobExceptionHandler implements JobExceptionHandler {
+    
+    @Override
+    public void handleException(final String jobName, final Throwable cause) {
+        log.error(String.format("Job '%s' exception occur in job processing", jobName), cause);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/DataflowJobExecutor.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/DataflowJobExecutor.java
new file mode 100755
index 0000000..83a33d3
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/DataflowJobExecutor.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.type;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.cloud.api.dataflow.DataflowJob;
+import org.apache.shardingsphere.elasticjob.cloud.config.dataflow.DataflowJobConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.executor.AbstractElasticJobExecutor;
+import org.apache.shardingsphere.elasticjob.cloud.executor.JobFacade;
+
+import java.util.List;
+
+/**
+ * Dataflow job executor.
+ */
+public final class DataflowJobExecutor extends AbstractElasticJobExecutor {
+    
+    private final DataflowJob<Object> dataflowJob;
+    
+    public DataflowJobExecutor(final DataflowJob<Object> dataflowJob, final JobFacade jobFacade) {
+        super(jobFacade);
+        this.dataflowJob = dataflowJob;
+    }
+    
+    @Override
+    protected void process(final ShardingContext shardingContext) {
+        DataflowJobConfiguration dataflowConfig = (DataflowJobConfiguration) getJobRootConfig().getTypeConfig();
+        if (dataflowConfig.isStreamingProcess()) {
+            streamingExecute(shardingContext);
+        } else {
+            oneOffExecute(shardingContext);
+        }
+    }
+    
+    private void streamingExecute(final ShardingContext shardingContext) {
+        List<Object> data = fetchData(shardingContext);
+        while (null != data && !data.isEmpty()) {
+            processData(shardingContext, data);
+            if (!getJobFacade().isEligibleForJobRunning()) {
+                break;
+            }
+            data = fetchData(shardingContext);
+        }
+    }
+    
+    private void oneOffExecute(final ShardingContext shardingContext) {
+        List<Object> data = fetchData(shardingContext);
+        if (null != data && !data.isEmpty()) {
+            processData(shardingContext, data);
+        }
+    }
+    
+    private List<Object> fetchData(final ShardingContext shardingContext) {
+        return dataflowJob.fetchData(shardingContext);
+    }
+    
+    private void processData(final ShardingContext shardingContext, final List<Object> data) {
+        dataflowJob.processData(shardingContext, data);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/ScriptJobExecutor.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/ScriptJobExecutor.java
new file mode 100755
index 0000000..87b9a20
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/ScriptJobExecutor.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.type;
+
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.elasticjob.cloud.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.cloud.config.script.ScriptJobConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobConfigurationException;
+import org.apache.shardingsphere.elasticjob.cloud.executor.AbstractElasticJobExecutor;
+import org.apache.shardingsphere.elasticjob.cloud.executor.JobFacade;
+import org.apache.shardingsphere.elasticjob.cloud.util.json.GsonFactory;
+import org.apache.commons.exec.CommandLine;
+import org.apache.commons.exec.DefaultExecutor;
+
+import java.io.IOException;
+
+/**
+ * Script job executor.
+ */
+public final class ScriptJobExecutor extends AbstractElasticJobExecutor {
+    
+    public ScriptJobExecutor(final JobFacade jobFacade) {
+        super(jobFacade);
+    }
+    
+    @Override
+    protected void process(final ShardingContext shardingContext) {
+        final String scriptCommandLine = ((ScriptJobConfiguration) getJobRootConfig().getTypeConfig()).getScriptCommandLine();
+        if (Strings.isNullOrEmpty(scriptCommandLine)) {
+            throw new JobConfigurationException("Cannot find script command line for job '%s', job is not executed.", shardingContext.getJobName());
+        }
+        executeScript(shardingContext, scriptCommandLine);
+    }
+    
+    private void executeScript(final ShardingContext shardingContext, final String scriptCommandLine) {
+        CommandLine commandLine = CommandLine.parse(scriptCommandLine);
+        commandLine.addArgument(GsonFactory.getGson().toJson(shardingContext), false);
+        try {
+            new DefaultExecutor().execute(commandLine);
+        } catch (final IOException ex) {
+            throw new JobConfigurationException("Execute script failure.", ex);
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/SimpleJobExecutor.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/SimpleJobExecutor.java
new file mode 100755
index 0000000..90f5208
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/executor/type/SimpleJobExecutor.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.executor.type;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.cloud.api.simple.SimpleJob;
+import org.apache.shardingsphere.elasticjob.cloud.executor.AbstractElasticJobExecutor;
+import org.apache.shardingsphere.elasticjob.cloud.executor.JobFacade;
+
+/**
+ * Simple job executor.
+ */
+public final class SimpleJobExecutor extends AbstractElasticJobExecutor {
+    
+    private final SimpleJob simpleJob;
+    
+    public SimpleJobExecutor(final SimpleJob simpleJob, final JobFacade jobFacade) {
+        super(jobFacade);
+        this.simpleJob = simpleJob;
+    }
+    
+    @Override
+    protected void process(final ShardingContext shardingContext) {
+        simpleJob.execute(shardingContext);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/CoordinatorRegistryCenter.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/CoordinatorRegistryCenter.java
new file mode 100755
index 0000000..8d9025a
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/CoordinatorRegistryCenter.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.base;
+
+import java.util.List;
+
+/**
+ * Coordinator registry center.
+ */
+public interface CoordinatorRegistryCenter extends RegistryCenter {
+
+    /**
+     * Get value from registry center directly.
+     *
+     * @param key key
+     * @return value
+     */
+    String getDirectly(String key);
+
+    /**
+     * Get children keys.
+     *
+     * @param key key
+     * @return children keys
+     */
+    List<String> getChildrenKeys(String key);
+
+    /**
+     * Get children number.
+     *
+     * @param key key
+     * @return children number
+     */
+    int getNumChildren(String key);
+
+    /**
+     * Persist ephemeral data.
+     *
+     * @param key key
+     * @param value value
+     */
+    void persistEphemeral(String key, String value);
+
+    /**
+     * Persist sequential data.
+     *
+     * @param key key
+     * @param value value
+     * @return value which include 10 digital
+     */
+    String persistSequential(String key, String value);
+
+    /**
+     * Persist ephemeral sequential data.
+     *
+     * @param key key
+     */
+    void persistEphemeralSequential(String key);
+
+    /**
+     * Add data to cache.
+     *
+     * @param cachePath cache path
+     */
+    void addCacheData(String cachePath);
+
+    /**
+     * Evict data from cache.
+     *
+     * @param cachePath cache path
+     */
+    void evictCacheData(String cachePath);
+
+    /**
+     * Get raw cache object of registry center.
+     *
+     * @param cachePath cache path
+     * @return raw cache object of registry center
+     */
+    Object getRawCache(String cachePath);
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/ElectionCandidate.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/ElectionCandidate.java
new file mode 100755
index 0000000..bae16b3
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/ElectionCandidate.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.base;
+
+/**
+ * Election candidate.
+ *
+ * <p>
+ *     Guarantee {@link #startLeadership()} and {@link #stopLeadership()} method run in same thread.
+ * </p>
+ */
+public interface ElectionCandidate {
+
+    /**
+     * Start leadership.
+     *
+     * @throws Exception exception
+     */
+    void startLeadership() throws Exception;
+
+    /**
+     * Stop leadership.
+     *
+     * <p>Should not throw any exception for the implementation class.</p>
+     */
+    void stopLeadership();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/RegistryCenter.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/RegistryCenter.java
new file mode 100755
index 0000000..1f95c8b
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/base/RegistryCenter.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.base;
+
+/**
+ * Registry center.
+ */
+public interface RegistryCenter {
+
+    /**
+     * Initialize registry center.
+     */
+    void init();
+
+    /**
+     * Close registry center.
+     */
+    void close();
+
+    /**
+     * Get value.
+     *
+     * @param key key
+     * @return value
+     */
+    String get(String key);
+
+    /**
+     * Judge node is exist or not.
+     *
+     * @param key key
+     * @return node is exist or not
+     */
+    boolean isExisted(String key);
+
+    /**
+     * Persist data.
+     *
+     * @param key key
+     * @param value value
+     */
+    void persist(String key, String value);
+
+    /**
+     * Update data.
+     *
+     * @param key key
+     * @param value value
+     */
+    void update(String key, String value);
+
+    /**
+     * Remove data.
+     *
+     * @param key key
+     */
+    void remove(String key);
+
+    /**
+     * Get current time from registry center.
+     *
+     * @param key key
+     * @return current time from registry center
+     */
+    long getRegistryCenterTime(String key);
+
+    /**
+     * Get raw client for registry center client.
+     **
+     * @return registry center raw client
+     */
+    Object getRawClient();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/exception/RegException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/exception/RegException.java
new file mode 100755
index 0000000..381a87e
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/exception/RegException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.exception;
+
+/**
+ * Registry center exception.
+ */
+public final class RegException extends RuntimeException {
+    
+    private static final long serialVersionUID = -6417179023552012152L;
+    
+    public RegException(final String errorMessage, final Object... args) {
+        super(String.format(errorMessage, args));
+    }
+    
+    public RegException(final Exception cause) {
+        super(cause);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/exception/RegExceptionHandler.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/exception/RegExceptionHandler.java
new file mode 100755
index 0000000..63ad3f6
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/exception/RegExceptionHandler.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.exception;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.zookeeper.KeeperException.ConnectionLossException;
+import org.apache.zookeeper.KeeperException.NoNodeException;
+import org.apache.zookeeper.KeeperException.NodeExistsException;
+
+/**
+ * Registry center exception handler.
+ */
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class RegExceptionHandler {
+
+    /**
+     * Handle exception.
+     *
+     * @param cause exception to be handled
+     */
+    public static void handleException(final Exception cause) {
+        if (null == cause) {
+            return;
+        }
+        if (isIgnoredException(cause) || null != cause.getCause() && isIgnoredException(cause.getCause())) {
+            log.debug("Elastic job: ignored exception for: {}", cause.getMessage());
+        } else if (cause instanceof InterruptedException) {
+            Thread.currentThread().interrupt();
+        } else {
+            throw new RegException(cause);
+        }
+    }
+    
+    private static boolean isIgnoredException(final Throwable cause) {
+        return cause instanceof ConnectionLossException || cause instanceof NoNodeException || cause instanceof NodeExistsException;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperConfiguration.java
new file mode 100755
index 0000000..73b69a2
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperConfiguration.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.zookeeper;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Zookeeper configuration.
+ */
+@Getter
+@Setter
+@RequiredArgsConstructor
+public final class ZookeeperConfiguration {
+
+    /**
+     * Server list of ZooKeeper.
+     *
+     * <p>
+     * Include IP addresses and ports,
+     * Multiple IP address split by comma.
+     * For example: host1:2181,host2:2181
+     * </p>
+     */
+    private final String serverLists;
+
+    /**
+     * Namespace.
+     */
+    private final String namespace;
+
+    /**
+     * Base sleep time milliseconds.
+     */
+    private int baseSleepTimeMilliseconds = 1000;
+
+    /**
+     * Max sleep time milliseconds.
+     */
+    private int maxSleepTimeMilliseconds = 3000;
+
+    /**
+     * Max retry times.
+     */
+    private int maxRetries = 3;
+
+    /**
+     * Session timeout milliseconds.
+     */
+    private int sessionTimeoutMilliseconds;
+
+    /**
+     * Connection timeout milliseconds.
+     */
+    private int connectionTimeoutMilliseconds;
+
+    /**
+     * Zookeeper digest.
+     */
+    private String digest;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperElectionService.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperElectionService.java
new file mode 100755
index 0000000..6935713
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperElectionService.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.zookeeper;
+
+import org.apache.shardingsphere.elasticjob.cloud.reg.base.ElectionCandidate;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobSystemException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.recipes.leader.LeaderSelector;
+import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Use {@link LeaderSelector} to implement election service.
+ */
+@Slf4j
+public final class ZookeeperElectionService {
+    
+    private final CountDownLatch leaderLatch = new CountDownLatch(1);
+    
+    private final LeaderSelector leaderSelector;
+    
+    public ZookeeperElectionService(final String identity, final CuratorFramework client, final String electionPath, final ElectionCandidate electionCandidate) {
+        leaderSelector = new LeaderSelector(client, electionPath, new LeaderSelectorListenerAdapter() {
+            
+            @Override
+            public void takeLeadership(final CuratorFramework client) throws Exception {
+                log.info("Elastic job: {} has leadership", identity);
+                try {
+                    electionCandidate.startLeadership();
+                    leaderLatch.await();
+                    log.warn("Elastic job: {} lost leadership.", identity);
+                    electionCandidate.stopLeadership();
+                } catch (final JobSystemException exception) {
+                    log.error("Elastic job: Starting error", exception);
+                    System.exit(1);  
+                }
+            }
+        });
+        leaderSelector.autoRequeue();
+        leaderSelector.setId(identity);
+    }
+
+    /**
+     * Start election.
+     */
+    public void start() {
+        log.debug("Elastic job: {} start to elect leadership", leaderSelector.getId());
+        leaderSelector.start();
+    }
+
+    /**
+     * Stop election.
+     */
+    public void stop() {
+        log.info("Elastic job: stop leadership election");
+        leaderLatch.countDown();
+        try {
+            leaderSelector.close();
+            // CHECKSTYLE:OFF
+        } catch (final Exception ignored) {
+        }
+        // CHECKSTYLE:ON
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperRegistryCenter.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperRegistryCenter.java
new file mode 100755
index 0000000..2a3caaf
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/reg/zookeeper/ZookeeperRegistryCenter.java
@@ -0,0 +1,331 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.reg.zookeeper;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.elasticjob.cloud.reg.base.CoordinatorRegistryCenter;
+import org.apache.shardingsphere.elasticjob.cloud.reg.exception.RegExceptionHandler;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.ACLProvider;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.TreeCache;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Registry center of ZooKeeper.
+ */
+@Slf4j
+public final class ZookeeperRegistryCenter implements CoordinatorRegistryCenter {
+    
+    @Getter(AccessLevel.PROTECTED)
+    private ZookeeperConfiguration zkConfig;
+    
+    private final Map<String, TreeCache> caches = new HashMap<>();
+    
+    @Getter
+    private CuratorFramework client;
+    
+    public ZookeeperRegistryCenter(final ZookeeperConfiguration zkConfig) {
+        this.zkConfig = zkConfig;
+    }
+    
+    @Override
+    public void init() {
+        log.debug("Elastic job: zookeeper registry center init, server lists is: {}.", zkConfig.getServerLists());
+        CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
+                .connectString(zkConfig.getServerLists())
+                .retryPolicy(new ExponentialBackoffRetry(zkConfig.getBaseSleepTimeMilliseconds(), zkConfig.getMaxRetries(), zkConfig.getMaxSleepTimeMilliseconds()))
+                .namespace(zkConfig.getNamespace());
+        if (0 != zkConfig.getSessionTimeoutMilliseconds()) {
+            builder.sessionTimeoutMs(zkConfig.getSessionTimeoutMilliseconds());
+        }
+        if (0 != zkConfig.getConnectionTimeoutMilliseconds()) {
+            builder.connectionTimeoutMs(zkConfig.getConnectionTimeoutMilliseconds());
+        }
+        if (!Strings.isNullOrEmpty(zkConfig.getDigest())) {
+            builder.authorization("digest", zkConfig.getDigest().getBytes(Charsets.UTF_8))
+                    .aclProvider(new ACLProvider() {
+                    
+                        @Override
+                        public List<ACL> getDefaultAcl() {
+                            return ZooDefs.Ids.CREATOR_ALL_ACL;
+                        }
+                    
+                        @Override
+                        public List<ACL> getAclForPath(final String path) {
+                            return ZooDefs.Ids.CREATOR_ALL_ACL;
+                        }
+                    });
+        }
+        client = builder.build();
+        client.start();
+        try {
+            if (!client.blockUntilConnected(zkConfig.getMaxSleepTimeMilliseconds() * zkConfig.getMaxRetries(), TimeUnit.MILLISECONDS)) {
+                client.close();
+                throw new KeeperException.OperationTimeoutException();
+            }
+            //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+            //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+    }
+    
+    @Override
+    public void close() {
+        for (Entry<String, TreeCache> each : caches.entrySet()) {
+            each.getValue().close();
+        }
+        waitForCacheClose();
+        CloseableUtils.closeQuietly(client);
+    }
+
+    /*
+     * TODO
+     * sleep 500ms, let cache client close first and then client, otherwise will throw exception
+     * reference:https://issues.apache.org/jira/browse/CURATOR-157
+     */
+    private void waitForCacheClose() {
+        try {
+            Thread.sleep(500L);
+        } catch (final InterruptedException ex) {
+            Thread.currentThread().interrupt();
+        }
+    }
+    
+    @Override
+    public String get(final String key) {
+        TreeCache cache = findTreeCache(key);
+        if (null == cache) {
+            return getDirectly(key);
+        }
+        ChildData resultInCache = cache.getCurrentData(key);
+        if (null != resultInCache) {
+            return null == resultInCache.getData() ? null : new String(resultInCache.getData(), Charsets.UTF_8);
+        }
+        return getDirectly(key);
+    }
+    
+    private TreeCache findTreeCache(final String key) {
+        for (Entry<String, TreeCache> entry : caches.entrySet()) {
+            if (key.startsWith(entry.getKey())) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+    
+    @Override
+    public String getDirectly(final String key) {
+        try {
+            return new String(client.getData().forPath(key), Charsets.UTF_8);
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+            return null;
+        }
+    }
+    
+    @Override
+    public List<String> getChildrenKeys(final String key) {
+        try {
+            List<String> result = client.getChildren().forPath(key);
+            Collections.sort(result, new Comparator<String>() {
+                
+                @Override
+                public int compare(final String o1, final String o2) {
+                    return o2.compareTo(o1);
+                }
+            });
+            return result;
+         //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+            return Collections.emptyList();
+        }
+    }
+    
+    @Override
+    public int getNumChildren(final String key) {
+        try {
+            Stat stat = client.checkExists().forPath(key);
+            if (null != stat) {
+                return stat.getNumChildren();
+            }
+            //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+            //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+        return 0;
+    }
+
+    @Override
+    public boolean isExisted(final String key) {
+        try {
+            return null != client.checkExists().forPath(key);
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+            return false;
+        }
+    }
+    
+    @Override
+    public void persist(final String key, final String value) {
+        try {
+            if (!isExisted(key)) {
+                client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(key, value.getBytes(Charsets.UTF_8));
+            } else {
+                update(key, value);
+            }
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+    }
+    
+    @Override
+    public void update(final String key, final String value) {
+        try {
+            client.inTransaction().check().forPath(key).and().setData().forPath(key, value.getBytes(Charsets.UTF_8)).and().commit();
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+    }
+    
+    @Override
+    public void persistEphemeral(final String key, final String value) {
+        try {
+            if (isExisted(key)) {
+                client.delete().deletingChildrenIfNeeded().forPath(key);
+            }
+            client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(key, value.getBytes(Charsets.UTF_8));
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+    }
+    
+    @Override
+    public String persistSequential(final String key, final String value) {
+        try {
+            return client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(key, value.getBytes(Charsets.UTF_8));
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+        return null;
+    }
+    
+    @Override
+    public void persistEphemeralSequential(final String key) {
+        try {
+            client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(key);
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+    }
+    
+    @Override
+    public void remove(final String key) {
+        try {
+            client.delete().deletingChildrenIfNeeded().forPath(key);
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+    }
+    
+    @Override
+    public long getRegistryCenterTime(final String key) {
+        long result = 0L;
+        try {
+            persist(key, "");
+            result = client.checkExists().forPath(key).getMtime();
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+        Preconditions.checkState(0L != result, "Cannot get registry center time.");
+        return result;
+    }
+    
+    @Override
+    public Object getRawClient() {
+        return client;
+    }
+    
+    @Override
+    public void addCacheData(final String cachePath) {
+        TreeCache cache = new TreeCache(client, cachePath);
+        try {
+            cache.start();
+        //CHECKSTYLE:OFF
+        } catch (final Exception ex) {
+        //CHECKSTYLE:ON
+            RegExceptionHandler.handleException(ex);
+        }
+        caches.put(cachePath + "/", cache);
+    }
+    
+    @Override
+    public void evictCacheData(final String cachePath) {
+        TreeCache cache = caches.remove(cachePath + "/");
+        if (null != cache) {
+            cache.close();
+        }
+    }
+    
+    @Override
+    public Object getRawCache(final String cachePath) {
+        return caches.get(cachePath + "/");
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/StatisticInterval.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/StatisticInterval.java
new file mode 100755
index 0000000..fc9f7e3
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/StatisticInterval.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Task running statistics.
+ */
+@Getter
+@RequiredArgsConstructor
+public enum StatisticInterval {
+    
+    MINUTE("0 * * * * ?"),
+    
+    HOUR("0 0 * * * ?"), 
+    
+    DAY("0 0 0 * * ?");
+    
+    private final String cron;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/rdb/StatisticRdbRepository.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/rdb/StatisticRdbRepository.java
new file mode 100755
index 0000000..46833a1
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/rdb/StatisticRdbRepository.java
@@ -0,0 +1,495 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.rdb;
+
+import com.google.common.base.Optional;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.StatisticInterval;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRegisterStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRunningStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskResultStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskRunningStatistics;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Statistic RDB repository.
+ */
+@Slf4j
+public class StatisticRdbRepository {
+    
+    private static final String TABLE_TASK_RESULT_STATISTICS = "TASK_RESULT_STATISTICS";
+    
+    private static final String TABLE_TASK_RUNNING_STATISTICS = "TASK_RUNNING_STATISTICS";
+
+    private static final String TABLE_JOB_RUNNING_STATISTICS = "JOB_RUNNING_STATISTICS";
+    
+    private static final String TABLE_JOB_REGISTER_STATISTICS = "JOB_REGISTER_STATISTICS";
+    
+    private final DataSource dataSource;
+
+    public StatisticRdbRepository(final DataSource dataSource) throws SQLException {
+        this.dataSource = dataSource;
+        initTables();
+    }
+    
+    private void initTables() throws SQLException {
+        try (Connection conn = dataSource.getConnection()) {
+            createTaskResultTableIfNeeded(conn);
+            createTaskRunningTableIfNeeded(conn);
+            createJobRunningTableIfNeeded(conn);
+            createJobRegisterTableIfNeeded(conn);
+        }
+    }
+    
+    private void createTaskResultTableIfNeeded(final Connection conn) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        for (StatisticInterval each : StatisticInterval.values()) {
+            try (ResultSet resultSet = dbMetaData.getTables(null, null, TABLE_TASK_RESULT_STATISTICS + "_" + each, new String[]{"TABLE"})) {
+                if (!resultSet.next()) {
+                    createTaskResultTable(conn, each);
+                }
+            }
+        }
+    }
+    
+    private void createTaskResultTable(final Connection conn, final StatisticInterval statisticInterval) throws SQLException {
+        String dbSchema = "CREATE TABLE `" + TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval + "` ("
+                + "`id` BIGINT NOT NULL AUTO_INCREMENT, "
+                + "`success_count` INT(11),"
+                + "`failed_count` INT(11),"
+                + "`statistics_time` TIMESTAMP NOT NULL,"
+                + "`creation_time` TIMESTAMP NOT NULL,"
+                + "PRIMARY KEY (`id`));";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
+            preparedStatement.execute();
+        }
+    }
+    
+    private void createTaskRunningTableIfNeeded(final Connection conn) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        try (ResultSet resultSet = dbMetaData.getTables(null, null, TABLE_TASK_RUNNING_STATISTICS, new String[]{"TABLE"})) {
+            if (!resultSet.next()) {
+                createTaskRunningTable(conn);
+            }
+        }
+    }
+    
+    private void createTaskRunningTable(final Connection conn) throws SQLException {
+        String dbSchema = "CREATE TABLE `" + TABLE_TASK_RUNNING_STATISTICS + "` ("
+                + "`id` BIGINT NOT NULL AUTO_INCREMENT, "
+                + "`running_count` INT(11),"
+                + "`statistics_time` TIMESTAMP NOT NULL,"
+                + "`creation_time` TIMESTAMP NOT NULL,"
+                + "PRIMARY KEY (`id`));";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
+            preparedStatement.execute();
+        }
+    }
+    
+    private void createJobRunningTableIfNeeded(final Connection conn) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        try (ResultSet resultSet = dbMetaData.getTables(null, null, TABLE_JOB_RUNNING_STATISTICS, new String[]{"TABLE"})) {
+            if (!resultSet.next()) {
+                createJobRunningTable(conn);
+            }
+        }
+    }
+    
+    private void createJobRunningTable(final Connection conn) throws SQLException {
+        String dbSchema = "CREATE TABLE `" + TABLE_JOB_RUNNING_STATISTICS + "` ("
+                + "`id` BIGINT NOT NULL AUTO_INCREMENT, "
+                + "`running_count` INT(11),"
+                + "`statistics_time` TIMESTAMP NOT NULL,"
+                + "`creation_time` TIMESTAMP NOT NULL,"
+                + "PRIMARY KEY (`id`));";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
+            preparedStatement.execute();
+        }
+    }
+    
+    private void createJobRegisterTableIfNeeded(final Connection conn) throws SQLException {
+        DatabaseMetaData dbMetaData = conn.getMetaData();
+        try (ResultSet resultSet = dbMetaData.getTables(null, null, TABLE_JOB_REGISTER_STATISTICS, new String[]{"TABLE"})) {
+            if (!resultSet.next()) {
+                createJobRegisterTable(conn);
+            }
+        }
+    }
+    
+    private void createJobRegisterTable(final Connection conn) throws SQLException {
+        String dbSchema = "CREATE TABLE `" + TABLE_JOB_REGISTER_STATISTICS + "` ("
+                + "`id` BIGINT NOT NULL AUTO_INCREMENT, "
+                + "`registered_count` INT(11),"
+                + "`statistics_time` TIMESTAMP NOT NULL,"
+                + "`creation_time` TIMESTAMP NOT NULL,"
+                + "PRIMARY KEY (`id`));";
+        try (PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
+            preparedStatement.execute();
+        }
+    }
+
+    /**
+     * Add task result statistics.
+     *
+     * @param taskResultStatistics task result statistics
+     * @return add success or not
+     */
+    public boolean add(final TaskResultStatistics taskResultStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_TASK_RESULT_STATISTICS + "_" + taskResultStatistics.getStatisticInterval()
+                + "` (`success_count`, `failed_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, taskResultStatistics.getSuccessCount());
+            preparedStatement.setInt(2, taskResultStatistics.getFailedCount());
+            preparedStatement.setTimestamp(3, new Timestamp(taskResultStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(4, new Timestamp(taskResultStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert taskResultStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Add task running statistics.
+     *
+     * @param taskRunningStatistics task running statistics
+     * @return add success or not
+     */
+    public boolean add(final TaskRunningStatistics taskRunningStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_TASK_RUNNING_STATISTICS + "` (`running_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, taskRunningStatistics.getRunningCount());
+            preparedStatement.setTimestamp(2, new Timestamp(taskRunningStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(3, new Timestamp(taskRunningStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert taskRunningStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Add job running statistics.
+     *
+     * @param jobRunningStatistics job running statistics
+     * @return add success or not
+     */
+    public boolean add(final JobRunningStatistics jobRunningStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_RUNNING_STATISTICS + "` (`running_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, jobRunningStatistics.getRunningCount());
+            preparedStatement.setTimestamp(2, new Timestamp(jobRunningStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(3, new Timestamp(jobRunningStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert jobRunningStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Add job register statistics.
+     *
+     * @param jobRegisterStatistics job register statistics
+     * @return add success or not
+     */
+    public boolean add(final JobRegisterStatistics jobRegisterStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_REGISTER_STATISTICS + "` (`registered_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, jobRegisterStatistics.getRegisteredCount());
+            preparedStatement.setTimestamp(2, new Timestamp(jobRegisterStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(3, new Timestamp(jobRegisterStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert jobRegisterStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find task result statistics.
+     *
+     * @param from from date to statistics
+     * @param statisticInterval statistic interval
+     * @return task result statistics
+     */
+    public List<TaskResultStatistics> findTaskResultStatistics(final Date from, final StatisticInterval statisticInterval) {
+        List<TaskResultStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, success_count, failed_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                TaskResultStatistics taskResultStatistics = new TaskResultStatistics(resultSet.getLong(1), resultSet.getInt(2), resultSet.getInt(3), 
+                        statisticInterval, new Date(resultSet.getTimestamp(4).getTime()), new Date(resultSet.getTimestamp(5).getTime()));
+                result.add(taskResultStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch taskResultStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Get summed task result statistics.
+     *
+     * @param from from date to statistics
+     * @param statisticInterval statistic interval
+     * @return summed task result statistics
+     */
+    public TaskResultStatistics getSummedTaskResultStatistics(final Date from, final StatisticInterval statisticInterval) {
+        TaskResultStatistics result = new TaskResultStatistics(0, 0, statisticInterval, new Date());
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT sum(success_count), sum(failed_count) FROM %s WHERE statistics_time >= '%s'", 
+                TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new TaskResultStatistics(resultSet.getInt(1), resultSet.getInt(2), statisticInterval, new Date());
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch summed taskResultStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find latest task result statistics.
+     *
+     * @param statisticInterval statistic interval
+     * @return task result statistics
+     */
+    public Optional<TaskResultStatistics> findLatestTaskResultStatistics(final StatisticInterval statisticInterval) {
+        TaskResultStatistics result = null;
+        String sql = String.format("SELECT id, success_count, failed_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new TaskResultStatistics(resultSet.getLong(1), resultSet.getInt(2), resultSet.getInt(3), 
+                        statisticInterval, new Date(resultSet.getTimestamp(4).getTime()), new Date(resultSet.getTimestamp(5).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest taskResultStatistics from DB error:", ex);
+        }
+        return Optional.fromNullable(result);
+    }
+
+    /**
+     * Find task running statistics.
+     *
+     * @param from from date to statistics
+     * @return Task running statistics
+     */
+    public List<TaskRunningStatistics> findTaskRunningStatistics(final Date from) {
+        List<TaskRunningStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_TASK_RUNNING_STATISTICS, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                TaskRunningStatistics taskRunningStatistics = new TaskRunningStatistics(resultSet.getLong(1), resultSet.getInt(2), 
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+                result.add(taskRunningStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch taskRunningStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find job running statistics.
+     *
+     * @param from from date to statistics
+     * @return job running statistics
+     */
+    public List<JobRunningStatistics> findJobRunningStatistics(final Date from) {
+        List<JobRunningStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_JOB_RUNNING_STATISTICS, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobRunningStatistics jobRunningStatistics = new JobRunningStatistics(resultSet.getLong(1), resultSet.getInt(2), 
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+                result.add(jobRunningStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch jobRunningStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find latest task running statistics.
+     *
+     * @return latest task running statistics
+     */
+    public Optional<TaskRunningStatistics> findLatestTaskRunningStatistics() {
+        TaskRunningStatistics result = null;
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_TASK_RUNNING_STATISTICS);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new TaskRunningStatistics(resultSet.getLong(1), resultSet.getInt(2), 
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest taskRunningStatistics from DB error:", ex);
+        }
+        return Optional.fromNullable(result);
+    }
+
+    /**
+     * Find latest job running statistics.
+     *
+     * @return job running statistics
+     */
+    public Optional<JobRunningStatistics> findLatestJobRunningStatistics() {
+        JobRunningStatistics result = null;
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_JOB_RUNNING_STATISTICS);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new JobRunningStatistics(resultSet.getLong(1), resultSet.getInt(2), 
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest jobRunningStatistics from DB error:", ex);
+        }
+        return Optional.fromNullable(result);
+    }
+
+    /**
+     * Find job register statistics.
+     *
+     * @param from from date to statistics
+     * @return job register statistics
+     */
+    public List<JobRegisterStatistics> findJobRegisterStatistics(final Date from) {
+        List<JobRegisterStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, registered_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_JOB_REGISTER_STATISTICS, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobRegisterStatistics jobRegisterStatistics = new JobRegisterStatistics(resultSet.getLong(1), resultSet.getInt(2), 
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+                result.add(jobRegisterStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch jobRegisterStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find latest job register statistics.
+     *
+     * @return job register statistics
+     */
+    public Optional<JobRegisterStatistics> findLatestJobRegisterStatistics() {
+        JobRegisterStatistics result = null;
+        String sql = String.format("SELECT id, registered_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_JOB_REGISTER_STATISTICS);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new JobRegisterStatistics(resultSet.getLong(1), resultSet.getInt(2), 
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest jobRegisterStatistics from DB error:", ex);
+        }
+        return Optional.fromNullable(result);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobExecutionTypeStatistics.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobExecutionTypeStatistics.java
new file mode 100755
index 0000000..706fe32
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobExecutionTypeStatistics.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.type.job;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Job execution type statistics.
+ */
+@Getter
+@AllArgsConstructor
+public final class JobExecutionTypeStatistics {
+    
+    private int transientJobCount;
+    
+    private int daemonJobCount;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobRegisterStatistics.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobRegisterStatistics.java
new file mode 100755
index 0000000..bf62a2a
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobRegisterStatistics.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.type.job;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * Job register statistics.
+ */
+@Getter
+@RequiredArgsConstructor
+@AllArgsConstructor
+public final class JobRegisterStatistics {
+    
+    private long id;
+    
+    private final int registeredCount;
+    
+    private final Date statisticsTime;
+    
+    private Date creationTime = new Date();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobRunningStatistics.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobRunningStatistics.java
new file mode 100755
index 0000000..dc74a66
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobRunningStatistics.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.type.job;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * Job running statistics.
+ */
+@Getter
+@RequiredArgsConstructor
+@AllArgsConstructor
+public final class JobRunningStatistics {
+    
+    private long id;
+    
+    private final int runningCount;
+    
+    private final Date statisticsTime;
+    
+    private Date creationTime = new Date();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobTypeStatistics.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobTypeStatistics.java
new file mode 100755
index 0000000..679c0e0
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/job/JobTypeStatistics.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.type.job;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Job type statistics.
+ */
+@Getter
+@AllArgsConstructor
+public final class JobTypeStatistics {
+    
+    private int scriptJobCount;
+    
+    private int simpleJobCount;
+    
+    private int dataflowJobCount;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/task/TaskResultStatistics.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/task/TaskResultStatistics.java
new file mode 100755
index 0000000..fb3045e
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/task/TaskResultStatistics.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.type.task;
+
+import org.apache.shardingsphere.elasticjob.cloud.statistics.StatisticInterval;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * Task result statistics.
+ */
+@Getter
+@AllArgsConstructor
+@RequiredArgsConstructor
+public final class TaskResultStatistics {
+    
+    private long id;
+    
+    private final int successCount;
+    
+    private final int failedCount;
+    
+    private final StatisticInterval statisticInterval;
+    
+    private final Date statisticsTime;
+    
+    private Date creationTime = new Date();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/task/TaskRunningStatistics.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/task/TaskRunningStatistics.java
new file mode 100755
index 0000000..b90af6c
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/statistics/type/task/TaskRunningStatistics.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.statistics.type.task;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * Task running statistics.
+ */
+@Getter
+@RequiredArgsConstructor
+@AllArgsConstructor
+public final class TaskRunningStatistics {
+    
+    private long id;
+    
+    private final int runningCount;
+    
+    private final Date statisticsTime;
+    
+    private Date creationTime = new Date();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/concurrent/BlockUtils.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/concurrent/BlockUtils.java
new file mode 100755
index 0000000..556a26a
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/concurrent/BlockUtils.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.concurrent;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class BlockUtils {
+
+    /**
+     * Wait for short time.
+     */
+    public static void waitingShortTime() {
+        sleep(100L);
+    }
+
+    /**
+     * Sleep for millis.
+     * @param millis the time for sleep
+     */
+    public static void sleep(final long millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (final InterruptedException ex) {
+            Thread.currentThread().interrupt();
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/concurrent/ExecutorServiceObject.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/concurrent/ExecutorServiceObject.java
new file mode 100755
index 0000000..c40980b
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/concurrent/ExecutorServiceObject.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.concurrent;
+
+import com.google.common.base.Joiner;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Executor service object.
+ */
+public final class ExecutorServiceObject {
+    
+    private final ThreadPoolExecutor threadPoolExecutor;
+    
+    private final BlockingQueue<Runnable> workQueue;
+    
+    public ExecutorServiceObject(final String namingPattern, final int threadSize) {
+        workQueue = new LinkedBlockingQueue<>();
+        threadPoolExecutor = new ThreadPoolExecutor(threadSize, threadSize, 5L, TimeUnit.MINUTES, workQueue, 
+                new BasicThreadFactory.Builder().namingPattern(Joiner.on("-").join(namingPattern, "%s")).build());
+        threadPoolExecutor.allowCoreThreadTimeOut(true);
+    }
+
+    /**
+     * Create executor service.
+     *
+     * @return executor service
+     */
+    public ExecutorService createExecutorService() {
+        return MoreExecutors.listeningDecorator(MoreExecutors.getExitingExecutorService(threadPoolExecutor));
+    }
+
+    /**
+     * Whether the threadPoolExecutor has been shut down.
+     *
+     * @return Whether the threadPoolExecutor has been shut down
+     */
+    public boolean isShutdown() {
+        return threadPoolExecutor.isShutdown();
+    }
+
+    /**
+     * Get active thread count.
+     *
+     * @return active thread count
+     */
+    public int getActiveThreadCount() {
+        return threadPoolExecutor.getActiveCount();
+    }
+
+    /**
+     * Get work queue size.
+     *
+     * @return work queue size
+     */
+    public int getWorkQueueSize() {
+        return workQueue.size();
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/config/ShardingItemParameters.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/config/ShardingItemParameters.java
new file mode 100755
index 0000000..93caf15
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/config/ShardingItemParameters.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.config;
+
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobConfigurationException;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Sharding item parameters.
+ */
+@Getter
+public final class ShardingItemParameters {
+    
+    private static final String PARAMETER_DELIMITER = ",";
+    
+    private static final String KEY_VALUE_DELIMITER = "=";
+    
+    private final Map<Integer, String> map;
+    
+    public ShardingItemParameters(final String shardingItemParameters) {
+        map = toMap(shardingItemParameters);
+    }
+    
+    private Map<Integer, String> toMap(final String originalShardingItemParameters) {
+        if (Strings.isNullOrEmpty(originalShardingItemParameters)) {
+            return Collections.emptyMap();
+        }
+        String[] shardingItemParameters = originalShardingItemParameters.split(PARAMETER_DELIMITER);
+        Map<Integer, String> result = new HashMap<>(shardingItemParameters.length);
+        for (String each : shardingItemParameters) {
+            ShardingItem shardingItem = parse(each, originalShardingItemParameters);
+            result.put(shardingItem.item, shardingItem.parameter);
+        }
+        return result;
+    }
+    
+    private ShardingItem parse(final String shardingItemParameter, final String originalShardingItemParameters) {
+        String[] pair = shardingItemParameter.trim().split(KEY_VALUE_DELIMITER);
+        if (2 != pair.length) {
+            throw new JobConfigurationException("Sharding item parameters '%s' format error, should be int=xx,int=xx", originalShardingItemParameters);
+        }
+        try {
+            return new ShardingItem(Integer.parseInt(pair[0].trim()), pair[1].trim());
+        } catch (final NumberFormatException ex) {
+            throw new JobConfigurationException("Sharding item parameters key '%s' is not an integer.", pair[0]);
+        }
+    }
+
+    /**
+     * Sharding item.
+     */
+    @AllArgsConstructor
+    private static final class ShardingItem {
+        
+        private final int item;
+        
+        private final String parameter;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/config/ShardingItems.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/config/ShardingItems.java
new file mode 100755
index 0000000..0709968
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/config/ShardingItems.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.config;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Sharding items.
+ */
+@Getter
+public final class ShardingItems {
+    
+    private static final String DELIMITER = ",";
+
+    /**
+     * Get sharding items via string.
+     *
+     * @param itemsString sharding items string
+     * @return sharding items
+     */
+    public static List<Integer> toItemList(final String itemsString) {
+        if (Strings.isNullOrEmpty(itemsString)) {
+            return Collections.emptyList();
+        }
+        String[] items = itemsString.split(DELIMITER);
+        List<Integer> result = new ArrayList<>(items.length);
+        for (String each : items) {
+            int item = Integer.parseInt(each);
+            if (!result.contains(item)) {
+                result.add(item);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Get sharding items string.
+     *
+     * @param items sharding items
+     * @return sharding items string
+     */
+    public static String toItemsString(final List<Integer> items) {
+        return items.isEmpty() ? "" : Joiner.on(DELIMITER).join(items);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/digest/Encryption.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/digest/Encryption.java
new file mode 100755
index 0000000..17fb18b
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/digest/Encryption.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.digest;
+
+import org.apache.shardingsphere.elasticjob.cloud.exception.JobSystemException;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * Encryption.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class Encryption {
+    
+    private static final String MD5 = "MD5";
+
+    /**
+     * Use md5 to encrypt string.
+     *
+     * @param str string to be encrypted
+     * @return encrypted string
+     */
+    public static String md5(final String str) {
+        try {
+            MessageDigest messageDigest = MessageDigest.getInstance(MD5);
+            messageDigest.update(str.getBytes());
+            return new BigInteger(1, messageDigest.digest()).toString(16);
+        } catch (final NoSuchAlgorithmException ex) {
+            throw new JobSystemException(ex);
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/HostException.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/HostException.java
new file mode 100755
index 0000000..d786762
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/HostException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.env;
+
+import java.io.IOException;
+
+/**
+ * Host exception.
+ */
+public final class HostException extends RuntimeException {
+    
+    private static final long serialVersionUID = 3589264847881174997L;
+    
+    public HostException(final IOException cause) {
+        super(cause);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/IpUtils.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/IpUtils.java
new file mode 100755
index 0000000..6e2d1ae
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/IpUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.env;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Enumeration;
+
+/**
+ * IP address utility.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class IpUtils {
+
+    public static final String IP_REGEX = "((\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})";
+    
+    private static volatile String cachedIpAddress;
+
+    /**
+     * Get IP address for localhost.
+     *
+     * @return IP address for localhost
+     */
+    public static String getIp() {
+        if (null != cachedIpAddress) {
+            return cachedIpAddress;
+        }
+        Enumeration<NetworkInterface> netInterfaces;
+        try {
+            netInterfaces = NetworkInterface.getNetworkInterfaces();
+        } catch (final SocketException ex) {
+            throw new HostException(ex);
+        }
+        String localIpAddress = null;
+        while (netInterfaces.hasMoreElements()) {
+            NetworkInterface netInterface = netInterfaces.nextElement();
+            Enumeration<InetAddress> ipAddresses = netInterface.getInetAddresses();
+            while (ipAddresses.hasMoreElements()) {
+                InetAddress ipAddress = ipAddresses.nextElement();
+                if (isPublicIpAddress(ipAddress)) {
+                    String publicIpAddress = ipAddress.getHostAddress();
+                    cachedIpAddress = publicIpAddress;
+                    return publicIpAddress;
+                }
+                if (isLocalIpAddress(ipAddress)) {
+                    localIpAddress = ipAddress.getHostAddress();
+                }
+            }
+        }
+        cachedIpAddress = localIpAddress;
+        return localIpAddress;
+    }
+    
+    private static boolean isPublicIpAddress(final InetAddress ipAddress) {
+        return !ipAddress.isSiteLocalAddress() && !ipAddress.isLoopbackAddress() && !isV6IpAddress(ipAddress);
+    }
+    
+    private static boolean isLocalIpAddress(final InetAddress ipAddress) {
+        return ipAddress.isSiteLocalAddress() && !ipAddress.isLoopbackAddress() && !isV6IpAddress(ipAddress);
+    }
+    
+    private static boolean isV6IpAddress(final InetAddress ipAddress) {
+        return ipAddress.getHostAddress().contains(":");
+    }
+
+    /**
+     * Get host name for localhost.
+     *
+     * @return host name for localhost
+     */
+    public static String getHostName() {
+        try {
+            return InetAddress.getLocalHost().getHostName();
+        } catch (final UnknownHostException ex) {
+            return "unknown";
+        }
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/TimeService.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/TimeService.java
new file mode 100755
index 0000000..d8fc2c7
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/env/TimeService.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.env;
+
+/**
+ * Time service.
+ */
+public final class TimeService {
+
+    /**
+     * Get current millis.
+     *
+     * @return current millis
+     */
+    public long getCurrentMillis() {
+        return System.currentTimeMillis();
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/json/AbstractJobConfigurationGsonTypeAdapter.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/json/AbstractJobConfigurationGsonTypeAdapter.java
new file mode 100755
index 0000000..c7652cc
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/json/AbstractJobConfigurationGsonTypeAdapter.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.json;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import org.apache.shardingsphere.elasticjob.cloud.api.JobType;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobTypeConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.script.ScriptJobConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobCoreConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.JobRootConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.dataflow.DataflowJobConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.config.simple.SimpleJobConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.JobProperties;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Job configuration gson type adapter.
+ *
+ * @param <T> type of job root configuration
+ */
+public abstract class AbstractJobConfigurationGsonTypeAdapter<T extends JobRootConfiguration> extends TypeAdapter<T> {
+    
+    @Override
+    public T read(final JsonReader in) throws IOException {
+        String jobName = "";
+        String cron = "";
+        int shardingTotalCount = 0;
+        String shardingItemParameters = "";
+        String jobParameter = "";
+        boolean failover = false;
+        boolean misfire = failover;
+        String description = "";
+        JobProperties jobProperties = new JobProperties();
+        JobType jobType = null;
+        String jobClass = "";
+        boolean streamingProcess = false;
+        String scriptCommandLine = "";
+        Map<String, Object> customizedValueMap = new HashMap<>(32, 1);
+        in.beginObject();
+        while (in.hasNext()) {
+            String jsonName = in.nextName();
+            switch (jsonName) {
+                case "jobName":
+                    jobName = in.nextString();
+                    break;
+                case "cron":
+                    cron = in.nextString();
+                    break;
+                case "shardingTotalCount":
+                    shardingTotalCount = in.nextInt();
+                    break;
+                case "shardingItemParameters":
+                    shardingItemParameters = in.nextString();
+                    break;
+                case "jobParameter":
+                    jobParameter = in.nextString();
+                    break;
+                case "failover":
+                    failover = in.nextBoolean();
+                    break;
+                case "misfire":
+                    misfire = in.nextBoolean();
+                    break;
+                case "description":
+                    description = in.nextString();
+                    break;
+                case "jobProperties":
+                    jobProperties = getJobProperties(in);
+                    break;
+                case "jobType":
+                    jobType = JobType.valueOf(in.nextString());
+                    break;
+                case "jobClass":
+                    jobClass = in.nextString();
+                    break;
+                case "streamingProcess":
+                    streamingProcess = in.nextBoolean();
+                    break;
+                case "scriptCommandLine":
+                    scriptCommandLine = in.nextString();
+                    break;
+                default:
+                    addToCustomizedValueMap(jsonName, in, customizedValueMap);
+                    break;
+            }
+        }
+        in.endObject();
+        JobCoreConfiguration coreConfig = getJobCoreConfiguration(jobName, cron, shardingTotalCount, shardingItemParameters,
+                jobParameter, failover, misfire, description, jobProperties);
+        JobTypeConfiguration typeConfig = getJobTypeConfiguration(coreConfig, jobType, jobClass, streamingProcess, scriptCommandLine);
+        return getJobRootConfiguration(typeConfig, customizedValueMap);
+    }
+    
+    private JobProperties getJobProperties(final JsonReader in) throws IOException {
+        JobProperties result = new JobProperties();
+        in.beginObject();
+        while (in.hasNext()) {
+            switch (in.nextName()) {
+                case "job_exception_handler":
+                    result.put(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER.getKey(), in.nextString());
+                    break;
+                case "executor_service_handler":
+                    result.put(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER.getKey(), in.nextString());
+                    break;
+                default:
+                    break;
+            }
+        }
+        in.endObject();
+        return result;
+    }
+    
+    protected abstract void addToCustomizedValueMap(String jsonName, JsonReader in, Map<String, Object> customizedValueMap) throws IOException;
+    
+    private JobCoreConfiguration getJobCoreConfiguration(final String jobName, final String cron, final int shardingTotalCount,
+                                                         final String shardingItemParameters, final String jobParameter, final boolean failover,
+                                                         final boolean misfire, final String description,
+                                                         final JobProperties jobProperties) {
+        return JobCoreConfiguration.newBuilder(jobName, cron, shardingTotalCount)
+                .shardingItemParameters(shardingItemParameters).jobParameter(jobParameter).failover(failover).misfire(misfire).description(description)
+                .jobProperties(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER.getKey(), jobProperties.get(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER))
+                .jobProperties(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER.getKey(), jobProperties.get(JobProperties.JobPropertiesEnum.EXECUTOR_SERVICE_HANDLER))
+                .build();
+    }
+    
+    private JobTypeConfiguration getJobTypeConfiguration(
+            final JobCoreConfiguration coreConfig, final JobType jobType, final String jobClass, final boolean streamingProcess, final String scriptCommandLine) {
+        Preconditions.checkNotNull(jobType, "jobType cannot be null.");
+        switch (jobType) {
+            case SIMPLE:
+                Preconditions.checkArgument(!Strings.isNullOrEmpty(jobClass), "jobClass cannot be empty.");
+                return new SimpleJobConfiguration(coreConfig, jobClass);
+            case DATAFLOW:
+                Preconditions.checkArgument(!Strings.isNullOrEmpty(jobClass), "jobClass cannot be empty.");
+                return new DataflowJobConfiguration(coreConfig, jobClass, streamingProcess);
+            case SCRIPT:
+                return new ScriptJobConfiguration(coreConfig, scriptCommandLine);
+            default:
+                throw new UnsupportedOperationException(String.valueOf(jobType));
+        }
+    }
+    
+    protected abstract T getJobRootConfiguration(JobTypeConfiguration typeConfig, Map<String, Object> customizedValueMap);
+    
+    @Override
+    public void write(final JsonWriter out, final T value) throws IOException {
+        out.beginObject();
+        out.name("jobName").value(value.getTypeConfig().getCoreConfig().getJobName());
+        out.name("jobClass").value(value.getTypeConfig().getJobClass());
+        out.name("jobType").value(value.getTypeConfig().getJobType().name());
+        out.name("cron").value(value.getTypeConfig().getCoreConfig().getCron());
+        out.name("shardingTotalCount").value(value.getTypeConfig().getCoreConfig().getShardingTotalCount());
+        out.name("shardingItemParameters").value(value.getTypeConfig().getCoreConfig().getShardingItemParameters());
+        out.name("jobParameter").value(value.getTypeConfig().getCoreConfig().getJobParameter());
+        out.name("failover").value(value.getTypeConfig().getCoreConfig().isFailover());
+        out.name("misfire").value(value.getTypeConfig().getCoreConfig().isMisfire());
+        out.name("description").value(value.getTypeConfig().getCoreConfig().getDescription());
+        out.name("jobProperties").jsonValue(value.getTypeConfig().getCoreConfig().getJobProperties().json());
+        if (value.getTypeConfig().getJobType() == JobType.DATAFLOW) {
+            DataflowJobConfiguration dataflowJobConfig = (DataflowJobConfiguration) value.getTypeConfig();
+            out.name("streamingProcess").value(dataflowJobConfig.isStreamingProcess());
+        } else if (value.getTypeConfig().getJobType() == JobType.SCRIPT) {
+            ScriptJobConfiguration scriptJobConfig = (ScriptJobConfiguration) value.getTypeConfig();
+            out.name("scriptCommandLine").value(scriptJobConfig.getScriptCommandLine());
+        }
+        writeCustomized(out, value);
+        out.endObject();
+    }
+    
+    protected abstract void writeCustomized(JsonWriter out, T value) throws IOException;
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/json/GsonFactory.java b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/json/GsonFactory.java
new file mode 100755
index 0000000..6297965
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/main/java/org/apache/shardingsphere/elasticjob/cloud/util/json/GsonFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.util.json;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapter;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.lang.reflect.Type;
+
+/**
+ * Gson factory.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class GsonFactory {
+    
+    private static final GsonBuilder GSON_BUILDER = new GsonBuilder();
+    
+    private static volatile Gson gson = GSON_BUILDER.create();
+
+    /**
+     * Register type adapter.
+     *
+     * @param type Gson type
+     * @param typeAdapter Gson type adapter
+     */
+    public static synchronized void registerTypeAdapter(final Type type, final TypeAdapter typeAdapter) {
+        GSON_BUILDER.registerTypeAdapter(type, typeAdapter);
+        gson = GSON_BUILDER.create();
+    }
+
+    /**
+     * Get gson instance.
+     *
+     * @return gson instance
+     */
+    public static Gson getGson() {
+        return gson;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/AllCoreTests.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/AllCoreTests.java
new file mode 100755
index 0000000..4251621
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/AllCoreTests.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud;
+
+import org.apache.shardingsphere.elasticjob.cloud.api.AllApiTests;
+import org.apache.shardingsphere.elasticjob.cloud.executor.AllExecutorTests;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.AllStatisticsTests;
+import org.apache.shardingsphere.elasticjob.cloud.config.AllConfigTests;
+import org.apache.shardingsphere.elasticjob.cloud.context.AllContextTests;
+import org.apache.shardingsphere.elasticjob.cloud.event.AllEventTests;
+import org.apache.shardingsphere.elasticjob.cloud.exception.AllExceptionTests;
+import org.apache.shardingsphere.elasticjob.cloud.reg.AllRegTests;
+import org.apache.shardingsphere.elasticjob.cloud.util.AllUtilTests;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({
+        AllRegTests.class,
+        AllContextTests.class,
+        AllApiTests.class,
+        AllConfigTests.class,
+        AllExecutorTests.class,
+        AllEventTests.class,
+        AllExceptionTests.class,
+        AllStatisticsTests.class,
+        AllUtilTests.class
+    })
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class AllCoreTests {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/api/AllApiTests.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/api/AllApiTests.java
new file mode 100755
index 0000000..312f511
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/api/AllApiTests.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses(ShardingContextTest.class)
+public final class AllApiTests {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/api/ShardingContextTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/api/ShardingContextTest.java
new file mode 100755
index 0000000..72a082a
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/api/ShardingContextTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.api;
+
+import org.apache.shardingsphere.elasticjob.cloud.executor.ShardingContexts;
+import org.apache.shardingsphere.elasticjob.cloud.fixture.ShardingContextsBuilder;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Test;
+
+public final class ShardingContextTest {
+    
+    @Test
+    public void assertNew() {
+        ShardingContexts shardingContexts = ShardingContextsBuilder.getMultipleShardingContexts();
+        ShardingContext actual = new ShardingContext(shardingContexts, 1);
+        Assert.assertThat(actual.getJobName(), Is.is(shardingContexts.getJobName()));
+        Assert.assertThat(actual.getTaskId(), Is.is(shardingContexts.getTaskId()));
+        Assert.assertThat(actual.getShardingTotalCount(), Is.is(shardingContexts.getShardingTotalCount()));
+        Assert.assertThat(actual.getJobParameter(), Is.is(shardingContexts.getJobParameter()));
+        Assert.assertThat(actual.getShardingItem(), Is.is(1));
+        Assert.assertThat(actual.getShardingParameter(), Is.is(shardingContexts.getShardingItemParameters().get(1)));
+    }
+    
+    @Test
+    public void assertToString() {
+        Assert.assertThat(new ShardingContext(ShardingContextsBuilder.getMultipleShardingContexts(), 1).toString(),
+                Is.is("ShardingContext(jobName=test_job, taskId=fake_task_id, shardingTotalCount=2, jobParameter=, shardingItem=1, shardingParameter=B)"));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/config/AllConfigTests.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/config/AllConfigTests.java
new file mode 100755
index 0000000..6044682
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/config/AllConfigTests.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses(JobCoreConfigurationTest.class)
+public final class AllConfigTests {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/config/JobCoreConfigurationTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/config/JobCoreConfigurationTest.java
new file mode 100755
index 0000000..32df8f1
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/config/JobCoreConfigurationTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.config;
+
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.impl.DefaultJobExceptionHandler;
+import org.apache.shardingsphere.elasticjob.cloud.fixture.handler.IgnoreJobExceptionHandler;
+import org.apache.shardingsphere.elasticjob.cloud.executor.handler.JobProperties;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Test;
+
+public final class JobCoreConfigurationTest {
+    
+    @Test
+    public void assertBuildAllProperties() {
+        JobCoreConfiguration actual = JobCoreConfiguration.newBuilder("test_job", "0/1 * * * * ?", 3)
+                .shardingItemParameters("0=a,1=b,2=c").jobParameter("param").failover(true).misfire(false).description("desc")
+                .jobProperties("job_exception_handler", IgnoreJobExceptionHandler.class.getName()).build();
+        assertRequiredProperties(actual);
+        Assert.assertThat(actual.getShardingItemParameters(), Is.is("0=a,1=b,2=c"));
+        Assert.assertThat(actual.getJobParameter(), Is.is("param"));
+        Assert.assertTrue(actual.isFailover());
+        Assert.assertFalse(actual.isMisfire());
+        Assert.assertThat(actual.getDescription(), Is.is("desc"));
+        Assert.assertThat(actual.getJobProperties().get(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER), Is.is(IgnoreJobExceptionHandler.class.getName()));
+    }
+    
+    @Test
+    public void assertBuildRequiredProperties() {
+        JobCoreConfiguration actual = JobCoreConfiguration.newBuilder("test_job", "0/1 * * * * ?", 3).build();
+        assertRequiredProperties(actual);
+        assertDefaultValues(actual);
+    }
+    
+    @Test
+    public void assertBuildWhenOptionalParametersIsNull() {
+        //noinspection NullArgumentToVariableArgMethod
+        JobCoreConfiguration actual = JobCoreConfiguration.newBuilder("test_job", "0/1 * * * * ?", 3).shardingItemParameters(null).jobParameter(null).description(null).build();
+        assertRequiredProperties(actual);
+        assertDefaultValues(actual);
+    }
+    
+    private void assertRequiredProperties(final JobCoreConfiguration actual) {
+        Assert.assertThat(actual.getJobName(), Is.is("test_job"));
+        Assert.assertThat(actual.getCron(), Is.is("0/1 * * * * ?"));
+        Assert.assertThat(actual.getShardingTotalCount(), Is.is(3));
+    }
+    
+    private void assertDefaultValues(final JobCoreConfiguration actual) {
+        Assert.assertThat(actual.getShardingItemParameters(), Is.is(""));
+        Assert.assertThat(actual.getJobParameter(), Is.is(""));
+        Assert.assertFalse(actual.isFailover());
+        Assert.assertTrue(actual.isMisfire());
+        Assert.assertThat(actual.getDescription(), Is.is(""));
+        Assert.assertThat(actual.getJobProperties().get(JobProperties.JobPropertiesEnum.JOB_EXCEPTION_HANDLER), Is.is(DefaultJobExceptionHandler.class.getName()));
+    }
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void assertBuildWhenJobNameIsNull() {
+        JobCoreConfiguration.newBuilder(null, "0/1 * * * * ?", 3).build();
+    }
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void assertBuildWhenCronIsNull() {
+        JobCoreConfiguration.newBuilder("test_job", null, 3).build();
+    }
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void assertBuildWhenTotalSHardingCountIsNegative() {
+        JobCoreConfiguration.newBuilder(null, "0/1 * * * * ?", -1).build();
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/context/AllContextTests.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/context/AllContextTests.java
new file mode 100755
index 0000000..aeaabed
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/context/AllContextTests.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.context;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses(TaskContextTest.class)
+public final class AllContextTests {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/context/TaskContextTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/context/TaskContextTest.java
new file mode 100755
index 0000000..84ab679
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/context/TaskContextTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.context;
+
+import com.google.common.collect.Lists;
+import org.apache.shardingsphere.elasticjob.cloud.fixture.context.TaskNode;
+import org.hamcrest.core.Is;
+import org.hamcrest.core.StringStartsWith;
+import org.junit.Assert;
+import org.junit.Test;
+
+public final class TaskContextTest {
+    
+    @Test
+    public void assertNew() {
+        TaskContext actual = new TaskContext("test_job", Lists.newArrayList(0), ExecutionType.READY, "slave-S0");
+        Assert.assertThat(actual.getMetaInfo().getJobName(), Is.is("test_job"));
+        Assert.assertThat(actual.getMetaInfo().getShardingItems().get(0), Is.is(0));
+        Assert.assertThat(actual.getType(), Is.is(ExecutionType.READY));
+        Assert.assertThat(actual.getSlaveId(), Is.is("slave-S0"));
+        Assert.assertThat(actual.getId(), StringStartsWith.startsWith(TaskNode.builder().build().getTaskNodeValue().substring(0, TaskNode.builder().build().getTaskNodeValue().length() - 1)));
+    }
+    
+    @Test
+    public void assertNewWithoutSlaveId() {
+        TaskContext actual = new TaskContext("test_job", Lists.newArrayList(0), ExecutionType.READY);
+        Assert.assertThat(actual.getSlaveId(), Is.is("unassigned-slave"));
+    }
+    
+    @Test
+    public void assertGetMetaInfo() {
+        TaskContext actual = new TaskContext("test_job", Lists.newArrayList(0), ExecutionType.READY, "slave-S0");
+        Assert.assertThat(actual.getMetaInfo().toString(), Is.is("test_job@-@0"));
+    }
+    
+    @Test
+    public void assertTaskContextFrom() {
+        TaskContext actual = TaskContext.from(TaskNode.builder().build().getTaskNodeValue());
+        Assert.assertThat(actual.getId(), Is.is(TaskNode.builder().build().getTaskNodeValue()));
+        Assert.assertThat(actual.getMetaInfo().getJobName(), Is.is("test_job"));
+        Assert.assertThat(actual.getMetaInfo().getShardingItems().get(0), Is.is(0));
+        Assert.assertThat(actual.getType(), Is.is(ExecutionType.READY));
+        Assert.assertThat(actual.getSlaveId(), Is.is("slave-S0"));
+    }
+    
+    @Test
+    public void assertMetaInfoFromWithMetaInfo() {
+        TaskContext.MetaInfo actual = TaskContext.MetaInfo.from("test_job@-@1");
+        Assert.assertThat(actual.getJobName(), Is.is("test_job"));
+        Assert.assertThat(actual.getShardingItems().get(0), Is.is(1));
+    }
+    
+    @Test
+    public void assertMetaInfoFromWithTaskId() {
+        TaskContext.MetaInfo actual = TaskContext.MetaInfo.from("test_job@-@1@-@READY@-@unassigned-slave@-@0");
+        Assert.assertThat(actual.getJobName(), Is.is("test_job"));
+        Assert.assertThat(actual.getShardingItems().get(0), Is.is(1));
+    }
+    
+    @Test
+    public void assertMetaInfoFromWithMetaInfoWithoutShardingItems() {
+        TaskContext.MetaInfo actual = TaskContext.MetaInfo.from("test_job@-@");
+        Assert.assertThat(actual.getJobName(), Is.is("test_job"));
+        Assert.assertTrue(actual.getShardingItems().isEmpty());
+    }
+    
+    @Test
+    public void assertMetaInfoFromWithTaskIdWithoutShardingItems() {
+        TaskContext.MetaInfo actual = TaskContext.MetaInfo.from("test_job@-@@-@READY@-@unassigned-slave@-@0");
+        Assert.assertThat(actual.getJobName(), Is.is("test_job"));
+        Assert.assertTrue(actual.getShardingItems().isEmpty());
+    }
+    
+    @Test
+    public void assertGetIdForUnassignedSlave() {
+        Assert.assertThat(TaskContext.getIdForUnassignedSlave("test_job@-@0@-@READY@-@slave-S0@-@0"), Is.is("test_job@-@0@-@READY@-@unassigned-slave@-@0"));
+    }
+    
+    @Test
+    public void assertGetTaskName() {
+        TaskContext actual = TaskContext.from(TaskNode.builder().build().getTaskNodeValue());
+        Assert.assertThat(actual.getTaskName(), Is.is("test_job@-@0@-@READY@-@slave-S0"));
+    }
+    
+    @Test
+    public void assertGetExecutorId() {
+        TaskContext actual = TaskContext.from(TaskNode.builder().build().getTaskNodeValue());
+        Assert.assertThat(actual.getExecutorId("app"), Is.is("app@-@slave-S0"));
+    }
+    
+    @Test
+    public void assertSetSlaveId() {
+        TaskContext actual = new TaskContext("test_job", Lists.newArrayList(0), ExecutionType.READY, "slave-S0");
+        Assert.assertThat(actual.getSlaveId(), Is.is("slave-S0"));
+        actual.setSlaveId("slave-S1");
+        Assert.assertThat(actual.getSlaveId(), Is.is("slave-S1"));
+    }
+    
+    @Test
+    public void assertSetIdle() {
+        TaskContext actual = new TaskContext("test_job", Lists.newArrayList(0), ExecutionType.READY, "slave-S0");
+        Assert.assertFalse(actual.isIdle());
+        actual.setIdle(true);
+        Assert.assertTrue(actual.isIdle());
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/AllEventTests.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/AllEventTests.java
new file mode 100755
index 0000000..d50c85c
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/AllEventTests.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.rdb.JobEventRdbConfigurationTest;
+import org.apache.shardingsphere.elasticjob.cloud.event.rdb.JobEventRdbIdentityTest;
+import org.apache.shardingsphere.elasticjob.cloud.event.rdb.JobEventRdbListenerTest;
+import org.apache.shardingsphere.elasticjob.cloud.event.rdb.JobEventRdbSearchTest;
+import org.apache.shardingsphere.elasticjob.cloud.event.rdb.JobEventRdbStorageTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+        JobExecutionEventTest.class, 
+        JobEventBusTest.class, 
+        JobEventRdbIdentityTest.class,
+        JobEventRdbConfigurationTest.class,
+        JobEventRdbListenerTest.class,
+        JobEventRdbStorageTest.class,
+        JobEventRdbSearchTest.class
+    })
+public final class AllEventTests {
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventBusTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventBusTest.java
new file mode 100755
index 0000000..a45ca39
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/JobEventBusTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+import com.google.common.eventbus.EventBus;
+import org.apache.shardingsphere.elasticjob.cloud.event.fixture.JobEventCaller;
+import org.apache.shardingsphere.elasticjob.cloud.event.fixture.TestJobEventConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.event.fixture.TestJobEventListener;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.fixture.TestJobEventFailureConfiguration;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.unitils.util.ReflectionUtils;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class JobEventBusTest {
+    
+    @Mock
+    private JobEventCaller jobEventCaller;
+    
+    @Mock
+    private EventBus eventBus;
+    
+    private JobEventBus jobEventBus;
+    
+    @Test
+    public void assertRegisterFailure() throws NoSuchFieldException {
+        jobEventBus = new JobEventBus(new TestJobEventFailureConfiguration());
+        assertIsRegistered(false);
+    }
+    
+    @Test
+    public void assertPost() throws InterruptedException, NoSuchFieldException {
+        jobEventBus = new JobEventBus(new TestJobEventConfiguration(jobEventCaller));
+        assertIsRegistered(true);
+        jobEventBus.post(new JobExecutionEvent("fake_task_id", "test_event_bus_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0));
+        while (!TestJobEventListener.isExecutionEventCalled()) {
+            Thread.sleep(100L);
+        }
+        Mockito.verify(jobEventCaller).call();
+    }
+    
+    @Test
+    public void assertPostWithoutListener() throws NoSuchFieldException {
+        jobEventBus = new JobEventBus();
+        assertIsRegistered(false);
+        ReflectionUtils.setFieldValue(jobEventBus, "eventBus", eventBus);
+        jobEventBus.post(new JobExecutionEvent("fake_task_id", "test_event_bus_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0));
+        Mockito.verify(eventBus, Mockito.times(0)).post(ArgumentMatchers.<JobEvent>any());
+    }
+    
+    private void assertIsRegistered(final boolean actual) throws NoSuchFieldException {
+        Assert.assertThat((boolean) ReflectionUtils.getFieldValue(jobEventBus, JobEventBus.class.getDeclaredField("isRegistered")), Is.is(actual));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/JobExecutionEventTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/JobExecutionEventTest.java
new file mode 100755
index 0000000..f5284c6
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/JobExecutionEventTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Test;
+
+public final class JobExecutionEventTest {
+    
+    @Test
+    public void assertNewJobExecutionEvent() {
+        JobExecutionEvent actual = new JobExecutionEvent("fake_task_id", "test_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
+        Assert.assertThat(actual.getJobName(), Is.is("test_job"));
+        Assert.assertThat(actual.getSource(), Is.is(JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER));
+        Assert.assertThat(actual.getShardingItem(), Is.is(0));
+        Assert.assertNotNull(actual.getHostname());
+        Assert.assertNotNull(actual.getStartTime());
+        Assert.assertNull(actual.getCompleteTime());
+        Assert.assertFalse(actual.isSuccess());
+        Assert.assertThat(actual.getFailureCause(), Is.is(""));
+    }
+    
+    @Test
+    public void assertExecutionSuccess() {
+        JobExecutionEvent startEvent = new JobExecutionEvent("fake_task_id", "test_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
+        JobExecutionEvent successEvent = startEvent.executionSuccess();
+        Assert.assertNotNull(successEvent.getCompleteTime());
+        Assert.assertTrue(successEvent.isSuccess());
+    }
+    
+    @Test
+    public void assertExecutionFailure() {
+        JobExecutionEvent startEvent = new JobExecutionEvent("fake_task_id", "test_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
+        JobExecutionEvent failureEvent = startEvent.executionFailure(new RuntimeException("failure"));
+        Assert.assertNotNull(failureEvent.getCompleteTime());
+        Assert.assertFalse(failureEvent.isSuccess());
+        Assert.assertThat(failureEvent.getFailureCause(), CoreMatchers.startsWith("java.lang.RuntimeException: failure"));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/JobEventCaller.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/JobEventCaller.java
new file mode 100755
index 0000000..d00cb41
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/JobEventCaller.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.fixture;
+
+public interface JobEventCaller {
+
+    /**
+     * Call method.
+     */
+    void call();
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventConfiguration.java
new file mode 100755
index 0000000..4f6cd5b
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.fixture;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListener;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListenerConfigurationException;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public final class TestJobEventConfiguration extends TestJobEventIdentity implements JobEventConfiguration {
+    
+    private final JobEventCaller jobEventCaller;
+    
+    @Override
+    public JobEventListener createJobEventListener() throws JobEventListenerConfigurationException {
+        return new TestJobEventListener(jobEventCaller);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventFailureConfiguration.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventFailureConfiguration.java
new file mode 100755
index 0000000..43decde
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventFailureConfiguration.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.fixture;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListener;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListenerConfigurationException;
+
+public final class TestJobEventFailureConfiguration extends TestJobEventIdentity implements JobEventConfiguration {
+    
+    @Override
+    public JobEventListener createJobEventListener() throws JobEventListenerConfigurationException {
+        throw new JobEventListenerConfigurationException(new RuntimeException("assert failure"));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventIdentity.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventIdentity.java
new file mode 100755
index 0000000..75bc221
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventIdentity.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.fixture;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventIdentity;
+
+public class TestJobEventIdentity implements JobEventIdentity {
+    
+    @Override
+    public String getIdentity() {
+        return "test";
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventListener.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventListener.java
new file mode 100755
index 0000000..096337d
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/fixture/TestJobEventListener.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.fixture;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListener;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public final class TestJobEventListener extends TestJobEventIdentity implements JobEventListener {
+    
+    @Getter
+    private static volatile boolean executionEventCalled;
+    
+    private final JobEventCaller jobEventCaller;
+    
+    @Override
+    public void listen(final JobExecutionEvent jobExecutionEvent) {
+        jobEventCaller.call();
+        executionEventCalled = true;
+    }
+    
+    @Override
+    public void listen(final JobStatusTraceEvent jobStatusTraceEvent) {
+        jobEventCaller.call();
+    }
+
+    /**
+     * Reset the event.
+     */
+    public static void reset() {
+        executionEventCalled = false;
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbConfigurationTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbConfigurationTest.java
new file mode 100755
index 0000000..b52d827
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbConfigurationTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListenerConfigurationException;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Test;
+
+public final class JobEventRdbConfigurationTest {
+    
+    @Test
+    public void assertGetDataSource() throws JobEventListenerConfigurationException {
+        BasicDataSource dataSource = new BasicDataSource();
+        dataSource.setDriverClassName(org.h2.Driver.class.getName());
+        dataSource.setUrl("jdbc:h2:mem:job_event_storage");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        Assert.assertThat((BasicDataSource) (new JobEventRdbConfiguration(dataSource).getDataSource()), Is.is(dataSource));
+    }
+    
+    @Test
+    public void assertCreateJobEventListenerSuccess() throws JobEventListenerConfigurationException {
+        BasicDataSource dataSource = new BasicDataSource();
+        dataSource.setDriverClassName(org.h2.Driver.class.getName());
+        dataSource.setUrl("jdbc:h2:mem:job_event_storage");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        Assert.assertThat(new JobEventRdbConfiguration(dataSource).createJobEventListener(), CoreMatchers.instanceOf(JobEventRdbListener.class));
+    }
+    
+    @Test(expected = JobEventListenerConfigurationException.class)
+    public void assertCreateJobEventListenerFailure() throws JobEventListenerConfigurationException {
+        new JobEventRdbConfiguration(new BasicDataSource()).createJobEventListener();
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbIdentityTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbIdentityTest.java
new file mode 100755
index 0000000..5a70e6a
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbIdentityTest.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Test;
+
+public final class JobEventRdbIdentityTest {
+    
+    @Test
+    public void assertGetIdentity() {
+        Assert.assertThat(new JobEventRdbIdentity().getIdentity(), Is.is("rdb"));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbListenerTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbListenerTest.java
new file mode 100755
index 0000000..93865a1
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbListenerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+        
+import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventBus;
+import org.apache.shardingsphere.elasticjob.cloud.event.JobEventListenerConfigurationException;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.unitils.util.ReflectionUtils;
+
+import java.sql.SQLException;
+
+import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class JobEventRdbListenerTest {
+    
+    private static final String JOB_NAME = "test_rdb_event_listener";
+    
+    @Mock
+    private JobEventRdbConfiguration jobEventRdbConfiguration;
+    
+    @Mock
+    private JobEventRdbStorage repository;
+    
+    private JobEventBus jobEventBus;
+    
+    @Before
+    public void setUp() throws JobEventListenerConfigurationException, SQLException, NoSuchFieldException {
+        BasicDataSource dataSource = new BasicDataSource();
+        dataSource.setDriverClassName(org.h2.Driver.class.getName());
+        dataSource.setUrl("jdbc:h2:mem:job_event_storage");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        JobEventRdbListener jobEventRdbListener = new JobEventRdbListener(dataSource);
+        ReflectionUtils.setFieldValue(jobEventRdbListener, "repository", repository);
+        when(jobEventRdbConfiguration.createJobEventListener()).thenReturn(jobEventRdbListener);
+        jobEventBus = new JobEventBus(jobEventRdbConfiguration);
+    }
+    
+    @Test
+    public void assertPostJobExecutionEvent() {
+        JobExecutionEvent jobExecutionEvent = new JobExecutionEvent("fake_task_id", JOB_NAME, JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
+        jobEventBus.post(jobExecutionEvent);
+        verify(repository, atMost(1)).addJobExecutionEvent(jobExecutionEvent);
+    }
+    
+    @Test
+    public void assertPostJobStatusTraceEvent() {
+        JobStatusTraceEvent jobStatusTraceEvent = new JobStatusTraceEvent(
+                JOB_NAME, "fake_task_id", "fake_slave_id", JobStatusTraceEvent.Source.LITE_EXECUTOR, ExecutionType.READY, "0", JobStatusTraceEvent.State.TASK_RUNNING, "message is empty.");
+        jobEventBus.post(jobStatusTraceEvent);
+        verify(repository, atMost(1)).addJobStatusTraceEvent(jobStatusTraceEvent);
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbSearchTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbSearchTest.java
new file mode 100755
index 0000000..a1b3b24
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbSearchTest.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class JobEventRdbSearchTest {
+    
+    private static JobEventRdbStorage storage;
+    
+    private static JobEventRdbSearch repository;
+    
+    @BeforeClass
+    public static void setUpClass() throws SQLException {
+        BasicDataSource dataSource = new BasicDataSource();
+        dataSource.setDriverClassName(org.h2.Driver.class.getName());
+        dataSource.setUrl("jdbc:h2:mem:");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        storage = new JobEventRdbStorage(dataSource);
+        repository = new JobEventRdbSearch(dataSource);
+        initStorage();
+    }
+    
+    private static void initStorage() {
+        for (int i = 1; i <= 500; i++) {
+            JobExecutionEvent startEvent = new JobExecutionEvent("fake_task_id", "test_job_" + i, JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
+            storage.addJobExecutionEvent(startEvent);
+            if (i % 2 == 0) {
+                JobExecutionEvent successEvent = startEvent.executionSuccess();
+                storage.addJobExecutionEvent(successEvent);
+            }
+            storage.addJobStatusTraceEvent(
+                    new JobStatusTraceEvent("test_job_" + i, "fake_failed_failover_task_id", "fake_slave_id", 
+                            JobStatusTraceEvent.Source.LITE_EXECUTOR, ExecutionType.FAILOVER, "0", JobStatusTraceEvent.State.TASK_FAILED, "message is empty."));
+        }
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithPageSizeAndNumber() {
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(50, 1, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(50));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(100, 5, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(100));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(100, 6, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(0));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithErrorPageSizeAndNumber() {
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(-1, -1, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithSort() {
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, "jobName", "ASC", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        assertThat(result.getRows().get(0).getJobName(), is("test_job_1"));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, "jobName", "DESC", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        assertThat(result.getRows().get(0).getJobName(), is("test_job_99"));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithErrorSort() {
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, "jobName", "ERROR_SORT", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        assertThat(result.getRows().get(0).getJobName(), is("test_job_1"));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, "notExistField", "ASC", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithTime() {
+        Date now = new Date();
+        Date tenMinutesBefore = new Date(now.getTime() - 10 * 60 * 1000);
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, tenMinutesBefore, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, now, null, null));
+        assertThat(result.getTotal(), is(0));
+        assertThat(result.getRows().size(), is(0));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, tenMinutesBefore, null));
+        assertThat(result.getTotal(), is(0));
+        assertThat(result.getRows().size(), is(0));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, now, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, tenMinutesBefore, now, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithFields() {
+        Map<String, Object> fields = new HashMap<>();
+        fields.put("isSuccess", "1");
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, fields));
+        assertThat(result.getTotal(), is(250));
+        assertThat(result.getRows().size(), is(10));
+        fields.put("isSuccess", null);
+        fields.put("jobName", "test_job_1");
+        result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, fields));
+        assertThat(result.getTotal(), is(1));
+        assertThat(result.getRows().size(), is(1));
+    }
+    
+    @Test
+    public void assertFindJobExecutionEventsWithErrorFields() {
+        Map<String, Object> fields = new HashMap<>();
+        fields.put("notExistField", "some value");
+        JobEventRdbSearch.Result<JobExecutionEvent> result = repository.findJobExecutionEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, fields));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithPageSizeAndNumber() {
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(50, 1, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(50));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(100, 5, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(100));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(100, 6, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(0));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithErrorPageSizeAndNumber() {
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(-1, -1, null, null, null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithSort() {
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, "jobName", "ASC", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        assertThat(result.getRows().get(0).getJobName(), is("test_job_1"));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, "jobName", "DESC", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        assertThat(result.getRows().get(0).getJobName(), is("test_job_99"));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithErrorSort() {
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, "jobName", "ERROR_SORT", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        assertThat(result.getRows().get(0).getJobName(), is("test_job_1"));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, "notExistField", "ASC", null, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithTime() {
+        Date now = new Date();
+        Date tenMinutesBefore = new Date(now.getTime() - 10 * 60 * 1000);
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, tenMinutesBefore, null, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, now, null, null));
+        assertThat(result.getTotal(), is(0));
+        assertThat(result.getRows().size(), is(0));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, tenMinutesBefore, null));
+        assertThat(result.getTotal(), is(0));
+        assertThat(result.getRows().size(), is(0));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, now, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+        result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, tenMinutesBefore, now, null));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithFields() {
+        Map<String, Object> fields = new HashMap<>();
+        fields.put("jobName", "test_job_1");
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, fields));
+        assertThat(result.getTotal(), is(1));
+        assertThat(result.getRows().size(), is(1));
+    }
+    
+    @Test
+    public void assertFindJobStatusTraceEventsWithErrorFields() {
+        Map<String, Object> fields = new HashMap<>();
+        fields.put("notExistField", "some value");
+        JobEventRdbSearch.Result<JobStatusTraceEvent> result = repository.findJobStatusTraceEvents(new JobEventRdbSearch.Condition(10, 1, null, null, null, null, fields));
+        assertThat(result.getTotal(), is(500));
+        assertThat(result.getRows().size(), is(10));
+    }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbStorageTest.java b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbStorageTest.java
new file mode 100755
index 0000000..c549576
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-common/src/test/java/org/apache/shardingsphere/elasticjob/cloud/event/rdb/JobEventRdbStorageTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.event.rdb;
+
+import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
+import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.SQLException;
+import java.util.List;
+
+public class JobEventRdbStorageTest {
+    
+    private JobEventRdbStorage storage;
+    
+    @Before
+    public void setup() throws SQLException {
+        BasicDataSource dataSource = new BasicDataSource();
+        dataSource.setDriverClassName(org.h2.Driver.class.getName());
+        dataSource.setUrl("jdbc:h2:mem:job_event_storage");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        storage = new JobEventRdbStorage(dataSource);
+    }
+    
+    @Test
+    public void assertAddJobExecutionEvent() throws SQLException {
+        Assert.assertTrue(storage.addJobExecutionEvent(new JobExecutionEvent("fake_task_id", "test_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0)));
+    }
+    
+    @Test
+    public void assertAddJobStatusTraceEvent() throws SQLException {
+        Assert.assertTrue(storage.addJobStatusTraceEvent(new JobStatusTraceEvent("test_job", "fake_task_id", "fake_slave_id", JobStatusTraceEvent.Source.LITE_EXECUTOR, ExecutionType.READY, "0",
+                JobStatusTraceEvent.State.TASK_RUNNING, "message is empty.")));
+    }
+    
+    @Test
+    public void assertAddJobStatusTraceEventWhenFailoverWithTaskStagingState() throws SQLException {
+        JobStatusTraceEvent jobStatusTraceEvent = new JobStatusTraceEvent("test_job", "fake_failover_task_id", "fake_slave_id", JobStatusTraceEvent.Source.LITE_EXECUTOR, ExecutionType.FAILOVER, "0",
+                JobStatusTraceEvent.State.TASK_STAGING, "message is empty.");
+        jobStatusTraceEvent.setOriginalTaskId("original_fake_failover_task_id");
+        Assert.assertThat(storage.getJobStatusTraceEvents("fake_failover_task_id").size(), Is.is(0));
+        storage.addJobStatusTraceEvent(jobStatusTraceEvent);
+        Assert.assertThat(storage.getJobStatusTraceEvents("fake_failover_task_id").size(), Is.is(1));
+    }
+    
+    @Test
+    public void assertAddJobStatusTraceEventWhenFailoverWithTaskFailedState() throws SQLException {
+        JobStatusTraceEvent stagingJobStatusTraceEvent = new JobStatusTraceEvent("test_job", "fake_failed_failover_task_id", "fake_slave_id", JobStatusTraceEvent.Source.LITE_EXECUTOR,
+                ExecutionType.FAILOVER, "0", JobStatusTraceEvent.State.TASK_STAGING, "message is empty.");
+        stagingJobStatusTraceEvent.setOriginalTaskId("original_fake_failed_failover_task_id");
+        storage.addJobStatusTraceEvent(stagingJobStatusTraceEvent);
+        JobStatusTraceEvent failedJobStatusTraceEvent = new JobStatusTraceEvent("test_job", "fake_failed_failover_task_id", "fake_slave_id", JobStatusTraceEvent.Source.LITE_EXECUTOR,
+                ExecutionType.FAILOVER, "0", JobStatusTraceEvent.State.TASK_FAILED, "message is empty.");
+        storage.addJobStatusTraceEvent(failedJobStatusTraceEvent);
+        List<JobStatusTraceEvent> jobStatusTraceEvents = storage.getJobStatusTraceEvents("fake_failed_failover_task_id");
+        Assert.assertThat(jobStatusTraceEvents.size(), Is.is(2));
+        for (JobStatusTraceEvent jobStatusTraceEvent : jobStatusTraceEvents) {
... 54144 lines suppressed ...