canal mysql从库_大厂如何基于binlog解决多机房同步mysql数据(一)?

目录

  1. 前言
  2. 单一IDC
  3. 多IDC
  4. mysql主从同步
  5. 数据同步方案
  6. 多机房mysql同步方案
  7. 优化同步方案
  8. 同步方案的问题
  9. 如何解决重复插入
  10. 对于DDL语句处理
  11. 如何解决唯一索引冲突
  12. 如何解决数据回环问题
  13. 总结

前言

小伙伴们是否经常听说多机房部署,异地容灾?什么两地3中心,三地5中心?是否好奇多机房部署,数据之间是如何共享的呢

今天老顾就来尝试着给大家解惑解惑,并详细介绍一下数据同步的问题。

单一IDC

ead54ac9039dd4364a44434a22c243cb.png

上图的架构,是一个IDC机房中,部署了一主两从mysql数据库集群,大多数据中小型互联网公司采用的方案。

上面的方案存在一些问题:

1)不同地区的用户体验速度不同。一个IDC必然只能部署在一个地区,例如部署在北京,那么北京的用户访问将会得到快速响应;但是对于上海的用户,访问延迟一般就会大一点

上海到北京的一个RTT可能有20ms左右。

2)容灾问题。这里容灾不是单台机器故障,而是指机房断电,自然灾害,或者光纤被挖断等重大灾害。一旦出现这种问题,将无法正常为用户提供访问,甚至出现数据丢失的情况。

某年,支付宝杭州某数据中心的光缆就被挖断过

多IDC

为了解决这些问题,我们可以将服务部署到多个不同的IDC中,不同IDC之间的数据互相进行同步。如下图

bb5a890dda7bd918b1c59a9f1d941cf3.png

通过这种方式,我们可以解决单机房遇到的问题:

1)用户体验。不同的用户可以选择离自己最近的机房进行访问

2)容灾问题。当一个机房挂了之后,我们可以将这个机房用户的流量调度到另外一个正常的机房,由于不同机房之间的数据是实时同步的,用户流量调度过去后,也可以正常访问数据

故障发生那一刻的少部分数据可能会丢失

关于流量的调度问题,本文就不介绍,以后老顾会单独介绍流量、灰度发布的问题。本文主要介绍数据同步。

容灾补充

  • 机房容灾 : 上面的案例中,我们使用了2个IDC,但是2个IDC并不能具备机房容灾能力。至少需要3个IDC,例如,一些基于多数派协议的一致性组件,如zookeeper,redis、etcd、consul等,需要得到大部分节点的同意。例如我们部署了3个节点,在只有2个机房的情况下, 必然是一个机房部署2个节点,一个机房部署一个节点。当部署了2个节点的机房挂了之后,只剩下一个节点,无法形成多数派。在3机房的情况下,每个机房部署一个节点,任意一个机房挂了,还剩2个节点,还是可以形成多数派。这也就是我们常说的"两地三中心”。
  • 城市级容灾:在发生重大自然灾害的情况下,可能整个城市的机房都无法访问。为了达到城市级容灾的能力,使用的是"三地五中心"的方案。这种情况下,3个城市分别拥有2、2、1个机房。当整个城市发生灾难时,其他两个城市依然至少可以保证有3个机房依然是存活的,同样可以形成多数派。

Mysql主从同步

小伙伴们应该知道mysql的主从架构的数据复制的基本原理

ac5402f46f8c58d2e40353e8f847163c.png

通常一个mysql集群有一主多从构成。用户的数据都是写入主库Master,Master将数据写入到本地二进制日志binary log中。从库Slave启动一个IO线程(I/O Thread)从主从同步binlog,写入到本地的relay log中,同时slave还会启动一个SQL Thread,读取本地的relay log,写入到本地,从而实现数据同步

数据同步方案

根据上面的mysql主从数据复制方案,那我们是不是可以自己写个组件,也读取binlog日志,解析出sql语句;然后同步到另一个mysql集群呢?

这样就可以实现了一个集群的数据,同步到另一个集群中。

那这个组件需要我们自己写吗?这个组件可以参考binlog的协议,只要有资深的网络编程知识,是能够实现的。

当然现在也不需要我们自己编写,现在市面上有成熟开源的

  • 阿里巴巴开源的canal
  • 美团开源的puma
  • linkedin开源的databus

