数据库读写分离一致性问题

说说思路

1 半同步复制

  简单的说就是: 主库发生增删改操作的时候,会等从库及时复制了并且通知了主库, 才会把这个操作叫做成功.

  优点:保证数据一致性

  缺点:就是会慢

专业的讲:

  半同步复制,是等待其中一个从库也接收到Binlog事务并成功写入Relay Log之后,才返回Commit操作成功给客户端;如此半同步就保证了事务成功提交后至少有两份日志记录,一份在主库Binlog上,另一份在从库的Relay Log上,从而进一步保证数据完整性;半同步复制很大程度取决于主从网络RTT(往返时延),以插件 semisync_master/semisync_slave 形式存在。 

mysql具体如何配置可参考

https://www.cnblogs.com/zero-gg/p/9057092.html

mqspl半同步存在的一些问题

https://www.cnblogs.com/jichunhu/p/5825801.html

 

2 全同步复制

介绍了半同步,全同步概念也就不言而喻啦。

 

3 数据库中间件

如果有了数据库中间件,所有的数据库请求都走中间件,这个主从不一致的问题可以这么解决:

所有的读写请求都走中间件,然后写的请求路由到主库,读的请求路由到从库

但是我们中间件会记录写库的一个key,在设置一个允许同步时间,假设是1s

当有一个写请求过来时候,生成一个key A ,马上路由写到主库,然后立马有一个读请求过来。 从库可能是旧数据,或者没有来得及同步。 如果时间是在1s内的,就对应的key继续路由到主库。如果在1s以后的,就路由到从库。

说白了,中间件就是给个同步时间,给你同步,在同步时间内,所有的请求都落在主库

不知有没有可用的中间件,不过实现相对简单,可以用本地缓存来实现,通过查找本地缓存来判断数据是否刚写入。

 

虽然MySQL一直在优化数据的一致性问题,但问题依然存在,使得各大企业纷纷各自设计一套MySQL补丁来保证数据一致。腾讯数平的TDSQL,腾讯微信的PhxSQL,阿里的AliSQL,网易的InnoSQL等设计都是为了保证数据一致性。MySQL5.7发布的lossless半同步,虽然宣称zero loss,解决了5.6版本中有可能出现的data lost问题,但其数据一致性仍未完全解决。

 

cluster 方案

MySQL异步复制

在MySQL发展的早期,就提供了异步复制的技术,只要写的压力不是特别大,在网络条件较好的情况下,发生主备切换基本上能将影响控制到秒级别,因此吸引了很多开发者的关注和使用。但这套方案提供的一致性保证,对于计费或者金融行业是不够的。

图4是异步复制的大致流程,很显然主机提交了binlog就会返回给业务成功,没有保证binlog同步到了备机,这样在切换的瞬间很有可能丢失这部分事务。

 

 

图4 异步复制

MySQL半同步复

到了MySQL 5.5版本的时候,Google提供了一个半同步半异步的插件,确保必须收到一个备机的应答才让事务在主机中提交;当备机应答超时的情况下,强同步就会自动退化成异步模式(这也是半同步半异步名字的由来)。

 

 

图5 半同步复制

这套方案相对异步复制,在数据的可靠性方面确实好很多,在主机本身故障的情况下,基本能保证不丢失事务(因为最后一个事务,至少有一个备机上存在),但一旦退化成异步复制就回到过去了。TDSQL没直接采用这套方案,是因为:在主备跨IDC(ping延迟2-3毫秒)时性能非常很低。

Cluster

除了上面的方案外,开源社区还有三个Cluster解决方案,分别是Oracle的NDB引擎、Percona XtraDB Cluster和MariaDB Galera Cluster,从公开资料的性能对比上来看,后2者在性能和系统灵活性等方面都强于NDB(同时采用NDB意味着也放弃了InnoDB引擎,NDB主要是基于全内存的,并且需要高速网络环境支持,所以不考虑了);Percona XtraDB Cluster和MariaDB Galera Cluster强同步机制的底层都是采用Galera这套强同步的架构。MariaDB Galera Cluster具有如下非常吸引人的特性:

♦  MariaDB Galera Cluster 是一套在MySQL InnoDB存储引擎上面实现multi-master及数据实时同步的系统架构,业务层面无需做读写分离工作,数据库读写压力都能按照既定的规则分发到各个节点上去;
♦  同步复制Synchronous replication:保证节点间数据一致性;
♦  Active-active multi-master拓扑逻辑:多主的拓扑结构,可以认为没有备机的概念;
♦  可对集群中任一节点进行数据读写:假如一个set有3个节点,则3个节点可以同时读写,上次完全不用关心主备切换和读写分离;
♦  自动成员控制,故障节点自动从集群中移除;
♦  自动节点加入;
♦  真正并行的复制,基于行级:同一个表可以在集群中任何节点更新,支持不带where条件,但一次更新的记录条数有限制;
♦  每个节点都包含完整的数据副本。

