6-3 MySQL分库分表与集群管理

1. 为什么需要分库分表?

关系型数据库,表中管理的数据以行记录为单元。当一张表的数据达到上千万条时,随之带来的是更高的磁盘、IO、系统开销,更复杂的索引维护,以及性能上的瓶颈。而一台服务的资源终究是有限的,因此需要对数据库和表进行合理拆分,从而使其更好的提供数据服务。

分库分表的目的在于:减小数据库的负担,提高数据库的效率,缩短查询时间。另外,因为分库分表这种改造是可控的,底层还是基于数据库管理系统,因此整个数据库的运维体系以及相关基础设施都是可重用的。

分库概念:一个系统的多张数据表,存储到多个数据库实例中;

分表概念:对于一张多行(记录)多列(字段)的二维数据表,分两种分表操作:

  • (1) 垂直分表: 竖向切分,不同分表存储不同的字段,可以把不常用或者大容量、或者不同业务的字段拆分出去;
    优点:可以实现热数据和冷数据的分离,将不经常变化的数据和变动较大的数据分散再不同的库/表中。
    缺点:没有解决数据量大带来的性能损耗,读写压力依旧很大。
  • (2) 水平分表(复杂): 横向切分,按照特定分片算法,不同分表存储不同的记录。例如根据年份来拆分不同的数据库。每个数据库结构一致,但是数据得以拆分,每个子表记录数量得到降低,从而提升性能。
    优点:单库(表)的数据量得以减少,提高性能。提高了系统的稳定性和负载能力。切分出的表结构相同,应用程序只需要做子表的映射即可。
    缺点:数据分片在扩容时需要迁移。数据库维护成本增加。

2. 主从复制,读写分离

高并发业务服务器端,如果将对数据库的读和写都放在同一个数据库实例中,无疑是低效率的。因为读、写操作会涉及到锁的竞争,尤其是写操作,通常一个事务进行写操作时,其它并发的事务则会因为排他锁而阻塞。而在实际的业务作业中,对数据库的操作总是读多写少的,并且读的效率也高于写操作。因此,将数据库架构设计成主从集群,读写业务分离,对于高并发的数据访问是高效的解决方法。

主从架构除了带来支持高并发的优点,还使得MySQL数据库具有高可用的能力。主从架构中,若主服务器宕机,从服务器可以快速顶替,使得服务器具有高可用、容灾能力。

2.1 主从架构

图片说明

如图所示为3个节点的主从架构的基本示意图,3个MySQL集群中1个节点为主库(Master),2个节点为从节点(Slave):

  • 1.主库负责接收用户的写操作,并通过更新二进制日志BINLOG通知从库更新数据。
  • 2.从库主要负责用户的读操作(分担主服务器的读写压力),并且负责重放Master的写操作(即复制主库做的写操作),从而保证集群数据一致性、高可用、实现容灾能力。
  • 3.Proxy: sql语句代理,对读写操作请求的SQL指令进行路由,使得读写分离。
  • 4.Direct: 负载均衡组件, 对Mysql Proxy分发得读操作,按照一定得一致性哈希等算法进行分发至后端的从库。

2.2 MySQL数据复制过程解析(Replication)

MySQL的数据复制(Replication)过程是将一个MySQL实例中的数据复制到另一个MySQL实例中。

MySQL的复制(replication)是一个异步的复制,从一个MySQLinstace(Master)复制到另一个MySQLinstance(Slave)。Replication功能的出现能够非常方便将某一数据库中的数据复制到多台服务器中的数据里实例中,从而实现数据备份、主从热备、数据库集群等功能。且整个过程是异步进行的,复制的延时非常小,有效的提高了数据库的处理能力,提高了数据安全性等。

整个复制操作主要由三个进程完成的,其中两个进程在Slave服务器上(Sql进程和IO进程),另外一个进程在Master服务器(IO进程)上。

要实施复制,首先必须打开Master端的bin-log功能,整个复制过程实际上就是Slave从Master端获取该日志然后再在自己端完全顺序的执行日志中所记录的各种操作。复制的基本过程如下:

  • (1)Slave端的I/O进程与Master端的I/O进程建立连接,Slave请求监控bin-log日志,当发现bin-log日志发生变化后请求获取指定位置的bin-log文件的日志内容,
  • (2)Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取指定日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
  • (3)Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的某个位置开始往后的日志内容,请发给我”;
  • (4)Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行

