Cannal实现数据异构

问题:
在大型网站架构中,DB会采用分库分表来解决容量和性能的问题。但这带来个新的问题:比如不同维度的查询或者聚合查询
方案:
一般会通过数据异构机制来解决问题。

具体示例:
为提升系统的接单能力,需要对订单表进行分库分表,随之而来的问题:用户如何查询自己的订单列表?
方法1:扫描所有订单表,然后内存聚合,在大流量的架构中肯定是不行的;
方法2:双写,但是双写无法保证一致性;
方法3:订阅数据库变更日志,比如订阅mysql的binlog日志模拟数据库的主从同步机制,然后解析变更日志写到订单列表,从而实现数据异构,
这种机制也能保证数据的一致性。
比如,订单中心按照订单号分库分表,然后异构出:订单列表按照用户分库分表,商家订单,订单缓存,ES搜索

MYSQL主从复制
原理
--canal类似该原理



1.准备:
github:https://github.com/alibaba/canal
包括
1-canal的文档
2-server端
3-client端的
4-例子
5-源码包等等

2.canal概述
canal是应阿里巴巴存在杭州和美国的双机房部署,存在跨机房同步的业务需求而提出的。

早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,从此开启了一段新纪元。
说明:目前内部使用的同步,已经支持mysql5.x和Oracle部分版本的日志解析

canal server通过slave机制订阅数据库的binlong日志

基于日志增量订阅&消费支持的业务:
(1)数据库镜像
(2)数据库实时备份
(3)多级索引 (卖家和买家各自分库索引)
(4)search build
(5)业务cache刷新
(6)价格变化等重要业务消息

keyword:数据库同步,增量订阅&消费。


3.canal工作原理:
从上层来看,复制分成三步:
(1)  master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);
(2) slave将master的binary log events拷贝到它的中继日志(relay log);
(3) slave重做中继日志中的事件,将改变反映它自己的数据。


4.部署canal:
4.0 前提:
Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH.
需要安装JDK


4.1 部署canal-server:
4.1.1数据库配置:
开启MySQL的binlog功能,并配置binlog模式为row。

在my.cnf 加入如下:
vi /etc/my.cnf
[mysqld] 
log-bin=mysql-bin #开启二进制日志 
binlog-format=ROW #选择row模式  ,不要使用statement或者mix模式
server_id=1  #配置主数据库ID,不能和从数据库重复,即不能和canal的slaveId重复,配置mysql replaction需要定义
binlog提供的三种记录模式:
见书,在使用Canal时建议使用row模式

另外在MYSQL中执行"show binary logs",将看到当前有哪些二进制文件及其大小

4.1.2在mysql中 配置canal数据库管理用户,配置相应权限(repication权限)
CREATE USER canal IDENTIFIED BY 'canal';   
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%'; 
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ; 
FLUSH PRIVILEGES;
说明:一定要重启,否则不生效,避免类似这样的错误

4.1.3下载canal https://github.com/alibaba/canal/releases
并解压到相应文件夹,比如我下载的是canal.deployer-1.0.24.tar.gz
mkdir /usr/server/canal
cd /usr/server
tar -zxvf canal.tar.gz -C  canal

canal 文件目录结构
drwxr-xr-x 2 jianghang jianghang  136 2013-02-05 21:51 bin 
drwxr-xr-x 4 jianghang jianghang  160 2013-02-05 21:51 conf 
drwxr-xr-x 2 jianghang jianghang 1.3K 2013-02-05 21:51 lib 
drwxr-xr-x 2 jianghang jianghang   48 2013-02-05 21:29 logs 

4.1.4修改配置-canal的数据库实例 instance.properties
说明:这里可以使用已经存在的 example,也可以新起实例,这个名字和客户端java类中写的名字需要一致
这里我们新配置一个canal Server实例

// vi /usr/server/canal/conf/example/instance.properties 
mkdir -p /usr/server/canal/conf/product
cp /usr/server/canal/conf/example/instance.properties  /usr/server/canal/conf/product/
vi  /usr/server/canal/conf/product/instance.properties

