小程聊微服务-数据抽取那点事(一)

本文涉及的产品
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 一、前言我们在《微服务是在双刃剑 http://www.jianshu.com/p/82ec12651d2d 》中提到了当我们将应用服务化以后,很多在单块系统中能够开展的数据统计和分析业务将会受到很大程度的影响,本文将延续上一篇文章深入分析服务化后,作为后端的数据统计和分析如何做。

一、前言

我们在《微服务是在双刃剑 http://www.jianshu.com/p/82ec12651d2d 》中提到了当我们将应用服务化以后,很多在单块系统中能够开展的数据统计和分析业务将会受到很大程度的影响,本文将延续上一篇文章深入分析服务化后,作为后端的数据统计和分析如何做。

注:本文的数据库是基于Oracle数据库

二、服务化后的现状分析

拿一个简单的快捷支付系统为例,服务化后的系统调用图如下所示:


image.png

通过上图我们可以看到,单块系统根据业务进行服务化后,每个系统功能单一、职责明确并且独立布署,这只是从系统的角度描述了服务化后的调用关系,那么从微服务的角度讲,还有一点是去中心化,也就是将数据库也按服务进行拆分,下图所示的正是每个服务与其对应的数据库间的关系。

image.png

上面我们可以看到,每个服务对应一个数据库,这样从上到下就已经全部拆分开了,再结合康威定律的理论,每个服务由一个团队负责管理,团队之间彼此协作和沟通。

三、数据抽取的技术选型

关于后台的数据统计需求,因为服务化后数据库已经拆分开,于是对后台数据统计造成了一定的困扰,针对这个问题我首先想到的是利用数据库同步来解决,将不同库或者表的数据统一汇总到一起。那么接下来,我将和大家一起逐步探讨和分析。

1、使用Oracle Golden Gate(简称OGG)工具

OGG的实现原理是抽取源端的redo log和archive log,然后通过TCP/IP协议投递到目标端,最后解析还原同步到目标端,使目标端实现源端的数据同步,如下图所示:

image.png
1.1 使用OGG的优点:

1、对生产系统影响小:实时读取交易日志,以低资源占用实现大交易量数据实时复制。
2、以交易为单位复制,保证交易一致性:只同步已提交的数据。
3、灵活的拓扑结构:支持一对一、一对多、多对一、多对多和双向复制等。
4、可以自定义基于表和行的过滤规则,可以对实时数据执行灵活影射和变换。

1.2 使用OGG需要注意的问题点:

1、在二个库之间做数据同步的时候,如果我们要在表中新加字段,必须要将OGG停下来加字段,然后再启动,新字段同步才会生效。
2、使用OGG做数据同步的时候,工具不是很稳定,经常会出现假死或者退出的情况。
3、OGG偶尔出现在同步过程中丢数据的时候。

2、使用Oracle Logminer

Logminer是oracle从8i开始提供的用于分析重做日志信息的工具,它包括DBMS_LOGMNR和DBMS_LOGMNR_D两个package,后边的D是字典的意思。它既能分析redo log file,也能分析归档后的archive log file。通过LogMiner可以跟踪Oracle数据库的所有DML、DDL和DCL操作。

2.1 使用LogMiner进行数据同步的框架图如下所示:
image.png
2.2 数据同步流程图如下所示:
image.png

同步流程说明:

通过指定源端、目标端数据库信息、LogMiner 同步时间等配置信息,获取源端同步数据。

1、通过定时轮询的方式检测是否到达数据同步时间,如果是则进行数据同步,否则继续进行轮询。
2、定时加载数据库归档日志文件到动态表 v$logmnr_contents 中。
3、根据条件读取指定 sql 语句。
4、执行 sql 语句。

基于JAVA写的LogMiner的数据同步部分核心代码如下所示:

