MySQL是互联网最常用的开源数据库产品,平常开发大都使用单机服务。而实际生产中,往往数据量很大,且对数据安全性要求也很高。单机必然不能满足。因此生产环境中,必须要搭建一套MySQL主从复制的架构,同时可以基于一些工具实现高可用架构。然后可以在此基础上,基于一些中间件实现读写分离架构,最后如果数据量非常大,还可以实现分库分表架构。

单机--》主从复制(高可用,自动切换)--》读写分离--》分库分表

搭建主从集群

主从架构的好处:可以缓解数据存储及访问的压力。

        1、数据安全,主服务增加了数据备份

        2、读写分离,大部分业务场景都是读多写少,当读的请求远远高于写请求时,可以将读请求由从服务来分担。主从架构只是实现读写分离的一个基础,实现读写分离还需要一些中间件来支持,如:ShardingSphere

        3、故障转移-高可用,当MySQL主服务宕机后,可以由一台从服务切换为主服务,继续提供数据读写功能。为了实现MySQL自动主从切换,还需要依靠其他的中间件,e.g. MMM、MHA、MGR。

一般项目中,如果数据库访问压力没有那么大,读写分离不是必须要做的,但,主从架构和高可用架构规则是必须要搭建的。

同步的原理

         MySQL服务的主从架构一般都是通过binlog日志文件来进行。即在主服务上打开binlog记录每一步的数据库操作,然后从服务上会有一个IO线程,负责跟主服务建立一个TCP连接,请求主服务将binlog传输过来。这时,主库上会有一个IO dump线程,负责通过这个TCP连接把binlog日志传输给从库的IO线程。接着从服务的IO线程会把读取到的binlog日志数据写入自己的relay日志文件中。然后从服务上另外一个线程会读取relay日志里的内容,进行操作重演,达到还原数据的目的。

        MySQL的binlog不光可以用于主从同步,还可以用于缓存数据同步等场景。e.g. Canal可以模拟一个slave节点,先MySQL发起binlog同步,然后将数据落地到Redis、Kafaka等其他组件,实现数据实时流转。

        搭建主从集群的两个必要条件:

        1、双方MySQL版本必须一致(至少主服务的版本低于从服务)

        2、两节点的时间需要同步

读写分离,需要限制用户写入数据,可以将从服务read_only设置为1(set global read_only=1;)。read_only=1只读模式,不会影响slave同步复制;

其他集群方式

为了提高整个集群的高可用能力,可以扩展出多主的集群,可以扩展出互为主从的互主集群,甚至是环形的主从集群,实现MySQL多活部署。

半同步复制

        由于发送binlog是异步的,如果主服务宕机了,而从服务还没有备份到新执行的binlog,那就有可能会丢数据。半同步复制机制是一种介于异步复制和全同步复制之间的机制。主库在执行完客户端提交的事务后,并不是立即返回客户端响应,而是等待至少一个从库接收并写到relay log中,才会返回给客户端。MySQL在等待确认时,默认会等10秒,如果超过10秒没有收到ack,就会降级成为异步复制。半同步复制基于lib/plugin下的semisync_master.so和semisync_slave.so两个文件。

主从架构数据延迟

出现这个问题的根本在于:主服务数据都是多线程并发写入的,而从服务是单个线程慢慢拉取binlog,这中间有效率差。所以解决这个问题的关键就是要让从服务也用多线程并行复制binlog数据。MySQL5.7版本后,就已支持并行复制。将从服务slave_parallel_workers设置为一个大于0的数,然后把slave_parallel_type设置为LOGICAL_CLOCK。

MySQL高可用方案

        MySQL主服务挂了,从服务无法自动切换成为主服务。需要借助第三方工具实现:MMM、MHA、MGR,三者共同点:

        1、对主从复制集群中的Master节点进行监控

        2、自动的对Master进行迁移,通过VIP

        3、重新配置集群中的其他slave对新的Master进行同步

分库分表

        微服务架构中,每个服务都分配一个独立的数据库,就是分库;而对一些日志表,按月拆分成不同的表,就是分表。

垂直分片:核心就是专库专用,按照业务将表进行归类,分布到不同的数据库或表中。

水平分片:又称横向分片,通过某个(几个)字段,根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。

常用的分片策略:

        取余\取模:数据存放均匀,但扩容非常麻烦

        按照范围分片:好扩容,数据分布可能不均匀

        按照时间分片:比较容易将热点数据区分出来

        按照枚举值分片:如地区

        按照字段前缀指定进行分区:自定义业务规则分片

水平分片从理论上突破了单机数据量处理的瓶颈,且扩展相对自由,是分库分表的标准解决方案。

一般在系统设计阶段就应该根据业务耦合松紧来确定垂直分库分表方案,数据量及访问量不是特别大的情况,首先考虑缓存、读写分离、索引技术。若数据量极大,且持续增长,再考虑水平分库分表方案。

分库分表引入的问题:

        事务一致性问题,分布式事务

        跨节点关联查询问题

        跨节点分页、排序函数

        主键避重问题

        公共表处理,参数表、字典表,数据量小,保存到每个数据库

        运维工作量

什么时候需要分库分表?

        阿里开发手册建议,MySQL单表记录如果达到500w,或者单表容量达到2GB,一般就建议进行分库分表。

常见分库分表组件:shardingsphere、mycat、dble