开发者社区> 杰克.陈> 正文

【Quartz】持久化到数据库【五】

简介: 原文:【Quartz】持久化到数据库【五】   前言     我们做到这里已经对Quartz定时器组件已经是学会了基本的使用了。但是我们有没有想过任务开启之后万一断掉了,当机了我们怎么办,你是否还想继续执行原先的任务。
+关注继续查看
原文:【Quartz】持久化到数据库【五】

  前言

    我们做到这里已经对Quartz定时器组件已经是学会了基本的使用了。但是我们有没有想过任务开启之后万一断掉了,当机了我们怎么办,你是否还想继续执行原先的任务。我们普通的创建是把任务放在内存中存储,如果内存被释放掉,任务也就消失了,那怎么办哪,不得不说这个组件还是很厉害的。他已经帮我们想过了解方案---就是放到数据库。

  Quartz插一嘴:

    quartz在任务中分为两种:有状态和无状态执行。

    有状态:对于同一个 trigger 来说,有状态的 job 不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。所有我自己理解为串行的顺序执行(自己怎么好记怎么理解 哈哈)

   无状态:无状态任务一般指可以并发的任务,即任务之间是独立的,不会互相干扰。就是各自干各自的。

数据库概貌:

    首先上一下sql脚本下载地址:sql数据库rar文件下载

 表结构瞅一瞅:

下面是表代表的大致意思吧:

 

表名

描述

QRTZ_BLOB_TRIGGERS

作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候)

QRTZ_CALENDARS

以 Blob 类型存储 Quartz 的 Calendar 信息

QRTZ_CRON_TRIGGERS

存储 Cron Trigger,包括 Cron 表达式和时区信息

QRTZ_FIRED_TRIGGERS

存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息

QRTZ_JOB_DETAILS

存储每一个已配置的 Job 的详细信息

QRTZ_LOCKS

存储程序的非观锁的信息(假如使用了悲观锁)

QRTZ_PAUSED_TRIGGER_GRPS

存储已暂停的 Trigger 组的信息

QRTZ_SCHEDULER_STATE

存储少量的有关 Scheduler 的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)

QRTZ_SIMPLE_TRIGGERS

存储简单的 Trigger,包括重复次数,间隔,以及已触的次数

QRTZ_SIMPROP_TRIGGERS

 

QRTZ_TRIGGERS

存储已配置的 Trigger 的信息

 代码部分:

    工具都有了那就干活吧,既然我上面说了任务分为有状态和无状态,那正好借这个例子一起给介绍一下。首先还是我们的老朋友任务的创建:

这是一个无状态任务

 public class ServerJob : IJob
    {
        private const string Count = "count";
        public virtual void Execute(IJobExecutionContext context)
        {
            JobKey jobKey = context.JobDetail.Key;
            try
            {
                // 如果任务是恢复的任务的话
                if (context.Recovering)
                {
                    WritTxt.WriteFile("serversql", jobKey+":恢复打印");
                }
                else
                {
                    WritTxt.WriteFile("serversql", jobKey+":启动打印");
                }
                JobDataMap data = context.JobDetail.JobDataMap;
                int count;
                if (data.ContainsKey(Count))
                {
                    count = data.GetInt(Count);
                }
                else
                {
                    count = 0;
                }
                count++;
                data.Put(Count, count);

                WritTxt.WriteFile("serversql", string.Format("结束: {0} done at {1}\n 累计数 #{2}", jobKey, DateTime.Now.ToString("r"), count));
            }
            catch (Exception ex)
            {

            }
        }
    }

下面是一个有状态任务,因为本人比较懒所有就不写新任务了,直接继承了无状态任务事件。

    [PersistJobDataAfterExecution] //代表当前任务是否有状态
    [DisallowConcurrentExecution]//代表任务不允许并发
    public class ServerJobState : ServerJob
    {
    }

下面就是我们要说的重点了;数据库配置

只需要在实例化调度器前把我们的数据库配置传进去就好了。