################################################# 
## mysql serverId  必须和master的SQL的ID不一致
canal.instance.mysql.slaveId = 101 
 
# position info:连接的数据库地址,从哪个二进制文件,哪个位置开始 
canal.instance.master.address = 127.0.0.1:3306
# MYSQL主库连接时,起始的binlog文件
canal.instance.master.journal.name =
# MYSQL主库连接时,起始的binlog文件 偏移量  
canal.instance.master.position =
# MYSQL主库连接时,起始的binlog文件 时间戳
canal.instance.master.timestamp =  
 
#从库
#canal.instance.standby.address =  
#canal.instance.standby.journal.name = 
#canal.instance.standby.position =  
#canal.instance.standby.timestamp =  
 
# username/password,需要改成自己的数据库信息 
canal.instance.dbUsername = canal   
canal.instance.dbPassword = canal 
canal.instance.defaultDatabaseName = canal_test 
canal.instance.connectionCharset = UTF-8

# 通过如下配置过滤订阅的是 哪个库中的哪些表,减少不必要的订阅;
# 比如只关注产品数据库,通过如下模式可只订阅产品数据库
# table regex 
# canal.instance.filter.regex = .*\\..* 
  canal.instance.filter.regex = product_\d+\\.*
 
################################################# 

说明:若多个库订阅,则需要配置多个实例,为每个数据库配置一个配置文件


4.1.5 进行canal Server 的配置,修改conf/canal.properties
vi /usr/server/canal/conf/canal.properties

canal.id= 1
canal.ip=
canal.port= 11111
canal.zkServers=


# 当前canalserver上部署的实例,配置多个时用逗号分隔,此处配置product
canal.destinations= product

# 使用zk持久化模式,这样可以保证集群数据共享,共享HA
canal.instance.global.spring.xml = classpath:spring/default-instance.xml

4.1.5然后cd到bin目录  启动和停止canal-server
启动 
/usr/server/canal/bin/startup.sh & tail -f /usr/server/canal/logs/canal/canal.log

停止
/usr/server/canal/bin/stop.sh 

验证启动状态,查看log文件
tail -f /usr/server/canal/logs/canal/canal.log

2014-07-18 10:21:08.525 [main] INFO  com.alibaba.otter.canal.deployer.CanalLauncher - ## start the canal server. 
2014-07-18 10:21:08.609 [main] INFO  com.alibaba.otter.canal.deployer.CanalController - ## start the canal server[10.12.109.201:11111] 
2014-07-18 10:21:09.037 [main] INFO  com.alibaba.otter.canal.deployer.CanalLauncher - ## the canal server is running now ...... 
---> 上述日志信息显示启动canal成功


*********canal server 集群**************
canal server可以部署一台,也可以部署多台,但是只有一台是活跃的,其它的作为备机;canalserver的高可用是通过zk维护的。

需要安装:zookeeper

配置文件如下修改:
vi /usr/server/canal/conf/canal.properties

canal.id= 1
canal.ip=
canal.port= 11111
canal.zkServers=127.0.0.1:2181


4.2运行canal-client实例:
4.2.1 建立实例maven工程
mvn archetype:create -DgroupId=com.alibaba.otter -DartifactId=canal.sample 
[实践:手动创建Maven工程]

4.2.2 添加pom依赖:
<dependency> 
    <groupId>com.alibaba.otter</groupId> 
    <artifactId>canal.client</artifactId> 
    <version>1.0.12</version> 
</dependency> 

4.2.3 更新依赖 mvn install

4.2.4 ClientSamplet.Java 
实例代码
package canal.sample;
/**
 * Created by hp on 14-7-17.
 */ 
import java.net.InetSocketAddress; 
import java.util.List;
 
import com.alibaba.otter.canal.client.CanalConnector; 
import com.alibaba.otter.canal.common.utils.AddressUtils; 
import com.alibaba.otter.canal.protocol.Message; 
import com.alibaba.otter.canal.protocol.CanalEntry.Column; 
import com.alibaba.otter.canal.protocol.CanalEntry.Entry; 
import com.alibaba.otter.canal.protocol.CanalEntry.EntryType; 
import com.alibaba.otter.canal.protocol.CanalEntry.EventType; 
import com.alibaba.otter.canal.protocol.CanalEntry.RowChange; 
import com.alibaba.otter.canal.protocol.CanalEntry.RowData; 
import com.alibaba.otter.canal.client.*; 
import com.google.protobuf.InvalidProtocolBufferException;
//import org.jetbrains.annotations.NotNull;  
 