try {
    ResultSet resultSet = null;
    // 获取源数据库连接
    sourceConn = DataBase.getSourceDataBase(); Statement statement = sourceConn.createStatement();
    // 添加所有日志文件,本代码仅分析联机日志 StringBuffer sbSQL = new StringBuffer(); sbSQL.append(" BEGIN");
    sbSQL.append("
    dbms_logmnr.add_logfile(logfilename=>'"+Constants.LOG_PATH+"\\REDO01.LOG', options=>dbms_logmnr.NEW);");
    sbSQL.append(" dbms_logmnr.add_logfile(logfilename=>'"+Constants.LOG_PATH+"\\REDO02.LOG', options=>dbms_logmnr.ADDFILE);");
    sbSQL.append(" dbms_logmnr.add_logfile(logfilename=>'"+Constants.LOG_PATH+"\\REDO03.LOG', options=>dbms_logmnr.ADDFILE);");
    sbSQL.append(" END;");
    CallableStatement callableStatement = sourceConn.prepareCall(sbSQL+""); callableStatement.execute();
    // 打印获分析日志文件信息
    resultSet = statement.executeQuery("SELECT db_name, thread_sqn, filename FROM v$logmnr_logs");

    while(resultSet.next()) {
        System.out.println("已添加日志文件==>"+resultSet.getObject(3)); 
    }

    System.out.println("开始分析日志文件,起始scn号:"+Constants.LAST_SCN);
    callableStatement = sourceConn.prepareCall("BEGINdbms_logmnr.start_logmnrstartScn=>'"+Constants.LAST_SCN+"',dictfilename=>'"+Constants.DATA_DICTIONARY+"\\dictionary.ora',OPTIONS =>DBMS_LOGMNR.COMMITTED_DATA_ONLY+dbms_logmnr.NO_ROWID_IN_STMT);END;");
    callableStatement.execute(); 
    System.out.println("完成分析日志文件");
    // 查询获取分析结果 System.out.println("查询分析结果"); 
    resultSet = statement.executeQuery("SELECT scn,operation,timestamp,status,sql_redo FROM v$logmnr_contents WHERE seg_owner='"+Constants.SOURCE_CLIENT_USERNAME+"' AND seg_type_name='TABLE' AND operation !='SELECT_FOR_UPDATE'");

    // 连接到目标数据库,在目标数据库执行redo语句
    targetConn = DataBase.getTargetDataBase();
    Statement targetStatement = targetConn.createStatement();
    String lastScn = Constants.LAST_SCN; String operation = null;
    String sql = null;
    boolean isCreateDictionary = false; while(resultSet.next()){
    lastScn = resultSet.getObject(1)+"";
    if( lastScn.equals(Constants.LAST_SCN) ) {
        continue; 
    }
    operation = resultSet.getObject(2)+""; 
    if( "DDL".equalsIgnoreCase(operation) ) {
        isCreateDictionary = true;
    }
    sql = resultSet.getObject(5)+"";
    // 替换用户
    sql = sql.replace("\""+Constants.SOURCE_CLIENT_USERNAME+"\".", ""); System.out.println("scn="+lastScn+",自动执行sql=="+sql+"");
    try {
        targetStatement.executeUpdate(sql.substring(0, sql.length()-1));
    } catch (Exception e) {
        System.out.println("测试一下,已经执行过了"); }
    }
    // 更新scn
    Constants.LAST_SCN = (Integer.parseInt(lastScn))+"";
    // DDL发生变化,更新数据字典 
    if( isCreateDictionary ){
        System.out.println("DDL发生变化,更新数据字典");
        createDictionary(sourceConn); 
        System.out.println("完成更新数据字典"); 
        isCreateDictionary = false;
    } 

    System.out.println("完成一个工作单元");
} finally {
    if( null != sourceConn ) { 
        sourceConn.close();
    } 
    if( null != targetConn ) {
        targetConn.close();
    }
    sourceConn = null;
    targetConn = null; 
    }
}
2.3 使用LogMiner做数据同步需要注意的点:

1、LogMiner是针对数据库级别的同步。
2、LogMiner工具的时效性较差,同步延时时间很长。
3、目标库必须与源库版本相同,或者比源库版本更高;目标库与源库字符集一致,或者是源库字符集的超集。
4、源数据库与目标库,必须运行在相同的硬件平台。
5、通过LogMiner方式获取日志的,通过oracle提供工具读取redo日志的信息,然后解析成SQL队列。有些特殊的数据类型,数据的变化是不记录到redo的,比如LOB字段的变化

3、总结