目前来看,Galera是一套相当完美的方案。但是,在跨IDC的性能测试中,其性能下降比较大,另外,实现方案也比较复杂,目前对它的代码理解还不够透彻,所以暂时没有在计费领域大范围推广使用。但我相信这个方向是对的,有吸引力的,随着后续Galera越来越完善,我们对它研究得越透彻,也许有一天会采用这套方案。

 

性能测试和分析

上面的三种复制模式对比测试,数据如图6所示。

 

 

图6 三种复制模式的对比

从图6的数据可以看出,半同步和Galera模式对性能的损耗还是非常大的,Galera的毛刺尤其严重,所以在跨IDC环境下还不是适合计费这样对延迟要求非常低的场景。

为什么性能损耗会这么严重呢?这个看明白MySQL的网络模型就清楚了。外界可查的MySQL最早的公开版本应该是1996年的3.1.1.1版本,这么多年来,网络模型基本上变化不大,与Apache有点类似,有点区别的是MySQL采用的是每个连接一个线程的模型,这套模型最大的好处就是开发特别简单,线程内部都是同步调用,只要不访问外部接口,支撑每秒几百上千的请求量也基本够用,因为大部分情况下IO是瓶颈。不过随着当前硬件的发展,尤其是SSD、FusionIO的出现,IOPS从200+/s进化到几十万甚至百万次/s,IO基本上不再是瓶颈,若再采用这套模型并采用阻塞的方式调用延迟较大的外部接口,则CPU都会阻塞在等网络应答上了,性能自然上不去。

不过在MySQL5.6企业版和MariaDB、Percona中都引入了线程池,使得网络模型灵活了很多,图7是简化后的对比模型。

 

 

图7 简化的对比模型

TDSQL采用的强同步方案

从上面的分析可知,半同步半异步是比较轻量级的高一致性容灾方案,但受限于已有的同步网络模型,CPU利用不起来。我们如果在线程池基础之上做一些修改,参考半同步的思路就可以实现一个高性能的强同步方案。

目前的做法是采用与Linux内核处理中断的思路:将上面线程池模型的第三个环节(执行SQL的逻辑)拆成两个部分:

♦  上半部分:任务执行到写binlog为止,然后将会话保存到session中,接着执行下一轮循环去处理其他请求了,这样就避免让线程阻塞等待应答了;

♦  然后:MySQL自身负责主备同步的dump线程会将binlog立即发送出去,备机的IO线程收到binlog并写入到relay log之后,再通过UDP给主机一个应答;

♦  在主机上,开一组线程来处理应答,收到应答之后找到对应的会话,执行下半部分的commit,send应答,绑定到epoll等操作。绑定到epoll之后这个连接又可以被其他线程检测到并执行了。

改造后性能提升明显,如图8所示。

 

 

图8 改造后的性能

数据高可用性保障机制

除上述强同步机制外,TDSQL还做了以下增强,以提升数据的可用性。

♦  推荐一个set最少配置3个跨IDC的节点,可以按业务的要求对备机开放查询服务。

♦  支持灵活增加节点,比如觉得3个节点还不够,可以非常方便地增加节点。TDSQL会自动完成数据的全量和增量复制,此处主要依赖Xtrabackup实现物理复制,性能测试数据表明:一个小时大概可以拷贝500GB数据到新节点。那么对于Z3(1.1TB盘,一般最多用800GB左右),新加入的节点大概1.5个小时左右就有了全量数据,此功能也可以用在坏盘等情况下替换节点的时候使用,非常方便。

♦  细心的同学可能会发现上面的强同步还有点小缺陷:比如主机用kill -9杀掉,那么可能写了binlog但没有来得及发送到远端,此时当然也不会返回给业务成功,备机上不存在这笔数据,但主机起来之后会多出来这笔事务。我们的做法是对新增的事务根据row格式的binlog做闪回,当然回退不了的比如drop table之类的,就直接提醒运维手工确认是否清除数据库,然后会由Xtrabakcup机制自动从新的备机全量拉取数据重构。

♦  节点的监控通过跨IDC部署的ZooKeeper来保证,并且主备切换由一套自动化的严格流程来保证。

接下来的方向

♦  当将高一致性容灾、高可用性、自动容量伸缩做实后,随着业务的接入,集群的规模会越来越大,TDSQL必将会更加依赖实时的资源调度、隔离框架,因此有必要研究如何将TDSQL与Docker结合起来。

♦  如前所述,Galera集群是个非常好的发展方向,我们会持续研究并实践。

♦  目前大部分MySQL还在使用单个连接单线程模型,线程池也刚起步,以后随着大家对性能要求越来越高,这块也许可以继续突破,比如结合线程池+协程也许是个很好的方向,如果真能引入协程,也许为MySQL增加调用外部接口的结构会灵活很多。

♦  TDSQL将数据拆是拆的彻底了,但作为完整的分布式数据库、合也需要考虑,比如跨库少量记录的join,规模受限的分布式事务等,目前的做法是数据按小时入TDW,在TDW上做OLAP分析。

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值