我们可以利用这些开源组件订阅binlog日志,解析到变化数据同步到目标库中。整个过程可以分为2步,第一步订阅获得变化的数据,第二步是把变化数据更新到其他目标库

这边所说的目标库,不单单为mysql集群,也可以为redis,es等

d4d294bfa4a39c1a55ebb679506eaf7b.png

上图我们通过订阅binlog,完成比较有代表性的数据同步

多机房Mysql同步

根据上面的知识,多机房的mysql的数据同步,可以也采用binlog方案

c424e265165800306e068f6995bea888.png

北京用户的数据不断写入离自己最近的机房的DB,通过binlog订阅组件订阅这个库binlog,然后下游的更新组件将binlog转换成SQL,插入到目标库。上海用户类似,只不过方向相反,不再赘述。通过这种方式,我们可以实时的将两个库的数据同步到对端。

上面的方案面对binlog更新不频繁的场景,应该问题不大;但是如果更新很频繁,那么binlog日志量会很大,处理更新数据的组件很有可能会顶不住,那如何处理?

优化同步方案

为了解决binlog量过大,更新数据组件处理不过来,可以在此方案中加入MQ进行削峰,如下图

f7e47141cbc872e93c9fbf0fc70c008b.png

同步方案的问题

我们看到上面的架构,主要是针对增量数据的同步;但一开始项目上线的时候,全量数据怎么处理呢?这个一般的处理策略是DBA先dump一份源库完整的数据快照;目标库导入快照即可。

下面我们看看增量数据同步,仔细的小伙伴们应该会看到北京IDC和上海IDC之间的数据是双向的,因为北京用户的数据是更新到北京DB的,上海用户的数据是更新到上海DB的,所以业务上面也是必须是双向的

整个数据同步的过程会出现几个问题:

如何解决重复插入?

考虑以下情况下,源库中的一条记录没有唯一索引。对于这个记录的binlog,通过更新组件将binlog转换成sql插入目标库时,抛出了异常,此时我们并不知道知道是否插入成功了,则需要进行重试。如果之前已经是插入目标库成功,只是目标库响应时网络超时(socket timeout)了,导致的异常,这个时候重试插入,就会存在多条记录,造成数据不一致

因此,通常,在数据同步时,通常会限制记录必须有要有主键或者唯一索引

对于DDL语句如何处理?

如果数据库表中已经有大量数据,例如千万级别、或者上亿,这个时候对于这个表的DDL变更,将会变得非常慢,可能会需要几分钟甚至更长时间,而DDL操作是会锁表的,这必然会对业务造成极大的影响

因此,同步组件通常会对DDL语句进行过滤,不进行同步。DBA在不同的数据库集群上,通过一些在线DDL工具进行表结构变更。

如何解决唯一索引冲突?

由于两边的库都存在数据插入,如果都使用了同一个唯一索引,那么在同步到对端时,将会产生唯一索引冲突。对于这种情况,通常建议是使用一个全局唯一的分布式ID生成器来生成唯一索引,保证不会产生冲突。

另外,如果真的产生冲突了,同步组件应该将冲突的记录保存下来,以便之后的问题排查。

如何解决数据回环问题?

此问题是数据同步经常出现的,也是必须需要解决的。最重要的问题。我们针对INSERT、UPDATE、DELETE三个操作来分别进行说明:

INSERT操作

假设在A库插入数据,A库产生binlog,之后同步到B库,B库同样也会产生binlog。由于是双向同步,这条记录,又会被重新同步回A库。由于A库本来就存在这条记录了,产生冲突。

UPDATE操作

先考虑针对A库某条记录R只有一次更新的情况,将R更新成R1,之后R1这个binlog会被同步到B库,B库又将R1同步会A库。对于这种情况下,A库将不会产生binlog。因为A库记录当前是R1,B库同步回来的还是R1,意味着值没有变。

在一个更新操作并没有改变某条记录值的情况下,mysql是不会产生binlog,相当于同步终止。下图演示了当更新的值没有变时,mysql实际上不会做任何操作:

a13a7ea6c9b2ce8056d3becc359ac428.png

