zoukankan      html  css  js  c++  java
  • 达梦数据库备份-Quartz定时任务备份

    定时任务备份为创建定时任务,定时的去备份数据库,使用quartz做定时任务(存在spring无法管理quartz类的问题),并将定时任务的信息保存到数据库实现定时任务的增删改查和数据还原,然后将备份代码集成到quartz中。

    代码中只实现table级别的备份,全局备份只是导出语句不同

    1. Quartz集成到springboot

      pom文件添加依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>

      quartz的配置类

    /**
     *  * 任务调度管理器  
     */
    @Configuration
    public class QuartzConfig {
    
        private MyJobFactory jobFactory;
    
        public QuartzConfig(MyJobFactory jobFactory) {
            this.jobFactory = jobFactory;
        }
    
        /**
         *  配置SchedulerFactoryBean     
         *  将一个方法产生为Bean并交给Spring容器管理
         */
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean() {
            // Spring提供SchedulerFactoryBean为Scheduler提供配置信息,并被Spring容器管理其生命周期
            SchedulerFactoryBean factory = new SchedulerFactoryBean();
            // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
            factory.setOverwriteExistingJobs(true);
            // 设置自定义Job Factory,用于Spring管理Job bean
            factory.setJobFactory(jobFactory);
            return factory;
        }
    
        @Bean(name = "scheduler")
        public Scheduler scheduler() {
            return schedulerFactoryBean().getScheduler();
        }
    }

      自定义job类

    @Component
    public class MyJobFactory extends AdaptableJobFactory {
        /**
         *  AutowireCapableBeanFactory接口是BeanFactory的子类      *
         * 可以连接和填充那些生命周期不被Spring管理的已存在的bean实例     
         */
        private AutowireCapableBeanFactory factory;
    
        public MyJobFactory(AutowireCapableBeanFactory factory) {
            this.factory = factory;
        }
    
        /**
         * 创建Job实例     
         */
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            // 实例化对象
            Object job = super.createJobInstance(bundle);
            // 进行注入(Spring管理该Bean)
            factory.autowireBean(job);
            // 返回对象
            return job;
        }
    }

      定时任务的工具类

    @Service
    public class SchedulerUtil {
    
        @Autowired
        private Scheduler scheduler;
    
        private final static Logger LOGGER = LoggerFactory.getLogger(SchedulerUtil.class);
    
        /**
         * @Description: 任务执行类
         */
        private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        private static String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";
        private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";
    
        /**
         * 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
         *
         * @param jobName 任务名
         * @param cls     任务
         * @param time    时间设置,参考quartz说明文档
         */
        public void addJob(String jobName, Class cls, String time, Map<String, Object> map) {
            try {
                // Scheduler scheduler = schedulerFactory.getScheduler();//创建一个触发器表
                JobDetail jobDetail = JobBuilder.newJob()// 创建一个jobbuilder用来定义一个任务明细。
                        .ofType(cls)// 设置类,将被实例化
                        .withIdentity(new JobKey(jobName, JOB_GROUP_NAME))// 使用给定的名称和默认组jobkey识别任务明细
                        .build();// 产品定义的JobDetail实例这jobbuilder。
    
                Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule(time))// 设置schedulebuilder将用于定义触发器的表。
                        .withIdentity(new TriggerKey(jobName, TRIGGER_GROUP_NAME)).build();// 创建Trigger
                TriggerKey triggerKey = trigger.getKey();
                JobKey jobKey = trigger.getJobKey();
                // 把保存triggerKey和jobKey
                map.put("triggerKey", triggerKey);
                map.put("jobKey", jobKey);
                map.put("jobname", jobName);
                jobDetail.getJobDataMap().put("canshu", map);
                scheduler.scheduleJob(jobDetail, trigger);// 绑定
                scheduler.start();
            } catch (Exception e) {
                LOGGER.error("添加定时任务失败", e.getMessage());
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
         *
         * @param jobName
         * @param time
       * @param map 业务参数,根据实际情况传参
    */ public void modifyJobTime(String jobName, String time, Map<String, Object> map, String jobkey, String triggerkey) { try { Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule(time))// 设置schedulebuilder将用于定义触发器的表。 .withIdentity(new TriggerKey(jobName, TRIGGER_GROUP_NAME)).build();// 创建Trigger if (trigger == null) { return; } removeJob(new TriggerKey(triggerkey), new JobKey(jobkey)); addJob(jobName, QuartzJob.class, time, map); } catch (Exception e) { LOGGER.error("添加定时任务失败", e.getMessage()); throw new RuntimeException(e); } } /** * 暂停一个任务(使用默认的任务组名,触发器名,触发器组名) * * @param triggerKey * @param jobKey */ public void pauseJob(TriggerKey triggerKey, JobKey jobKey) { try { scheduler.pauseTrigger(triggerKey);// 停止触发器 scheduler.pauseJob(jobKey); } catch (Exception e) { throw new RuntimeException(e); } } /** * 恢复一个任务(使用默认的任务组名,触发器名,触发器组名) * * @param triggerKey * @param jobKey */ public void resumeJob(TriggerKey triggerKey, JobKey jobKey) { try { scheduler.resumeTrigger(triggerKey); scheduler.resumeJob(jobKey); } catch (Exception e) { throw new RuntimeException(e); } } /** * 移除一个任务(使用默认的任务组名,触发器名,触发器组名) * * @param triggerKey * @param jobKey */ public void removeJob(TriggerKey triggerKey, JobKey jobKey) { try { scheduler.unscheduleJob(triggerKey);// 移除触发器 scheduler.deleteJob(jobKey); } catch (Exception e) { throw new RuntimeException(e); } } /** * 启动所有定时任务 */ public void startJobs() { try { Scheduler sched = schedulerFactory.getScheduler(); sched.start(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 关闭所有定时任务 */ public void shutdownJobs() { try { Scheduler sched = schedulerFactory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { throw new RuntimeException(e); } } }

    2. 备份集成到Quartz

      创建QuartzJob类实现备份功能

     

    /**
     * 任务类
     */
    @Service
    public class QuartzJob implements Job {
    
        @Autowired
        private BfbService bfbService;
    
        @Autowired
        private SjglSjbflbService sjglSjbflbService;
        @Autowired
        private SjglDsrwxxService sjglDsrwxxService;
    
        @Value("${dmdump.dev.password}")
        private String password;
    
        @Value("${dameng.dev.ip}")
        private String ip;
        @Value("${dameng.dev.userName}")
        private String userName;
        @Value("${dameng.dev.userPwd}")
        private String userPwd;
    
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            JobDataMap map = context.getJobDetail().getJobDataMap();
            Map<String, Object> data = (Map<String, Object>) map.get("canshu");
            String copyType = data.get("copyType").toString();
            System.out.println("备份地点:" + data.get("copyType"));
    
            // 拼接表名
            String tnames = data.get("tnames");
            String result = null;
            // 保存备份列表,备份文件名称=数据库id+T+时间
            SjglSjbflbParam param = new SjglSjbflbParam();
            param.setCjlx(copyType);
            // 获取服务器连接
            if (data.get("ip") != null && data.get("port") != null && data.get("user") != null && data.get("pwd") != null
                    && data.get("dir") != null) {
                param.setIp(data.get("ip").toString());
                param.setPort(data.get("port").toString());
                param.setUsername(data.get("user").toString());
                param.setUsername(data.get("user").toString());
                param.setRepassword(data.get("pwd").toString());
                param.setDir(data.get("dir").toString());
            }
            // 添加数据库备份列表数据
            String fname = data.get("jobname").toString();
            param.setDsrwxxid(Long.parseLong(fname.split("T")[0]));
            // param.setWjmc(fname);
            param.setCjz((Long) data.get("cjz"));
            StringBuffer tids = new StringBuffer();
            for (String s1 : (String[]) data.get("ids")) {
                tids.append(s1).append(",");
            }
            param.setTids(tids.toString().substring(0, tids.toString().length() - 1));
            param.setBflx("2");
            String filename = sjglSjbflbService.add(param);
            // 修改任务表中的jobkey和triggerKey
            SjglDsrwxxParam dsparam = new SjglDsrwxxParam();
            // 在定时任务表中添加keys字段
            sjglDsrwxxService.updateKeyByid(Long.parseLong(fname.split("T")[0]), data.get("triggerKey").toString(),
                    context.getJobDetail().getKey().toString());
            // 获取服务器连接
            Connection conn = DMruntimeUtil.login(ip, userName, userPwd);
            // 备份
            if (copyType.equals("local")) {
                String dexpStr = DMruntimeUtil.dumpByTables(data.get("hostip").toString(), data.get("dbname").toString(),
                        data.get("username").toString(), data.get("password").toString(), tnames, filename);
                String cmd = "cd /opt/dameng/dmdbms/bin;" + dexpStr;
                result = DMruntimeUtil.execute(conn, cmd);
            } else if (copyType.equals("foreignLands")) {
                // 调用shell脚本 sh dexplocal.sh test2 DEV.SYS_USER root@ip:/opt/data
                // pwd  22
                String cmd = "sh /opt/dameng/dmdbms/shelldata/dexphand.sh " + filename + " " + tnames + " "
                        + data.get("user") + "@" + data.get("ip") + ":" + data.get("dir") + " " + data.get("pwd") + " "
                        + data.get("port");
                result = DMruntimeUtil.execute(conn, cmd);
            }
            // return result;
        }
    
    }

        通过linux脚本实现异地备份,也可通过拼接命令实现

    #!/bin/bash                               //脚本声明                
    # 手动异城:方式备份EVAL.DEV数据          //注释信息
    cd /opt/dameng/dmdbms/bin
      
    filename=$1  
    tables=$2
    reurl=$3
    password=$4
    port=$5
    ./dexp USERID=SYSDBA/SYSDBA@ip:port FILE=${filename}.dmp LOG=${filename}.log TABLES=${tables} DIRECTORY=/opt/dameng/dmdbms/dm7data/EVAL/dexp  
      
    sshpass -p ${password} scp -P ${port} /opt/dameng/dmdbms/dm7data/EVAL/dexp/${filename}.dmp ${reurl}/${filename}.dmp  
    echo "success"
  • 相关阅读:
    Linux中Postfix邮件安装Maildrop(八)
    Linux中Postfix邮件WebMail配置(七)
    Linux中Postfix虚拟用户及虚拟域(六)
    Linux中Postfix邮件认证配置(五)
    Linux中Postfix邮件接收配置(四)
    Go构建工程入门1(了解即可,现在推荐使用Go module)
    Pod 启动流程详解
    Go Modules详解
    k8s 学习资源备忘录
    Kubernetes 架构及核心概念
  • 原文地址:https://www.cnblogs.com/yjwww/p/12126261.html
Copyright © 2011-2022 走看看