目录
MySQL主从同步原理
MySQL主从复制的核心就是二进制日志
面试回答
分库分表
分库分表的时机
分库分表的策略
垂直分库
垂直分表
水平分库
水平分表
分库分表的策略
分库之后的问题
面试回答
如果项目上线了,通常情况下,会去搭建主从的架构,一个JAVA应用,首先要去廉价而数据库的中间件,中间件其中至少连接了两个库。当主库写数据的时候,就要把数据同步到从库,那是如何进行同步的呢?原理又是什么呢?
二进制日志(BINLOG)记录了所有的 DDL(数据定义语言CREATE,DROP,OUT)语句和 DML(数据操纵语言INSERT,UPDATE,DELETE)语句,但不包括数据查询(SELECT、SHOW)语句。
同步流程是这样的,当主库数据发生了变化,比如是一个写操作,也可以是DDL或者是DML,会把这些数据写到一个blog日志文件中,这时候,从库有一个IOthread线程,专门从主库的blog日志文件中读取数据,读取完成后,就会写入到从库的中继日志中,叫做Relay log。
再由从库的SQLthread线程来读取中继日志的文件,把里面的命令在重新执行一次,执行完之后,主库和从库不就保持同步了吗
复制主要分成三步:
Master 主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。
从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志 Relay Log 。
slave重做中继日志中的事件,将改变反映它自己的数据。
面试官:MySQL主从同步原理
候选人:MySQL主从复制的核心就是二进制日志(DDL(数据定义语言)语句 和 DML(数据操纵语言)语句),它的步骤是这样的:
第一:主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。
第二:从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志 Relay Log 。
第三:从库重做中继日志中的事件,将改变反映它自己的数据
在主从同步阶段,主库和从库的数据是一样的,主要解决的是访问的压力,让读写分开进行,它是解决不理海量数据存储的问题的,这个时候,就需要分库分表
当然分库分表也不是一开始就需要的,而是有前提的
1,前提,项目业务数据逐渐增多,或业务发展比较迅速(单表的数据量达1000W或20G以后 )
2,优化已解决不了性能问题(主从读写分离、查询索引…)
3,IO瓶颈(磁盘IO、网络IO)、CPU瓶颈(聚合查询、连接数太多)
分库分表主要解决的是存储的压力,本来只有一个库,现在分了多个库进行存储,是不是就可以存储更多的数据,同时因为我有多个库,那我每一个节点是不是都可以处理用户的请求呢,是不是就可以增加用户的连接数
以表为依据,根据业务将不同表拆分到不同库中。
如图,这是一张电商的数据库,前面两张都是和用户有关系,中间两张都是和订单有关系,后面两张是和商品有关系
所以现在我们可以根据不同的业务将不同的表存储到数据库中,这就是典型的垂直分库。而微服务不就是不同的服务对应不同的数据库,如图,不同的服务与不同的数据库相对应
特点:
1,按业务对数据分级管理、维护、监控、扩展
2,在高并发下,提高磁盘IO和数据量连接数
以字段为依据,根据字段属性将不同字段拆分到不同表中。
拆分规则:
1,把不常用的字段单独放在一张表
2,把text,blob等大字段拆分出来放在附表中
如图,前面的字段都是对于商品的基本描述,而最后的description描述则是大文本内容,所以我们将表拆为基本信息和详细信息,这两个表分别存储不同的数据,其中两张表之间是1对1的关系
特点:
1,冷热数据分离
2,减少IO过渡争抢,两表互不影响
将一个库的数据拆分到多个库中。
当数据量越来越大,如果还放在一起可能会影响性能,这个时候我们就需要把他拆到各个库中进行存储。
如图,每个库中存储的数据是不一样的,所有的库加起来,才是这个订单业务的所有的数据,但是此时出现了一个问题,现在有三个库,那我们应该如何找到数据并且进行查询呢?
在我们查询的时候,其实是有一些路由的规则
1,根据id节点取模
2,按id也就是范围路由,节点1(1-100万 ),节点2(100万-200万)
…
特点:
1,解决了单库大数量,高并发的性能瓶颈问题
2,提高了系统的稳定性和可用性
将一个表的数据拆分到多个表中(可以在同一个库内)。
特点:
优化单一表数据量过大而产生的性能问题;
避免IO争抢并减少锁表的几率;
在一开始的时候,我们的应用程序只是连接了其中的一个库,
现在我们一个应用程序连接了三个库,还要按照取模的方式去找到各个数据库,假如后面因为业务要求,又做了集群,实现起来就会越来越复杂,就会产生一系列的问题
1,分布式事务一致性问题
现在有多个库,多个表,现在要同时操作在不同数据库中的不同的表,每一个库都会管理自己的事务,假如有一个库它的提交失败了,这个时候是不是就会产生事务不一致的问题
2,跨节点关联查询
假如做了分库分表,现在你的a库和b库分别存储的是不同的表,两张表还要进行关联,这个又怎么做呢
3,跨节点分页、排序函数
和2一样,这种排序,分页又要怎么做呢,即使说是取模,那有应该怎么去分页查询这些数据呢
4,主键避重
假如现在做了水平分库,每个库中存储的都是相同的表,每个表中的id可能都是自增的,会不会出现id重复的情况呢
为了避免上述问题的产生,一般在项目中使用分库分表的话,都会去增加一个中间件,进行关联,并且可以帮助我们降低开发的难度,并且可以帮助我们解决上述的问题
分库分表中间件。比如:
sharding-sphere
mycat
面试官:你们项目用过MySQL的分库分表吗?
候选人: 嗯,因为我们都是微服务开发,每个微服务对应了一个数据库,是根据业务 进行拆分的,这个其实就是垂直拆分。
面试官:那你之前使用过水平分库吗?
候选人: 嗯,这个是使用过的,我们当时的业务是(xxx),一开始,我们也是单库,后 来这个业务逐渐发展,业务量上来的很迅速,其中(xx)表已经存放了超过 1000万的数据,我们做了很多优化也不好使,性能依然很慢,所以当时就使 用了水平分库。
我们一开始先做了3台服务器对应了3个数据库,由于库多了,需要分片,我 们当时采用的mycat来作为数据库的中间件。数据都是按照id(自增)取模 的方式来存取的。
当然一开始的时候,那些旧数据,我们做了一些清洗的工作,我们也是按照 id取模规则分别存储到了各个数据库中,好处就是可以让各个数据库分摊存 储和读取的压力,解决了我们当时性能的问题