上面二种方案各有优缺点,但是实际工作中更需要同步延时小,同时稳定性极佳并且数据丢失率极低的方案,可以看到这二个方案并不适合做真正的数据抽取工具,来实现一个如下的方案:

image.png

在下一文中,我将结合工作实战为大家介绍一款高效的数据库同步工具,最终解决微服务实施中所带来的数据统计的痛点。

注:本文参考了 http://www.cnblogs.com/shishanyuan/p/3142788.html

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
4月前
|
SQL 数据库 微服务
微服务03,最简单的Demo,我们每个服务不能重复开发相同业务,微服务数据独立,不要访问其他微服务的数据库,微服务的特点之一是提供不能功能的数据库互相分割,微服务需要根据业务模块拆分,做到单一职责,
微服务03,最简单的Demo,我们每个服务不能重复开发相同业务,微服务数据独立,不要访问其他微服务的数据库,微服务的特点之一是提供不能功能的数据库互相分割,微服务需要根据业务模块拆分,做到单一职责,
|
4月前
|
消息中间件 Kafka 微服务
微服务数据问题之MetaQ设置同步异步刷盘如何解决
微服务数据问题之MetaQ设置同步异步刷盘如何解决
|
4月前
|
消息中间件 存储 微服务
微服务数据问题之异步刷盘如何解决
微服务数据问题之异步刷盘如何解决
|
2月前
|
存储 搜索推荐 数据库
MarkLogic在微服务架构中的应用:提供服务间通信和数据共享的机制
随着微服务架构的发展,服务间通信和数据共享成为关键挑战。本文介绍MarkLogic数据库在微服务架构中的应用,阐述其多模型支持、索引搜索、事务处理及高可用性等优势,以及如何利用MarkLogic实现数据共享、服务间通信、事件驱动架构和数据分析,提升系统的可伸缩性和可靠性。
49 5
|
3月前
|
安全 网络安全 数据安全/隐私保护
云原生技术探索:容器化与微服务架构的实践之路网络安全与信息安全:保护数据的关键策略
【8月更文挑战第28天】本文将深入探讨云原生技术的核心概念,包括容器化和微服务架构。我们将通过实际案例和代码示例,展示如何在云平台上实现高效的应用部署和管理。文章不仅提供理论知识,还包含实操指南,帮助开发者理解并应用这些前沿技术。 【8月更文挑战第28天】在数字化时代,网络安全和信息安全是保护个人和企业数据的前线防御。本文将探讨网络安全漏洞的成因、加密技术的应用以及提升安全意识的重要性。文章旨在通过分析网络安全的薄弱环节,介绍如何利用加密技术和提高用户警觉性来构建更为坚固的数据保护屏障。
|
3月前
|
Java 数据库连接 微服务
揭秘微服务架构下的数据魔方:Hibernate如何玩转分布式持久化,实现秒级响应的秘密武器?
【8月更文挑战第31天】微服务架构通过将系统拆分成独立服务,提升了可维护性和扩展性,但也带来了数据一致性和事务管理等挑战。Hibernate 作为强大的 ORM 工具,在微服务中发挥关键作用,通过二级缓存和分布式事务支持,简化了对象关系映射,并提供了有效的持久化策略。其二级缓存机制减少数据库访问,提升性能;支持 JTA 保证跨服务事务一致性;乐观锁机制解决并发数据冲突。合理配置 Hibernate 可助力构建高效稳定的分布式系统。
67 0
|
4月前
|
消息中间件 微服务
微服务数据问题之同步复制如何解决
微服务数据问题之同步复制如何解决
|
4月前
|
消息中间件 负载均衡 Kafka
微服务数据问题之Kafka实现高可用如何解决
微服务数据问题之Kafka实现高可用如何解决
|
4月前
|
消息中间件 存储 负载均衡
微服务数据问题之Kafka作为元数据节点如何解决
微服务数据问题之Kafka作为元数据节点如何解决
|
4月前
|
消息中间件 Kafka 索引
微服务数据问题之Broker宕机MetaQ保证数据的可靠性如何解决
微服务数据问题之Broker宕机MetaQ保证数据的可靠性如何解决
下一篇
无影云桌面