上图演示了,数据中原本有一条记录(1,"tianshouzhi”),之后执行一个update语句,将id=1的记录的name值再次更新为”tianshouzhi”,意味着值并没有变更。这个时候,我们看到mysql 返回的影响的记录函数为0,也就是说,并不会产生的更新操作

小伙伴们是不是以为,update操作不会有回环问题了;事实上并不是,我们看一些场景:

虑A库的记录R被连续更新了2次,第一次更新成R1,第二次被更新成R2;这两条记录变更信息都被同步到B库,B也产生了R1和R2。由于B的数据也在往A同步,B的R1会被先同步到A,而A现在的值是R2,由于值不一样,将会被更新成R1,并产生新的binlog;此时B的R2再同步会A,发现A的值是R1,又更新成R2,也产生binlog。由于B同步回A的操作,让A又产生了新的binlog,A又要同步到B,如此反复,陷入无限循环中。

这个后果将会进入死循环。

DELETE操作

同样存在先后顺序问题。例如先插入一条记录,再删除。B在A删除后,又将插入的数据同步回A,接着再将A的删除操作也同步回A,每次都会产生binlog,陷入无限回环

总结

今天老顾介绍了基本的多机房同步mysql的方案,以及同步方案遇到的一些问题,以及一些解决方案;但还遗留了数据回环问题,老顾将在下一篇文章中介绍解决方案。谢谢!!!

---End---

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java语言怎么建立窗口awt,java.awt.Frame类:创建窗口

创建窗口是 AWT 编程的第一步,窗口是所有组件和面板的容器。在 Java AWT 中,我们使用 Frame 类来创建窗口。Frame 中文字意是“框架”,它的主要功能是建立窗口。AWT 建立窗口的步骤如下:设计 Frame 类对象,建立空白窗口…

sql数据导入错误代码: 0x80004005_SQL入门第八关 项目实战

不知不觉,学SQL已经一个多月了,每天下班学一个小时,有空做做练习题。从之前的焦虑到现在已经有了一定的自信了,猴子的课程真的很适合小白入门,尤其是SQL学习群里,助教老师很尽责,每个问题都会解…

虚拟主机选择php版本,虚拟主机的php版本如何选择

虚拟主机如何选择php版本?虚拟主机选择PHP版本,这是根据网站程序设置的。例如,新版本的WordPress需要PHP5.6和更高版本,而旧版本,如WordPress4,可以使用PHP5.2、5.3和其他更低版本。虚拟主机的PHP版本是什么…

php生成10万个字符串,有什么好的方法可以生成十万条不重复的13位纯数字字符串...

有什么好的方法可以生成十万条不重复的13位纯数字字符串回复内容:有什么好的方法可以生成十万条不重复的13位纯数字字符串一个个来。从13个0开始,一次加1。。。可用时间戳来生成,或者后面再加随机数package com.xtl.demo;import java.util.Ha…

python金融数据怎么获取_class类怎样在python中获取金融数据?

我们搜集金融数据,通常想要的是利用爬虫的方法。其实我们最近所学的class不仅可以进行类调用,在获取数据方面同样是可行的,很多小伙伴都比较关注理财方面的情况,对金融数据的需要也是比较多的。下面就class类在python中获取金融数…

有十五个数按由大到小顺序存放在一个数组中_数据结构基础 (代码效率优化, 线性表, 栈, 队列, 数组,字符串,树和二叉树,哈希表)...

作者:张人大代码效率优化复杂度 -- 一个关于输入数据量n的函数时间复杂度 -- 昂贵与代码的结构设计有着紧密关系一个顺序结构的代码,时间复杂度是O(1), 即任务与算例个数 n 无关空间复杂度 -- 廉价与数据结构设计有关数据结构 -- 考虑如何去组织计算机中…

matlab 转换图片格式,Matlab实现图片格式转换 pgm转jpg等

在Matlab下,转换图片格式相对比较容易,本文以 PGM 转 JPG 为例,贴出示例程序:% 将pgm图片批量转换为jpg图片function [ ] pgm2jpg( )% 读取指定目录下面所有的pgm格式图片pgms dir(C:\Users\kitty\test\*.pgm);num_pgms length( pgms );fo…

python3库查看调用_Python 3 中调用 COM 的库文件 | 学步园

在 Python 2.x 时代貌似有支持 COM的。 http://svn.python.org/projects/ctypes/tags/release_0_6_2/ctypes/win32/com/__init__.py 这个 win32 的 COM 包到了 3.x 时代就不见了。从那里参考和借鉴了很多,也被误导了很多,因为从2.x 到 3.x 变化很大&…

matlab的try函数,matlab – 是否可以在没有try块的情况下测试函数句柄?

要测试函数句柄,例如在你的问题中筛选出伪造的x notreallyafunction,你可以使用functions命令检查句柄并获取引用函数的名称,类型(简单,嵌套,重载,匿名等),和位置,如果它在文件中定义.>> x notreallyafunction;>> functions(x)ans function: notreallyafunction…

图片马赛克去除工具_图片太多该如何进行排版呢?

胖友们大家好呀,我是三儿昨天三儿刚讲了多文字如何排版就有胖友在后台留言说问三儿如何对图片较多的内容排版那么今天三儿就来教大家图片较多时我们该怎样排版!赶紧拿着小本本做好笔记哦!图片的重要性图片在排版设计中,占有很大的…

神经网络人口预测matlab,BP神经网络预测(人口)程序(matlab)

自己测试人口预测的matlab实现:x[5416755196563005748258796602666146562828646536599467207662076585967295691727049972538745427636878534806718299285229871778921190859924209371794974962599754298705100072101654103008104357105851107507109300111026112704…

idhttp返回乱码_HTTP客户端POST方式中文编码(乱码)解决方案(转)

这段时间,在给一个地区门户网站(alexa全球排行1200左右)做SSO集成,其中的一个部分就是Web Services服务接口,以及客户端,我们采用的是REST方式,不是SOAP,大致就是客户端通过HTTP POST方式向服务器提交数据&…

php如何监听页面滚动,html5中在元素滚动条在滚动时触发的事件onscroll

实例元素滚动时执行 JavaScript定义和用法onscroll 事件在元素滚动条在滚动时触发。提示: 使用 CSS overflow 样式属性来创建元素的滚动条。浏览器支持语法HTML 中:JavaScript 中:object.οnscrοllfunction(){myScript};JavaScript 中, 使用 addEventListener() 方…

stream去重_重复数据如何处理?List集合去重的四种方式

List集合在Java日常开发中是必不可少的,只要懂得运用各种各样的方法就可以大大提高我们开发的效率,适当活用各种方法才会使我们开发事半功倍。但是,有时候难免会遇到集合里的数据是重复的,需要进行去除。今天,就给大家…

php强制转成字符串,php怎么强制转成字符串

php强制转成字符串的方法:首先创建一个PHP示例文件;然后定义一个变量;最后通过PHP中的string方法强制转换成字符串即可。本文操作环境:windows7系统、PHP7.1版,DELL G3电脑PHP强制转换类型获取数据类型 :1.如果想查看某…

虚幻4模型提取_【UnrealEngine4】从虚幻四的着色模型到NPR

本文主要分享虚幻四中着色器的使用技巧与如何添加自己的着色模型的方式。(正在设计的一个像素风格的渲染流程,同样采用本文的方法,对引擎的着色模型进行了改造,可以接受天光/点光等的自定义照明效果)鄙人消失了一个月左右,又回来了…

可观测性PHP秩判据,线性系统的可控性与可观测性

现代控制理论中用状态方程和输出方程描述系统,输入和输出构成系统的外部变量,而状态为系统的内部变量,这就存在着系统内的所有状态是否可受输入影响和是否可由输出反映的问题,这就是可控性和可观测性问题。如果系统所有状态变量的…

ubuntu虚拟机进程被杀死_Ubuntu -- 查看和杀死进程

今天在netbeans中关闭webrick时,发现没有关闭掉,打入localhost:3000 依然显示页面,发现无法从nb中再次关闭只有进入ubuntu的进程下关闭查看进程:1, ps -e2, fengfeng:~$ sudo netstat -antupActive Internet connections (servers and established)Proto Recv-Q Send-Q Local…

matlab中的nlinfit,matlab中nlinfit问题!!!!!!!!!!!!

matlab中nlinfit问题!!!!!!!!!!!!mip版 关注:272 答案:3 悬赏:40解决时间 2021-01-19 04:20已解决2021-01-18 13:28muinline(beta(…

springboot幂等性_请问,springboot项目支付接口设计,如何保证支付的幂等性,并能给前端反馈友好的提示?...

什么是幂等性?幂等是一个数学与计算机学概念,在数学中某一元运算为幂等时,其作用在任一元素两次后会和其作用一次的结果相同。“ 在计算机中编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函…