一、mysql的主从复制架构
一、为什么要搭建mysql的主从复制架构
简单点就是为了防止主机宕机后从机可以顶替主机干活。而且主从复制可以实现读写分离,主机(master)进行写操作,从机(slave)进行读操作。尽量的减少各个节点的压力。
普通主从复制:
实现了读写分离的主从架构:
1、我们先来说说这个复制数据的原理过程
首先mysql在执行增删改的时候都会记录binlog日志,然后从库上有一个IO线程,这个线程会和主库建立一个TCP连接,然后后面会通过该连接请求master传输binlog日志给自己,这个时候主库会有一个IO dump线程会通过这个TCP连接把binlog日志传输给从库的IO线程。从库的IO线程会将读取到的binlog日志数据写入到自己本地的relay日志文件中,然后从库会有另外一个sql线程去读取relay日志的内容进行日志重做(就是把主库上的操作重做一遍)。
二、搭建一套mysql的主从架构
三、如何解决主从复制的各种问题?
问题来了。不管是在普通的主从复制(主从备份)或者实现了读写分离的主从复制架构。此时都会有主机向从机复制数据的过程。如果此时突然主机宕机了,那最新的一些数据是否来的及更新到slave?我现在往master中写入数据,然后迅速去从机读取数据,这个时候是否能即时的读到我刚才修改的数据?
1、数据延迟问题(异步复制情况下)
不能实时复制,此时就存在数据延迟问题。而此时的主从架构就存在主从延迟的问题。(不仅因为不能实时复制,有时多线程进行写入,而复制线程只有一个,此时肯定忙不过来)
此时如果想看主从之间延迟了多少时间,可以用一些工具来监控。例如percona-toolkit工具集的pt-heartbeat工具,他会在主库中创建一个heartbeat表,然后有一个线程定时更新这个表里的时间戳字段,从库有一个monitor线程负责检查从库同步过来的heartbeat表的时间戳。然后把从库从主库传来的时间戳和当前时间戳比较就知道落后了多长时间。
而对于数据延迟问题,我们就是需要尽可能的缩小主从同步的延迟时间。那么该怎么做呢?
(1)、让从库也用多线程并行复制数据,这样主从复制数据的速度快了,延迟也就低了。从mysql5.7开始就支持并行复制,可以在从库中设置slave_parallel_workers > 0, 然后把slave_parallel_type设置为logical_clock。这样就设置成功了。
如果此时你需要对刚写入的数据要求立马可以读到更新的值。此时你可以使用mycat或者sharding-jdbc等中间件设置强制读写都从主库走。
如果你对mysql做高可用保证数据绝对不丢失的话,建议使用半同步机制+从库的并行复制机制。
二、mysql的高可用
一、基于MHA搭建高可用环境
高可用和主从架构的搭建会用一篇文章来说明,这里不做分析。
三、分库分表
一、上亿数据量的用户如何进行水平拆分?
通常常用的支持分库分表操作的中间件有sharding-sphere和mycat两种。一般除非数据量太大不得不进行分库分表,否则是不建议使用分库分表的,因为分库分表会遗留很多问题。
如果此时我们有一张用户信息单表,此时主从用户有几千万,那么此时如果我们对该表进行搜索,即使我们建立了索引,但因为数据量太大,此时的索引树的层级很高,搜索起来还是要费很多时间的。而为了降低索引树的层级,此时我们可能会考虑使用分库分表技术,将一张表的数据分为多张表进行存储。一张表的存储行数一般要控制在500万行以内。
而此时怎么进行分表操作?
例如此时有用户表:userid和username。此时就可以对userid进行hash然后对表进行取模分别存在在各自的标准。最后在中间间上做一个路由,这样查询时就可以根据userid查到对应在那张表中了。但这里有一个问题,一般我们登录的时候不是根据userid登录的,而是根据username或者手机号登录的。此时我们就需要建立一张映射表(username和userid的一 一对应),然后再对username再做一次分库分表。然后用户登录就可以先根据username找到userid,然后再根据userid找到相应的信息。
但这个过程设计两次查询,性能上有一定的损耗,不过为了解决分库分表的问题也只能这样了。(这就是分库分表中会涉及的类似问题)。
如果此时要对用户表进行复杂的搜索,此时用分库分表可能要进行更多的建表和查询过程,此时最好是对你的用户数据表进行binlog监听(模拟从库获取binlog日志进行数据复制,例如阿里的cannl中间件),然后对接到es中,这样就可以对数据进行复制的搜索了。
二、如何进行跨库的分页操作?
例如订单表。此时某个用户查看自己的的订单时需要分页,且存在已付款、待收货、已完成等多种状态的筛选条件。
此时我们只能使用一个映射表,将 userid+orderid+这些筛选条件 做一个映射表,然后需要分页查询时,直接根据userid去映射表中找到所有的订单然后进行分页。
如果是运营端要对所有用户的订单进行检索时,此时用es是最好的选择。
网上说的一些将各个分库的数据拿进内存,然后基于内存进行筛选和分页,其实这种方法性能哥效率极差,都是几秒的速度。
一般还是建议根据建立映射表来解决这个问题。
三、分库分表技术方案的后续扩容
预设多张表以防后面扩容。
至此,狸猫技术窝的mysql专栏总结完了。这个专栏中对锁等方面的说明还是不够的,还有一些细节方面可能铺开讲。后续会去看姜承尧的DBA实战课程,进一步的巩固扫盲。后续的mysql高可用、主从等架构的搭建也会在其中的mysql笔记专栏中体现