为什么要分库分表
一般的机器(4核16G),单库的MySQL并发(QPS+TPS)超过了2k,系统基本就完蛋了。最好是并发量控制在1k左右。这里就引出一个问题,为什么要分库分表?
分库分表目的:解决高并发,和数据量大的问题。
1、高并发情况下,会造成IO读写频繁,自然就会造成读写缓慢,甚至是宕机。一般单库不要超过2k并发,NB的机器除外。
2、数据量大的问题。主要由于底层索引实现导致,MySQL的索引实现为B+TREE,数据量其他,会导致索引树十分庞大,造成查询缓慢。第二,innodb的最大存储限制64TB。
要解决上述问题。最常见做法,就是分库分表。
分库分表的目的,是将一个表拆成N个表,就是让每个表的数据量控制在一定范围内,保证SQL的性能。 一个表数据建议不要超过500W。
sharding-jdbc架构图分库分表,又分为垂直拆分和水平拆分。
水平拆分:统一个表的数据拆到不同的库不同的表中。可以根据时间、地区、或某个业务键维度,也可以通过hash进行拆分,最后通过路由访问到具体的数据。拆分后的每个表结构保持一致。
垂直拆分:就是把一个有很多字段的表给拆分成多个表,或者是多个库上去。每个库表的结构都不一样,每个库表都包含部分字段。一般来说,可以根据业务维度进行拆分,如订单表可以拆分为订单、订单支持、订单地址、订单商品、订单扩展等表;也可以,根据数据冷热程度拆分,20%的热点字段拆到一个表,80%的冷字段拆到另外一个表。
垂直拆分和水平拆分不停机分库分表数据迁移
一般数据库的拆分也是有一个过程的,一开始是单表,后面慢慢拆成多表。那么我们就看下如何平滑的从MySQL单表过度到MySQL的分库分表架构。
1、利用mysql+canal做增量数据同步,利用分库分表中间件,将数据路由到对应的新表中。
2、利用分库分表中间件,全量数据导入到对应的新表中。
3、通过单表数据和分库分表数据两两比较,更新不匹配的数据到新表中。
4、数据稳定后,将单表的配置切换到分库分表配置上。
分库分表如何动态扩容
设计分库分表的时候,不管3721直接就分32个库,每个库32个表,共1024个表。扩容的时候,申请增加更多的数据库服务器,装好mysql,倍数扩容,4台服务器,扩到8台服务器,16台服务器。最后,将原先数据库服务器的库,迁移到新的数据库服务器上去。
并发角度:每个库正常承载的写入并发量是1000,那么32个库就可以承载32 * 1000 = 32000的写并发,如果每个库承载1500的写并发,32 * 1500 = 48000的写并发,接近5万/s的写入并发,前面再加一个MQ,削峰,每秒写入MQ 8万条数据,每秒消费5万条数据。
存储角度:1024张表,假设每个表放500万数据,在MySQL里可以放50亿条数据。
读写分离也是分库
都分库分表了,为什么还要做读写分离?其实,读写分离跟分库分表解决的问题都是一样的。读写分离也是分库的一种。
例如,一个项目单库达到TPS1K,QPS2k,基本就很慢了。这个时候如果将单库拆成两个完全一样结构的库,一个负责写,一个负责读,这样就可以很好的进行处理性能。
读写分离,就需要用到主从同步技术。如果是写多读少,可以使用分库分表,或者M-M-S架构;如果读多写少,可以使用M-S-S,扩展4~5个S都是可以。
MySQL主从复制原理:主库将变更写binlog日志,然后从库连接到主库之后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入一个中继日志中。接着从库中有一个SQL线程会从中继日志读取binlog,然后执行binlog日志中的内容,也就是在自己本地再次执行一遍SQL,这样就可以保证自己跟主库的数据是一样的。
这里就有一个问题了。有数据传输就会有间延,一旦并发量大就有可能造成较大的间延,也产生了主从延时问题。
如何解决主从延时问题?
1、分库,将一个主库拆分为4个主库,每个主库的写并发就500/s,此时主从延迟可以忽略不计。
2、打开mysql支持的并行复制,多个库并行复制。如果说某个库的写入并发就是特别高,单库写并发达到了2000/s,并行复制还是没意义。28法则,很多时候比如说,就是少数的几个订单表,写入了2000/s,其他几十个表10/s。(所谓并行复制,指的是从库开启多个线程,并行读取relay log中不同库的日志,然后并行重放不同库的日志,这是库级别的并行。)
3、直接查主库(不推荐)
4、检查代码,一般INSERT/UPDATE后,马上进行SELECT,这种代码要避免。
网友评论