public class ClientSample { 
 
    public static void main(String args[]) throws Exception { 
        // 连接 canal Server 
        //CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(AddressUtils.getHostIp(), 
        CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("192.168.1.121",
                11111), "example", "", ""); 
                //11111), "chapter6", "", "");
       
        /**通过zk连接canal Server
        String zkServers = "192.168.1.121:2181";
        //目标实例:可以自定义一个,例如product
        String destination = "product";
        //连接 canal Server
        CanalConnector connector = CanalConnectors.newClusterConnector(zkServers, destination, "", "");
        **/
       
        int emptyCount = 0;  //空跑的次数
        int totalEmtryCount = 1200;//循环多少次为空时退出
        try { 
            connector.connect(); //连接
            connector.subscribe(".*\\..*"); //订阅所有,和不写此行一个效果
            //connector.subscribe("product_.*\\.product_.*");//订阅product数据库下的product表
            connector.rollback(); 
            while (emptyCount < totalEmtryCount) {
            //while(true){//一直循环
                //批量获取1000个日志(不确认模式)
                Message message = connector.getWithoutAck(1000);//这个值根据实际情况修改 
                long batchId = message.getId();
               
                //以下为空跑计数
                int size = message.getEntries().size(); 
                if (batchId == -1 || size == 0) { 
                    emptyCount++; 
                    System.out.println("empty count : " + emptyCount); 
                    try { 
                        Thread.sleep(1000); 
                    } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                    } 
                } else { 
                    emptyCount = 0;
                    //做数据处理
                    // System.out.printf("message[batchId=%s,size=%s] \n", batchId, size); 
                    printEntry(message.getEntries());
                } 
 
                connector.ack(batchId); // 提交确认 
                // connector.rollback(batchId); // 处理失败, 回滚数据 
            } 
 
            System.out.println("empty too many times, exit"); 
        } finally { 
            connector.disconnect(); 
        } 
    } 
 
    //private static void printEntry(@NotNull List<Entry> entrys) {
    private static void printEntry(List<Entry> entrys) throws InvalidProtocolBufferException {
        for (Entry entry : entrys) {
            if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) { 
                continue; 
            } 
 
            //如果是行数据
            if(entry.getEntryType() == EntryType.ROWDATA){
                //则解析行变更
                RowChange rowChage = null; 
                try { 
                    rowChage = RowChange.parseFrom(entry.getStoreValue()); 
                } catch (Exception e) { 
                    throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e); 
                } 
               
                EventType eventType = rowChage.getEventType();
                //这里捕获binlog变更信息
//                System.out.println(String.format("================> binlog[%s:%s] , name[%s,%s] , eventType : %s", 
//                        entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(), 
//                        entry.getHeader().getSchemaName(), entry.getHeader().getTableName(), 
//                        eventType));
               
                for (RowData rowData : rowChage.getRowDatasList()) {
                    //如果是删除,则获取删除的数据进行业务处理
                    if (eventType == EventType.DELETE) { 
                        printColumn(rowData.getBeforeColumnsList());
                        //List<Column> columns = rowData.getBeforeColumnsList();
                        //delete(columns);
                       
                    //如果是新增修改则获取新增修改数据进行处理
                    } else if (eventType == EventType.INSERT || eventType == eventType.UPDATE) { 
                        //printColumn(rowData.getAfterColumnsList()); 
                        List<Column> columns = rowData.getAfterColumnsList();
                        save(columns);
                       
                    } else { 
                        System.out.println("-------> before"); 
                        printColumn(rowData.getBeforeColumnsList()); 
                        System.out.println("-------> after"); 
                        printColumn(rowData.getAfterColumnsList()); 
                    } 
                }                
               
            }
           
        } 
    } 
   
    //新增的异构操作
    private static void save(List<Column> columns) {
        for (Column col:columns) {
            String name = col.getName();
            String value = col.getValue();
            System.out.println("name: "+ name + ",value:" + value);
           
            //name: uid,value:4
            //name: name,value:10
        }
       
    }

    //private static void printColumn(@NotNull List<Column> columns) { 
    private static void printColumn(List<Column> columns) { 
        for (Column column : columns) { 
            System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated()); 
        } 
    } 

