上次留下的问题

问题一: 跨公网部署Otter

参考架构图

解析

​ a. 数据涉及网络传输,S/E/T/L几个阶段会分散在2个或者更多Node节点上,多个Node之间通过zookeeper进行协同工作 (一般是Select和Extract在一个机房的Node,Transform/Load落在另一个机房的Node,通过zookeeper watcher ()机制触发客户端node执行回调事件)

​ 上图中:

​ A-->B同步走的是黄色的流程,S/E在A机房Node,T/L在B机房Node

​ B-->A同步走的是红色流程,S/E在B机房Node,T/L在A机房Node

​ b. node节点可以有failover / loadBalancer. (每个机房的Node节点,都可以是集群,一台或者多台机器)

​ c. Canal是嵌入在Node中的,一般选择在S/E节点上创建Canal,即在离源数据库机房近的一端Node创建Canal,同一节Node可以创建多个Canal实例,但是针对同一个同步,同一时间只会有一个工作节点。

​ d. 要保证两端Node网络是互通的,Manager和各个资源也要是互通的。

配置

阿里云 1核/2G

腾讯云 1核/2G

百度云 2核/4G

分配:

阿里云 Node Mysql A

腾讯云 Node Mysql B

百度云 Manager Otter Mysql Zookeeper

环境: jdk1.8 docker1.19 Mysql5.7(Docker版本) Zookeeper3.14 Otter1.14

部署结构:

graph TB
subgraph Otter相关
Manager-->NodeB
Manager-->NodeA
NodeA-->嵌入式canalA
NodeB-->嵌入式canalB
Manager-->ManagerMySQL
end
subgraph 机房A
MasterA-->SlaveA1
MasterA-->SlaveA2
MasterA-->SlaveAn
嵌入式canalA-->MasterA
end
subgraph 机房B
MasterB-->SlaveB1
MasterB-->SlaveB2
MasterB-->SlaveBn
嵌入式canalB-->MasterB
end

问题二: Otter内部工作模块构件

SETL阶段

解析

为了更好的支持系统的扩展性和灵活性,将整个同步流程抽象为Select/Extract/Transform/Load,这么4个阶段.

Select阶段: 为解决数据来源的差异性,比如接入canal获取增量数据,也可以接入其他系统获取其他数据等。

Extract阶段: 组装数据,针对多种数据来源,mysql,oracle,store,file等,进行数据组装和过滤。

Transform阶段: 数据提取转换过程,把数据转换成目标数据源要求的类型

Load阶段: 数据载入,具体把数据载入到目标端

自定义拓展
  1. 数据处理自定义,比如Extract , Transform的数据处理. 目前Select/Load不支持数据自定义处理
  2. 组件功能性扩展,比如支持oracle日志获取,支持hbase数据输出等.

自由之门:

​ EventProcessor : 自定义数据处理,可以改变一条变更数据的任意内容

​ FileResolver : 解决数据和文件的关联关系(主要解决异地文件同步路径问题)

组件拓展目前这块扩展性机制不够,设计时只预留了接口,但新增一个功能实现,需要通过硬编码的方式去进行,下载otter的源码,增加功能支持,修改spring配置,同时修改web页面,方便使用。

调度模型

解析
  1. otter通过select模块串行获取canal的批数据,注意是串行获取,每批次获取到的数据,就会有一个全局标识,otter里称之为processId.
  2. select模块获取到数据后,将其传递给后续的ETL模型. 这里E和T模块会是一个并行处理
  3. 将数据最后传递到Load时,会根据每批数据对应的processId,按照顺序进行串行加载。 ( 比如有一个processId=2的数据先到了Load模块,但会阻塞等processId=1的数据Load完成后才会被执行)

简单一点说,Select/Load模块会是一个串行机制来保证binlog处理的顺序性,Extract/Transform会是一个并行,加速传输效率.

并行度

类似于tcp滑动窗口大小,比如整个滑动窗口设置了并行度为5时,只有等第一个processId Load完成后,第6个Select才会去获取数据。

并行度为三:

sequenceDiagram
participant Select
participant Extract
participant Transform
participant Load
opt Select串行
Select-->Select:从源数据库get数据
end
Select->>Extract:批次一
par E/T并行处理
Extract->>Transform:组装后的数据
end
Transform->>Load:符合特定目标的数据
Select->>Extract:批次二
par E/T并行处理
Extract->>Transform:组装后的数据
end
Transform->>Load:符合特定目标的数据
Select->>Extract:批次三
par E/T并行处理
Extract->>Transform:组装后的数据
end
Transform->>Load:符合特定目标的数据
opt Load串行
Load-->Load:加载到数据库
end
Load-->>Select:批次一返回确认
Select->>Extract:批次四

SEDA模型(分阶段事件驱动)

把数据处理划分成各个阶段,由中央控制器调度。

对应到代码中:

graph TD

