网络服务业有哪些,网站做优化需要多少钱,外贸行业网站建设公司,加若格网站做么样目录前言单一IDC多IDCmysql主从同步数据同步方案多机房mysql同步方案优化同步方案同步方案的问题如何解决重复插入对于DDL语句处理如何解决唯一索引冲突如何解决数据回环问题总结前言小伙伴们是否经常听说多机房部署#xff0c;异地容灾#xff1f;什么两地3中心#xff0c;…目录前言单一IDC多IDCmysql主从同步数据同步方案多机房mysql同步方案优化同步方案同步方案的问题如何解决重复插入对于DDL语句处理如何解决唯一索引冲突如何解决数据回环问题总结前言小伙伴们是否经常听说多机房部署异地容灾什么两地3中心三地5中心是否好奇多机房部署数据之间是如何共享的呢今天老顾就来尝试着给大家解惑解惑并详细介绍一下数据同步的问题。单一IDC上图的架构是一个IDC机房中部署了一主两从mysql数据库集群大多数据中小型互联网公司采用的方案。上面的方案存在一些问题1)不同地区的用户体验速度不同。一个IDC必然只能部署在一个地区例如部署在北京那么北京的用户访问将会得到快速响应但是对于上海的用户访问延迟一般就会大一点。上海到北京的一个RTT可能有20ms左右。2)容灾问题。这里容灾不是单台机器故障而是指机房断电自然灾害或者光纤被挖断等重大灾害。一旦出现这种问题将无法正常为用户提供访问甚至出现数据丢失的情况。某年支付宝杭州某数据中心的光缆就被挖断过多IDC为了解决这些问题我们可以将服务部署到多个不同的IDC中不同IDC之间的数据互相进行同步。如下图通过这种方式我们可以解决单机房遇到的问题1)用户体验。不同的用户可以选择离自己最近的机房进行访问2)容灾问题。当一个机房挂了之后我们可以将这个机房用户的流量调度到另外一个正常的机房由于不同机房之间的数据是实时同步的用户流量调度过去后也可以正常访问数据故障发生那一刻的少部分数据可能会丢失 关于流量的调度问题本文就不介绍以后老顾会单独介绍流量、灰度发布的问题。本文主要介绍数据同步。容灾补充机房容灾 : 上面的案例中我们使用了2个IDC但是2个IDC并不能具备机房容灾能力。至少需要3个IDC例如一些基于多数派协议的一致性组件如zookeeperredis、etcd、consul等需要得到大部分节点的同意。例如我们部署了3个节点在只有2个机房的情况下 必然是一个机房部署2个节点一个机房部署一个节点。当部署了2个节点的机房挂了之后只剩下一个节点无法形成多数派。在3机房的情况下每个机房部署一个节点任意一个机房挂了还剩2个节点还是可以形成多数派。这也就是我们常说的两地三中心”。城市级容灾在发生重大自然灾害的情况下可能整个城市的机房都无法访问。为了达到城市级容灾的能力使用的是三地五中心的方案。这种情况下3个城市分别拥有2、2、1个机房。当整个城市发生灾难时其他两个城市依然至少可以保证有3个机房依然是存活的同样可以形成多数派。Mysql主从同步小伙伴们应该知道mysql的主从架构的数据复制的基本原理通常一个mysql集群有一主多从构成。用户的数据都是写入主库MasterMaster将数据写入到本地二进制日志binary log中。从库Slave启动一个IO线程(I/O Thread)从主从同步binlog写入到本地的relay log中同时slave还会启动一个SQL Thread读取本地的relay log写入到本地从而实现数据同步。数据同步方案根据上面的mysql主从数据复制方案那我们是不是可以自己写个组件也读取binlog日志解析出sql语句然后同步到另一个mysql集群呢这样就可以实现了一个集群的数据同步到另一个集群中。那这个组件需要我们自己写吗这个组件可以参考binlog的协议只要有资深的网络编程知识是能够实现的。当然现在也不需要我们自己编写现在市面上有成熟开源的阿里巴巴开源的canal美团开源的pumalinkedin开源的databus我们可以利用这些开源组件订阅binlog日志解析到变化数据同步到目标库中。整个过程可以分为2步第一步订阅获得变化的数据第二步是把变化数据更新到其他目标库。这边所说的目标库不单单为mysql集群也可以为redises等上图我们通过订阅binlog完成比较有代表性的数据同步多机房Mysql同步根据上面的知识多机房的mysql的数据同步可以也采用binlog方案北京用户的数据不断写入离自己最近的机房的DB通过binlog订阅组件订阅这个库binlog然后下游的更新组件将binlog转换成SQL插入到目标库。上海用户类似只不过方向相反不再赘述。通过这种方式我们可以实时的将两个库的数据同步到对端。上面的方案面对binlog更新不频繁的场景应该问题不大但是如果更新很频繁那么binlog日志量会很大处理更新数据的组件很有可能会顶不住那如何处理优化同步方案为了解决binlog量过大更新数据组件处理不过来可以在此方案中加入MQ进行削峰如下图同步方案的问题我们看到上面的架构主要是针对增量数据的同步但一开始项目上线的时候全量数据怎么处理呢这个一般的处理策略是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库记录当前是R1B库同步回来的还是R1意味着值没有变。在一个更新操作并没有改变某条记录值的情况下mysql是不会产生binlog相当于同步终止。下图演示了当更新的值没有变时mysql实际上不会做任何操作上图演示了数据中原本有一条记录(1,tianshouzhi”)之后执行一个update语句将id1的记录的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又产生了新的binlogA又要同步到B如此反复陷入无限循环中。这个后果将会进入死循环。DELETE操作 同样存在先后顺序问题。例如先插入一条记录再删除。B在A删除后又将插入的数据同步回A接着再将A的删除操作也同步回A每次都会产生binlog陷入无限回环。总结 今天老顾介绍了基本的多机房同步mysql的方案以及同步方案遇到的一些问题以及一些解决方案但还遗留了数据回环问题老顾将在下一篇文章中介绍解决方案。谢谢---End---