报错[有个jar包没找到注释掉了]
import org.jetbrains.annotations.NotNull;

通过以上代码,捕获数据库日志变更,然后进行相关业务的处理。无论是数据异构还是缓存更新


4.2.5 运行java实例

启动后看到控制端信息:
empty count : 1 
empty count : 2 
empty count : 3 
empty count : 4 


4.2.6触发数据库变更
create table test ( 
    uid int (4) primary key not null auto_increment, 
    name varchar(10) not null
); 
 
insert into test (name) values('10'); 


4.2.7 client 抓取mysql信息:
================> binlog[mysql-bin.000016:3281] , name[canal_test,test] , eventType : INSERT 
uid : 7    update=false 
name : 10    update=false 
empty count : 1 
empty count : 2 

[发现没有捕获到信息]
tail -f /usr/server/canal/logs/example/example.log

2017-06-03 13:11:28.802 [destination = chapter6 , address = /127.0.0.1:3306 , EventParser] WARN  c.a.otter.canal.parse.inbound.mysql.MysqlEventParser - prepare to find start position just show master status
2017-06-03 13:11:28.817 [destination = chapter6 , address = /127.0.0.1:3306 , EventParser] ERROR c.a.otter.canal.parse.inbound.mysql.MysqlEventParser - dump address /127.0.0.1:3306 has an error, retrying. caused by
com.alibaba.otter.canal.parse.exception.CanalParseException: command : 'show master status' has an error! pls check. you need (at least one of) the SUPER,REPLICATION CLIENT privilege(s) for this operation
2017-06-03 13:11:28.820 [destination = chapter6 , address = /127.0.0.1:3306 , EventParser] ERROR com.alibaba.otter.canal.common.alarm.LogAlarmHandler - destination:chapter6[com.alibaba.otter.canal.parse.exception.CanalParseException: command : 'show master status' has an error! pls check. you need (at least one of) the SUPER,REPLICATION CLIENT privilege(s) for this operation
]

原因很简单:因为Mysql需要开启binlog,我设置了,但是没重启。


这样可可以捕获到mysql信息了:
================> binlog[mysql-bin.000001:557] , name[chapter6,test] , eventType : INSERT
uid : 1    update=true
name : 10    update=true
empty count : 1
empty count : 2


5、部署过程中产生问题:

(1)启动失败,log日志中地址正在使用
1、11111端口正在被占用 可以用 ls -i:11111 查看监听进程谁占用端口 或者 用 ps -ef | grep 11111 查看哪个进程占用端口号  然后 kill -9 进程号  杀掉占用进程
2、可以编辑 canal/conf/canal.properties 中的端口号 ,改为不占用的端口

(2)canal无法抓取mysql触发数据库改变的信息
1、检查mysql是否打开binlog写入功能  检查binlog 是否为行模式。
    show variables like "binlog_format" 

2、检查my.cnf 和 instance.properties 等配置文件填写信息是否正确。

3、检查client 代码 调试实例代码

4、版本兼容问题,canal 1.8 换成 canal 1.7 继续测试

5、查看所有日志文件 分析日志

基于canal 解决Redis与数据库数据不一致问题 一、业务场景 在实际生产过程中,由于网络原因或者Redis故障等等原因会导致Redis与数据库数据不一致的问题,这个时候我们怎么办?或许我们可以写一个定时Job然后定时去跑数据,或者找到那条数据不一致,然后删除Redis中的缓存,但是这些都有缺点,定时任务跑数据,延时性太大了。如果是删除缓存,数据量少还可以,数据量多了呢,写脚本?那脚本执行时候一定会影响Redis性能。Canal这个开源框架可以很友好的解决我们上面这些问题。 二、Canal介绍 Canal是阿里巴巴的开源项目,其原理是... 阅读详情

