阿里云——数据传输服务DTS——数据订阅(旧版)监听到的数据解析

项目用到了阿里云的数据传输服务DTS,主要是数据监听。

参考文档:https://help.aliyun.com/document_detail/26647.html?spm=a2c4g.11186623.2.19.100e6099zLpsGv

用了一段时间,也踩了一些坑,现在做个总结。

数据过滤

DTS读取的是数据库的binlog文件,每秒一次,获取到的数据量是非常庞大的,但是这些数据并不都是我们需要的,尤其是心跳数据,如果不过滤的话,日志文件很快就爆炸。

过滤的方式很简单,只要增加一个判断语句即可。

"INSERT".equals(message.getRecord().getOpt().toString())

DTS的sdk提供为我们提供了以下过滤选项:

INSERT、UPDATE、DELETE、REPLACE、HEARTBEAT、CONSISTENCY_TEST、BEGIN、COMMIT、DDL、ROLLBACK、DML、UNKNOWN;

汉字编码

数据库设计的编码格式是utf8mb4,但是sdk默认数据的是utf8格式,输出的汉字乱码,需要转换。

 for (DataMessage.Record.Field field:fieldList) {
      String record = field.encoding;
      String vlaue = "";
      if (record.equals("utf8mb4")){
          vlaue= field.getValue().toString("utf8mb4");
      }else if (record.equals("utf8")){
          vlaue= field.getValue().toString("utf8");
      }else {
          vlaue= field.getValue().toString();
      }
      String type = field.getType().toString();
      String name = field.getFieldname();
      System.out.println("===========字段名:"+name+",字段类型:"+type+",字段编码:"+record+",字段数据:"+vlaue);
                                }

数据重复

DTS智能保证监听到的数据不丢失,但是不能保证不重复,需要自己进行判断。

每次消费数据后都保存消费位点数据。

String checkPoint  = message.getRecord().getCheckpoint();

消费新的数据前与之前的消费位点进行比对。

 public boolean equleCheckPoint(String checkPointOld,String checkPointYoung){
        //先比较文件后缀,同一个binlog文件的话再比较位点位置
        String[] checkPointOlds = checkPointOld.split("@");
        String[] checkPointYoungs = checkPointYoung.split("@");
        if (checkPointOlds[1].compareTo(checkPointYoungs[1])<=0){
            if (checkPointOlds[0].compareTo(checkPointYoungs[0])<0){
                return true;
            }
        }
        return false;
 }

日期格式

dts获取的所有数据都是String格式的,这也能理解,但是最不能理解的是它会把数据库中“2019-12-19”的数据输出为“2019:12:19”,非人哉。

 String dateString = "2019:12:19";
        String timeString = "10:55:12";
        String dateTimeString = "2019-12-19 10:55:12";
        String timeStampString = "1576726159654";
        //Date格式
        SimpleDateFormat dateSdf = new SimpleDateFormat("yyyy-MM-dd");
        dateString.replace(":", "-");
        try {
            Date date = dateSdf.parse(dateString);
        } catch (Exception e) {
            System.out.println("date格式转化失败");
        }
        //Time
        Time time = Time.valueOf(timeString);
        //DateTime
        try {
            Long timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateTimeString).getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //TimeStamp
        Timestamp timestamp = new Timestamp(Long.valueOf(timeStampString));

完整代码

 public void incremental() {
        studentMapper.deleteData2();
        try {
            logger.info("<=====================查询数据开始=============================>");
            /* 创建一个context */
            RegionContext context;
            context = new RegionContext();
            context.setUsePublicIp(true);
            context.setAccessKey(myak);
            context.setSecret(mysk);
            final ClusterClient client = new DefaultClusterClient(context);
            ClusterListener listener = new ClusterListener() {
                @Override
                public void notify(List<ClusterMessage> messages) throws Exception {
                    for (ClusterMessage message : messages) {
                        try {
                            //如果是INSERT类型的操作则获取监听到的数据
                            if ("INSERT".equals(message.getRecord().getOpt().toString())) {
                                //循环出一条sql中所有的字段信息
                                List<DataMessage.Record.Field> fieldList = message.getRecord().getFieldList();
                                /**
                                 * DTS返回的所有数据格式都是字符串形式的,如下数据在mysql中分别是Date,Time,DateTime,TimeStamp
                                 *
                                 *  String dateString = "2019:12:19";
                                 *  String timeString = "10:55:12";
                                 *  String dateTimeString = "2019-12-19 10:55:12";
                                 *  String timeStampString = "1576726159654";
                                 *
                                 */
                                String dataStr = fieldList.get(1).getValue().toString();
                                String timeStr = fieldList.get(2).getValue().toString();
                                String dateTimeStr = fieldList.get(3).getValue().toString();
                                String timeStampStr = fieldList.get(4).getValue().toString();
                                DateTimeEntity dateTimeEntity = new DateTimeEntity();
                                //Date格式
                                SimpleDateFormat dateSdf = new SimpleDateFormat("yyyy-MM-dd");
                                dataStr.replace(":", "-");
                                Date date;
                                try {
                                    date = dateSdf.parse(dataStr);
                                    dateTimeEntity.setMydate(date);
                                } catch (Exception e) {
                                    System.out.println("date格式转化失败");
                                }
                                //Time
                                dateTimeEntity.setMytime(Time.valueOf(timeStr));
                                //DateTime
                                Long timestamp = null;
                                try {
                                    timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateTimeStr).getTime();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                dateTimeEntity.setMydatetime(new Timestamp(timestamp));
                                //TimeStamp
                                dateTimeEntity.setMytimestamp(new Timestamp(Long.valueOf(timeStampStr)));
                                studentMapper.insertDataLocla(dateTimeEntity);
                                /**
                                 * 数据库如果设计的是utf8mb4格式,默认输出的汉字会乱码,需要转换
                                 *
                                 * */
                                for (DataMessage.Record.Field field:fieldList) {
                                    String record = field.encoding;
                                    String vlaue = "";
                                    if (record.equals("utf8mb4")){
                                        vlaue= field.getValue().toString("utf8mb4");
                                    }else if (record.equals("utf8")){
                                        vlaue= field.getValue().toString("utf8");
                                    }else {
                                        vlaue= field.getValue().toString();
                                    }
                                    String type = field.getType().toString();
                                    String name = field.getFieldname();
                                    System.out.println("===========字段名:"+name+",字段类型:"+type+",字段编码:"+record+",字段数据:"+vlaue);
                                }

                            } else {
                                System.out.println("》》》》》》》》》》》》》》》》》》没有数据变化");
                            }
                            /**
                             * 每条数据消费结束后必须给dts返回一个响应,此处指的是List<ClusterMessage> 中的所有message,而不能只限于自己需要的数据,否在消息堆积到4096条数据则sdk消费失败
                             * */
                             message.ackAsConsumed();
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                        }
                    }
                }

                @Override
                public void noException(Exception e) {
                    logger.warn("", e);
                }
            };
            /* 设置监听者 */
            client.addConcurrentListener(listener);
            /* 设置请求的guid */
            client.askForGUID(mysubID);
            /* 启动后台线程 */
            client.start();
        } catch (Exception e) {
            logger.info("<===========================查询失败==================================>");
            e.printStackTrace();
        }
    }

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值