MySQL集群基础概念

162 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情

1. 数据的切分

MySQL单表数据超过两千万,CRUD性能就会急速下降,所以我们需要把同一张表的数据切分到不同的MySQL节点中。这需要引入MySQL中间件,其实就是个SQL路由器而已。这种集群中间件有很多,比如MyCat、ProxySQL、ShardingSphere等等。因为MyCat弃管了,所以通常选择ShardingSphere,功能不输给MyCat,而且还是Apache负责维护的,国内也有很多项目组在用这个产品,手册资料相对齐全,所以相对来说是个主流的中间件。

image.png

我们在MySQL_1和MySQL_2两个节点上分别创建表,然后在ShardingSphere做好设置。如果INSERT语句主键值对2求模余0,这个INSERT语句就路由给MySQL_1节点;如果余数是1,INSERT语句就被路由给MyQL_2执行。你看,通过控制SQL语句的转发就能把订单数据切分到不同的MySQL节点上了。将来查询的数据的时候,ShardingSphere把SELECT语句发送给每个MySQL节点执行,然后ShardingSphere把得到的数据做汇总返回给Navicat就行了。我们在Navicat上面执行CRUD操作,几乎跟操作单节点MySQL差不多,但是这背后确实通过路由SQL语句来实现的。

即便海量数据可以切分到不同的MySQL节点,但是日积月累,每个MySQL里面的数据还是会超过两千万的,那该怎么办?这个也简单,做数据归档就好了。对于1年以上的业务数据,可以看做是过期的冷数据。我们可以把这部分数据转移到归档库里面,例如ToKuDB、MongoDB或者HBase里面。这样MySQL节点就实现缩表了,性能也就上去了。比方说你在银行APP上面只能插到12个月以内的流水账单,再早的账单是查不到的。这就是银行做了冷数据归档操作,只有银行内部少数人可以查阅这些过期的冷数据。

2. 数据同步

数据切分虽然能应对大量业务数据的存储,但是MySQL_1和MySQL_2节点数据是不同的,而且还没有备用的冗余节点,一旦宕机就会严重影响线上业务。接下来我们要考虑怎么给MySQL节点设置冗余节点。

MySQL自带了Master-Slave数据同步模式,也被称作主从同步模式。例如MySQL_A节点开启了binlog日志文件之后,MySQL_A上面执行SQL语句都会被记录在binlog日志里面。MySQL_B节点通过订阅MySQL_A的binlog文件,能实时下载到这个日志文件,然后在MySQL_B节点上运行这些SQL语句,于是就保证了自己的数据和MySQL_A节点一致。

image.png

MySQL_A被称作Master(主节点),MySQL_B被称作Slave(从节点)。需要注意,主从同步模式里面,数据同步是单项的,如果你在MySQL_A上写入数据,可以同步到MySQL_B上面;如果在MySQL_B上面写入数据,是不能同步到MySQL_A节点的。于是我们要配置双向主从同步,也就是互为主从节点。

image.png

MySQL_A订阅MySQL_B的日志文件,MySQL_B订阅MySQL_A的日志文件,这样无论我们在哪个节点上写入数据,另一个节点就会自动同步到了。

3. 读写分离

绝大多数Web系统都是读多写少的。所以搭建MySQL集群的时候,就要划定某些节点是读节点,某些节点是写节点。

image.png 我规划的是MySQL_1为写节点,MySQL_2和MySQL_3是读节点。多配制一些读节点也没问题,毕竟系统的读任务比较多。但是主从同步有个问题就是Master和Slave身份是固定,如果MySQL_1宕机,MySQL_2和MySQL_3都不能升级成写节点。那怎么办呢,给MySQL_1加上双向同步的MySQL_4节点。

image.png

ShardingSphere会轮询的方式给MySQL_1和MySQL_4发送写操作的SQL语句(INSERT、DELETE、UPDATE等);如果是查询语句,ShardingSphere会发给其余四个读节点去执行,这就实现了读写分离。假设MySQL_1宕机,ShardingSphere通过心跳检测能知道,于是所有的写操作就转发给MySQL_4。反之如果MySQL_4宕机,MySQL_1也会接替工作。在上面示意图中的6个MySQL节点,无论哪一个宕机都不影响数据库整体的使用,都有各自的冗余节点。

4. 数据库分片

上面的6个MySQL节点并不是最终的MySQL集群方案,因为无论我在MySQL_1或者MySQL_4写入数据,最终都会同步给其他的节点,也就是说数据不能实现切分。于是我们要引入数据库分片概念,分片内部数据可以做读写分了和主从同步,但是分片之间数据是不能同步的。

image.png

如上图,前6个节点组成了第一个MySQL分片,后6个MySQL节点组成了另一个MySQL分片,两个分片之间没有任何的数据同步。这时候ShardingSphere把各种SQL语句路由给相应的MySQL分片,数据就实现了切分。

例如分片A中我只保留了一个MySQL节点,其余五个节点都不需要。分片A和分片B切分的是某些数据表,比如司机表和钱包表的数据等等,分片C和分片D切分其他一些数据表的记录。