相关推荐

数据异构之 Canal 初探(技巧篇)

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

2401_83916435的博客 1129

Python paramiko ssh执行shell 报错Cannot find a Java JDK

Python编程使用paramiko模块的ssh远程linux执行shell报错 “Cannot find a Java JDK. Please set either set JAVA or put java (&gt;=1.5) in your PATH.” 具体代码如下: ssh = paramiko.SSHClient() ssh.set_missing_host_key_polic...

qq_30599553的博客 5337

十五、寻龙队列术——数据队列:基于Canal实现数据异构

Canal是阿里开源的一款基于MySQL数据库binlog的增量订阅和消费组件,通过 它可以订阅数据库的binlog 0志,然后进行一些数据消费,如数据镜像、数据异构、数 据索引、缓存更新等。相对于消息队列,通过这种机制可以实现数据的有序性和一致性。Canal架构如下图所示。MySQL数据库首先需要部署canal server,可以同时部署多台,但是只有一台是活跃的,其他的作 为备机。canal server会通过slave机制订阅数据库的binlog H志。

流楚丶格念的博客 2万+

报找不到jdk问题

把ecplise中的jdk删除掉 重新安装jdk

农码一生 857

基于alibaba-canal的异构数据同步解决方案

随着业务的发展,公司的整体架构方向向微服务演进。随之衍生出各种问题,本文主要提供的是数据库隔离(分库)之后的跨库join问题一种解决方案。 起因: ​ 商品服务的抽离,表结构细化;导致各依赖模块出现了各种跨库join问题。在某些复杂的业务场景下,基于原表(未分库前的商品信息)的一次join操作,在新的表结构下需要做多次跨库join。基于此场景,最终确定了技术方案: 对于简单的跨库join...

github_37947909的博客 5363

Redis(七):数据异构的武器-BINLOG+MQ 以及阿里cannal的使用

1、定义 何谓数据异构,比如我们将DB里面的数据持久化到REDIS里面去,就是一种数据异构的方式。如果要下个定义的话:把数据按需(数据结构、存取方式、存取形式)异地构建存储。 2、常见应用场景 分库分表中有一个最为常见的场景,为了提升数据库的查询能力,我们都会对数据库做分库分表操作。比如订单库,开始的时候我们是按照订单ID维度去分库分表,那么后来的业务需求想按照商家维度去查询,比如我想查询某...

scofen的博客 1257

Spring Cloud Alibaba基础练习01: 使用Cannal保持MySQL与Redis数据一致原理

Spring Cloud Alibaba基础教程01: 使用Cannal保持MySQL与Redis数据一致 2020-05-20 19:40:40 星期日 最近一致在研究Spring Cloud Alibaba的一些组件,在这里记录下心得体会,准备整理成一个系列的简单入门,方便日后查看. MySQL与Redis如何保持一致性的问题 首先来看下MySQL与Redis如何保持一致性的问题,我们会将数据放入到Redis中,从而减轻MySQL数据库的访问的压力,如果Redis缓存中没有存在该数据的情况下

东泽的博客 742

数据异构就该这样设计,yyds

本文主要叙述了数据异构的使用场景,方法。这里面涉及到的activemq以及canal并没有深入分析,关于这块的内容可以直接参考相关具体文档,文中已给了链接地址。根据数据异构的定义,将数据异地构建存储,我们可以应用的地方就非常多,文中说的分库分表之后按照其它维度来查询的时候,我们想脱离DB直接用缓存比如redis来抗量的时候。数据异构这种方式都能够很好的帮助我们来解决诸如此类的问题。

java1527的博客 241

异构系统交互

https://blog.csdn.net/liujiahan629629/article/details/23716357java https://www.cnblogs.com/bdqczhl/p/8777180.htmlc# 转载于:https://www.cnblogs.com/jinlin-2018/p/11147558.html

weixin_30520015的博客 136

源码分析 | 数据异构Canal 初探