/// <summary>
        /// 持久化属性
        /// </summary>
        NameValueCollection properties = new NameValueCollection();
        public ExampleServer()
        {       
            properties["quartz.scheduler.instanceName"] = "TestScheduler";
            properties["quartz.scheduler.instanceId"] = "instance_one";
            properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
            properties["quartz.threadPool.threadCount"] = "5";
            properties["quartz.threadPool.threadPriority"] = "Normal";
            properties["quartz.jobStore.misfireThreshold"] = "60000";
            properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
            properties["quartz.jobStore.useProperties"] = "false";
            properties["quartz.jobStore.dataSource"] = "default";
            properties["quartz.jobStore.tablePrefix"] = "QRTZ_";
            properties["quartz.jobStore.clustered"] = "true";
            properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";

            properties["quartz.dataSource.default.connectionString"] = "Server=(local);Database=quartz;Trusted_Connection=True;";
            properties["quartz.dataSource.default.provider"] = "SqlServer-20";

            // First we must get a reference to a scheduler
            ISchedulerFactory sf = new StdSchedulerFactory(properties);
            Scheduler = sf.GetScheduler();
        }

然后就是运行测试了,这里我用了不同的形式返回了调度器和调度工厂。这样子也挺好用的,可以把以前的那种方法改成这种。

 /// <summary>
        /// 调度工厂
        /// </summary>
        private static StdSchedulerFactory SchedulerFactory { get; set; }

        /// <summary>
        /// 调度接口
        /// </summary>
        private static IScheduler Scheduler { get; set; }


        #region 0.测试
        public void Run()
        {
            string schedId = Scheduler.SchedulerInstanceId;
            IJobDetail job = JobBuilder.Create<ServerJob>()
                           .WithIdentity("ServerJob", schedId)
                           .RequestRecovery()
                           .Build();


            ITrigger trigger = TriggerBuilder.Create()
                                          .WithIdentity("serverTrigger", schedId)
                                          .WithCronSchedule("0/10 * * * * ?")     //5秒执行一次
                                          .Build();
            //已存在就不重复添加
            try
            {
                Scheduler.ScheduleJob(job, trigger);
            }
            catch (Exception ex)
            {

            }
            IJobDetail jobState = JobBuilder.Create<ServerJobState>()
                           .WithIdentity("ServerJobSatte", schedId)
                           .RequestRecovery()
                           .Build();


            ITrigger triggerState = TriggerBuilder.Create()
                                          .WithIdentity("serverTriggerSatte", schedId)
                                          .WithCronSchedule("0/10 * * * * ?")     //5秒执行一次
                                          .Build();
            //已存在就不重复添加
            try
            {
                Scheduler.ScheduleJob(jobState, triggerState);
            }
            catch (Exception ex)
            {

            }
            //启动
            Scheduler.Start();

        }
        #endregion

最后就是大结局了,让我们看下运行结果吧:

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
再不懂时序就 OUT 啦!,DBengine 排名第一时序数据库,阿里云数据库 InfluxDB 正式商业化!
阿里云数据库 InfluxDB® 版已于近日正式启动商业化 。 InfluxDB 是 DBengine 网站时序数据库类目排名第一的数据库产品,广泛应用于互联网基础资源监控,容器监控,业务运营监控分析,物联网设备远程实时监控,工业安全生产监控,生产质量评估和故障回溯。
3248 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
19817 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
13775 0
SequoiaDB - 企业级NoSQL分布式大数据库
SequoiaDB 巨杉数据库是一款开源的金融级分布式关系型数据库,主要面对高并发联机交易型场景提供高性能、可靠稳定以及无限水平扩展的数据库服务。 用户可以在 SequoiaDB 巨杉数据库中创建多种类型的数据库实例,以满足上层不同应用程序各自的需求。
885 0
阿里云数据库Redis正式上线Tair持久存储系列 提供大规格命令级持久化能力的云上Redis服务
该自研产品打破了传统Redis中的数据只能在易失性存储上进行读写的刻板印象,针对客户不同业务阶段的数据存储要求与服务成本考量,全新实现了持久性更强、成本更低的KV数据库。
21452 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
18072 0
bboss持久层多数据源配置及多数据库事务控制使用方法
bboss持久层多数据源配置及使用方法,持久层框架及demo下载请参看文档:http://yin-bp.iteye.com/blog/1080824 1.配置多个数据源-poolman.xml 在classes类路径根目录下准备好dbcp.
813 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
24840 0
+关注
杰克.陈
一个安静的程序猿~
10427
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载