2.3 MySQL主从复制模式

    1. 异步复制(Asynchronous replication),即主库(Master)在执行完客户端提交的事务后会立即将结果返给给客户端,主库(Master)并不关心从库(Slave)是否已经复制了本次的写操作。异步复制效率较高,因为主库不关心从库的操作。但缺点也较为明显,即主从的数据一致性无法保障,从而影响高可用和容灾能力。
    1. 全同步复制(Fully synchronous replication),即主库(Master)执行完一个事务后不会立即返回客户端执行结果,而是等待所有的从库都执行了该事务才返回给客户端。全同步复制能够保证主从的数据一致性,但缺点是主库完成一个事务的时间会被拉长,性能降低。
    1. 半同步复制(Semisynchronous replication),介于全同步复制与全异步复制之间的方式,主库(Master)只需要等待至少一个从库(Slave)收到主库执行的事务修改并复制动作的应答,而不需要等待所有从库给主库反馈。半同步复制能够很大程度上提高效率,同时保证主从的数据一致性。

2.4 bin-log记录方式

  • 1.基于SQL语句的复制(statement based replication),Master端将每一条会修改数据的SQL记录下来,Slave端在复制的时候会根据二进制文件重新执行相同的SQL。这种模式的优点是Master端不需要记录每一行数据的变化(只记录sql query的执行动作),二进制日志文件量小,IO成本低,速度快。缺点是从库需要执行主库相同的SQL,就需要额外的知道每条语句执行的上下文信息,以保证该相同的操作在Slave端执行时能够得到和Master同样的结果。且并非所有的SQL语句都能被复制,当SQL操作不确定或操作较为复杂时可能导致从库执行失败。
  • 2.基于行记录的复制(row based replication),该模式的主要流程是,MySQL二级制日志文件会将每一行数据修改都记录下来,然后在Slave端进行同样的修改。这种模式的优点是:日志文件不需要将SQL语句执行的上下文记录下来,只是记录哪一条数据修改了,修改成什么样子了。相较于基于SQL语句的复制,基于行记录的复制在任何情况都可以被复制,是相对安全可靠的复制方式。
    缺点是bin-log的存储成倍增加。例如:执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。这样就大增加了复制过程的IO成本,导致速度下降、性能下降。
  • 3.混合方式复制(mixed based replication), 该模式结合了之前两种模式的优点,规避了二者的缺点。在该模式下,MySQL会根据执行的每一条语句来区分记录日志文件的格式。举例说明,当涉及到复杂的存储过程时,采用Row Level,规避Statement Level存在的某些场景无法复制的问题;当涉及到Alter table等操作时,采用Statement Level来规避Row Level带来的日志量巨大的问题。

2.5 全局事务标识(Global Transaction Identifier —— GTID)

GTID是唯一的标识符,由UUID(MySQL server中的全局唯一标识) + 事务id组成,一个事务对应一个GTID。GTID自动添加到事务的头部,并写入到bin-log中。GTID使得追踪和复制事务变得简单,而且能从宕机中快速恢复,如果主库(Master)宕机了,那么从库(Slave)要有顶替成为主库(Master)的方法。同理,如果宕机的机器恢复了,那么要有回到集群的方法。

以2.1节图中的3节点MySQL集群为例,假如已有MySQL集群是A为Master,B和C为Slave。此时A宕机了,需要从B和C中重新选择一个Master。replication机制是异步或半同步复制,若复制模式为半同步复制,可以通过GTID快速选择与Master保持一致的Slave成为新的Master;若复制方式为异步复制,那么B和C中的数据不一定包含了全部的A的数据,且B和C的数据也有可能不一致。此时若选择B为新的Master,根据GTID可以追踪到B和C中已完成的事务,从而将C中已完成的且B中为完成的数据迁移到B中。

全部评论

相关推荐

球球别再泡了:坏,我单9要了14
点赞 评论 收藏
分享
和蔼:在竞争中脱颖而出,厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务