源码分析 Canal 系列开始了,一个全新的系列,即能探讨 canal 本身的实现原理,也是笔者源码阅读技巧的展示。 1、应用场景 提到 Canal,大家应该都能想到这是一个用于解析 MySQL binlog 日志的工具,并将 MySQL 数据库数据同步到其他存储介质中,例如 Elasticsearch。 即 Canal 一个非常常用的使用场景:数据异构,一种更高级别的数据读写分离架构设计方法。 随着业务不断的发展,企业发展到一定阶段,发现单体的关系型数据库已无法支撑业务高速发展带来数据不断累.

xcz123x的博客 307

MySQL Cannal Kafka数据采集

介紹 canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。 基于日志增量订阅和消费的业务包括 数据库镜像 数据库实时备份 索引构建和实时维护(拆分异构索引、倒排索引等) 业务 cache

麦田里的守望者-蒋中洲【相信相信的力量】 382

大促突围:京东到家基于Canal的数据异构设计

张磊京东到家 高级研发工程师8年+软件研发经验,曾先后就职于链家地产、互动吧、寺库网等公司,任研发人员或团队leader,在解决业务系统设计落地方面拥有丰富经验;现就职于达达-京东到家,主...

大数据星球-浪尖 344

mysql加载数据源代码_MySQL数据源接入DBus

MySQL数据源接入DBus作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。一.cannal概述1>.cannal简介canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从2010年开始,业...

weixin_36143290的博客 428

redis+cannal+mysql共,canal redis mysql实现数据同步

https://github.com/alibaba/canal/wiki/Canal-Admin-Guidecanal 原理【官方文档】简介canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年...

weixin_29554849的博客 392

Otter数据同步原理

上图是基于memory的仲裁器实现数据扭转时许图,数据在经过SETL四个阶段完成数据处理,每个数据阶段处理完成将数据推送至下一个阻塞队列由下一个阶段的任务处理器完成数据处理再推向下一个阶段。在讲otter同步原理前需要提一下mysql的日志,otter是基于mysql的增量日志解析来实现数据同步的,这里的日志就是mysql二进制日志——binlog日志,该类型日志详细记录了所有修改的数据的sql,当某一时刻的数据误操作导致问题,或者数据库当即数据丢失,就可以通过binlog日志完成数据的找回。

wukuncsdn的博客 1535

Oracle 异构服务实践

近期公司准备开发一个计费项目,数据库当然还是选用我最信赖的Oracle了。由于一部分基础数据在一台Win2000Server的SQLServer7.0数据库中,需要考虑灵活、可靠的方法实现Or acle数据库端访问SQLServer中的数据。于是我有机会真正体验Oracle 9I 中的新增强功能“异构服务”(Heterogeneous Services)并为此...

weixin_33743248的博客 204

mysql cannal client_MYSQL同步其它类型数据库利器 - Canal的使用

Canal主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。其基本原理是伪装成辅库把数据同步到其他数据库中。基于日志增量订阅和消费的业务包括数据库镜像数据库实时备份索引构建和实时维护(拆分异构索引、倒排索引等)业务 cache 刷新带业务逻辑的增量数据处理当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0...

weixin_28406969的博客 458

异构平台同步(mysql-->oracle)

https://www.cnblogs.com/andy6/p/6159060.html 转载于:https://www.cnblogs.com/littlehb/p/9226223.html

weixin_30426957的博客 130

大数据 --> 淘宝异构数据数据交换工具 DataX

淘宝异构数据数据交换工具 DataX DataX是什么?   DataX是一个在异构数据库/文件系统之间高速交换数据的工具,实现了在任意的数据处理系统(RDBMS/Hdfs/Local filesystem)之间的数据交换,由淘宝数据平台部门完成。 DataX用来解决什么?   目前成熟的数据导入导出工具比较多,但是一般都只能用于数据导入或者导出...

weixin_30610755的博客 224
上一篇: Mysql-主从复制配置
下一篇: 基于sharding-jdbc 之spring+mybatis+sharding-jdbc整合
jcj_2012
博客等级 码龄14年 7粉丝 74原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值