A[OtterController] -->Z[根据NodeTask获取pipelineId]
Z-->Y[根据pipelineId获取tasks]
Y-->X[遍历tasks,运行isCreate==Task]
X-->B{TaskType?}
B-->|SelectTask|C[task=new SelectTask]
B-->|ExtractTask|D[task=new ExtractTask]
B-->|TransferTask|E[task=new TransferTask]
B-->|LoadTask|F[task=new LoadTask]
C-->G[start]
D-->G[start]
E-->G[start]
F-->G[start]
G-->H{TaskType?}
H-->|SelectTask|I[OtterSelector]
I-->CanalEmbedSelector执行数据获取
H-->|ExtractTask|J[OtterExtractor]
H-->|TransferTask|K[OtterTransformer]
H-->|LoadTask|L[OtterLoader]

解析

将并行化调度的串行/并行处理,进行隐藏,抽象了await/single的接口,整个调度称之为仲裁器。(有了这层抽象,不同的仲裁器实现可以解决同机房,异地机房的同步需求)

模型接口

​ await模拟object获取锁操作

​ notify被唤醒后提交任务到thread pools

​ single模拟object释放锁操作,触发下一个stage

这里使用了SEDA模型的优势

​ 共享thread pool,解决流控机制

​ 划分多stage,提升资源利用率(异地可以协同工作)

​ 统一编程模型,支持同机房,跨机房不同的调度算法(同机房耗时操作主要是数据处理,跨机房耗时操作主要是数据传输和回滚)

在pipe中,通过对数据进行TTL控制,解决TCP协议中的丢包问题控制. SEDA主要还是为了解决传统并发模型的缺点(锁机制,不易于控制,耦合度高),通过将服务器的处理划分各个Stage,利用queue连接起来形成一个pipeline的处理链,并且在Stage中利用控制器进行资源的调控。

有了一层SEDA调度模型的抽象,S/E/T/L模块之间互不感知,几个模块之间的数据传递,需要有一个机制来处理,这里抽象了一个pipe(管道)的概念.

原理:

stage | pipe | stage

基于pipe实现:

​ in memory (两个stage经过仲裁器调度算法选择为同一个node时,直接使用内存传输)

​ rpc call (传递的数据<1MB) (异地)

​ file(gzip) + http多线程下载 (文件,大量数据)

在pipe中,通过对数据进行TTL控制,解决TCP协议中的丢包问题控制. (TTL>n重传)

仲裁器算法

主要包括: 令牌生成(processId) + 事件通知.

令牌生成:

  • 基于AtomicLong.inc()机制(原子性自增),(纯内存机制,解决同机房,单节点同步需求,不需要多节点交互)
  • 基于zookeeper的自增id机制,(解决异地机房,多节点(一般是双节点)协作同步需求)

事件通知: (简单原理: 每个stage都会有个阻塞队列,接收上一个stage的single信号通知,当前stage会阻塞在该block queue上,直到有信号通知)

  • block queue + put/take方法,(同Node纯内存机制存取数据)
  • block queue + rpc + put/take方法 (两个stage对应的node不同,需要rpc调用,需要依赖负载均衡算法解决node节点的选择问题)
  • block queue + zookeeper watcher () (zookeeper事件客户端回调)

负载均衡算法

  • Stick : 类似于session stick技术,一旦第一次选择了node,下一次选择会继续使用该node. (有一个好处,资源上下文缓存命中率高)
  • Random : 随机算法
  • RoundRbin : 轮询算法

注意点:每个node节点,都会在zookeeper中生成Ephemeral节点(零时节点),每个node都会缓存住当前存活的node列表,node节点消失,通过zookeeper watcher机制刷新每个node机器的内存。然后针对每次负载均衡选择时只针对当前存活的节点,保证调度的可靠性。

问题三: 名词表

名词 解释 备注
Pipeline 从源端到目标端的整个过程描述,主要由一些同步映射过程组成
Channel 同步通道,单向同步中一个Pipeline组成,在双向同步中有两个Pipeline组成
DataMediaPair 根据业务表定义映射关系,比如源表和目标表,字段映射,字段组等
DataMedia 抽象的数据介质概念,可以理解为数据表/mq队列定义
DataMediaSource 抽象的数据介质源信息,补充描述DateMedia
ColumnPair 定义字段映射关系
ColumnGroup 定义字段映射组
Node 处理同步过程的工作节点,对应一个jvm
SEDA模型 Staged Event-Driven Architecture(把一个请求处理过程分成几个Stage,不同资源消耗的Stage使用不同数量的线程来处理,Stage间使用事件驱动的异步通信模式。)
stage 程序流程的各个阶段(这里指数据的S/E/T/L)
processId 处理批次ID,保证串行顺序
get/ack/rollback 获取/确认/回滚
zookeeper watcher () zookeeper 事件回调机制
zookeeper Ephemeral 节点 zookeeper session创建的一个零时节点
TTL 代表数据在网络中长时间没有响应被丢弃时经过的最大的路由器数量
failover 故障转移

Canal和Otter讨论二(原理与实践)的更多相关文章

  1. kafka原理和实践(二)spring-kafka简单实践

    系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...

  2. WebSocket原理与实践(二)---WebSocket协议

    WebSocket原理与实践(二)---WebSocket协议 WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的.协议定义ws和wss协议,分别为普通请求和基 ...

  3. 2017.2.9 深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二)-----配置文件详解

    深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二) ------配置文件详解 8.2 MyBatis-Spring应用 8.2.1 概述 本文主要讲述通过注解配置MyBa ...

  4. Spring Boot自动配置原理与实践(二)

    前言 在之前的博文(Spring Boot自动配置原理与实践(一))中,已经介绍了Spring boot的自动配置的相关原理与概念,本篇主要是对自动配置的实践,即自定义Starter,对原理与概念加深 ...

  5. Atitit 管理原理与实践attilax总结

    Atitit 管理原理与实践attilax总结 1. 管理学分类1 2. 我要学的管理学科2 3. 管理学原理2 4. 管理心理学2 5. 现代管理理论与方法2 6. <领导科学与艺术4 7. ...

  6. 分布式开放消息系统(RocketMQ)的原理与实践(转)

    转自:http://www.jianshu.com/p/453c6e7ff81c 分布式消息系统作为实现分布式系统可扩展.可伸缩性的关键组件,需要具有高吞吐量.高可用等特点.而谈到消息系统的设计,就回 ...

  7. 分布式消息中间件rocketmq的原理与实践

    RocketMQ作为阿里开源的一款高性能.高吞吐量的消息中间件,它是怎样来解决这两个问题的?RocketMQ 有哪些关键特性?其实现原理是怎样的? 关键特性以及其实现原理 一.顺序消息 消息有序指的是 ...

  8. 深入理解FFM原理与实践

    原文:http://tech.meituan.com/deep-understanding-of-ffm-principles-and-practices.html 深入理解FFM原理与实践 del2 ...

  9. 搞懂分布式技术10:LVS实现负载均衡的原理与实践

    搞懂分布式技术10:LVS实现负载均衡的原理与实践 浅析负载均衡及LVS实现 原创: fireflyc 写程序的康德 2017-09-19 负载均衡 负载均衡(Load Balance,缩写LB)是一 ...

随机推荐

  1. 用优先队列构造Huffman Tree及判断是否为最优编码的应用

    前言 我们知道,要构造Huffman Tree,每次都要从堆中弹出最小的两个权重的节点,然后把这两个权重的值相加存放到新的节点中,同时让这两个节点分别成为新节点的左右儿子,再把新节点插入到堆中.假设节 ...

  2. Autofac 框架初识与应用

    文字首发地址 一.前言 这上一篇中,主要讲述了什么是IoC容器,以及了解到它是DI构造函注入的框架,它管理着依赖项的生命周期以及映射关系,同时也介绍实践了在ASP.Net Core中,默认提供的内置I ...

  3. 孙悟空的身外身法术使用了Java设计模式:原型模式

    目录 定义 意图 主要解决问题 何时使用 优缺点 结构 简单形式的原型模式 登记形式的原型模式 两种形式比较 浅克隆和深克隆 孙悟空的身外身法术 浅克隆实现 深克隆实现 定义 原型模式属于对象的创建型 ...

  4. Mybatis3源码笔记(四)Configuration(续)

    1.pluginElement(root.evalNode("plugins")) 解析plugins节点(注册interceptorChain里记录对应的拦截器) private ...

  5. Go之Zap日志库集成Gin

    简介 在许多Go语言项目中,我们需要一个好的日志记录器能够提供下面这些功能: 1 . 能够将事件记录到文件中,而不是应用程序控制台; 2 . 日志切割-能够根据文件大小.时间或间隔等来切割日志文件; ...

  6. 《机器学习Python实现_10_02_集成学习_boosting_adaboost分类器实现》

    一.简介 adaboost是一种boosting方法,它的要点包括如下两方面: 1.模型生成 每一个基分类器会基于上一轮分类器在训练集上的表现,对样本做权重调整,使得错分样本的权重增加,正确分类的样本 ...

  7. Laravel5.6教程之——安装

    1.安装 方式1:全局安装 通过composer安装 laravel 安装器 composer global require "laravel/installer" 1 确保将 c ...

  8. overflow和absolute之间的问题,transfrom可以解决

    CSS代码: .overflow { width: 191px; height: 191px; border: 2px solid #beceeb; overflow: hidden; } .over ...

  9. 【CPU100%排查】CPU100%问题排查方案

    1.使用top -c 查看CPU 占用情况 ,按P(大写)可以倒序查看占CPU占用率  2.找到占用率高的进程以后,再定位到具体线程 比如 此时进程ID 14724 CPU占用高,进一步使用top - ...

  10. 技术面试问题汇总第003篇:猎豹移动反病毒工程师part3

    从现在开始,面试的问题渐渐深入.这次的三个问题,都是对PE格式的不断深入的提问.从最初的概念,到病毒对PE格式的利用,再到最后的壳的问题.这里需要说明的是,由于壳是一个比较复杂的概念,面试中也仅仅只能 ...