随着业务的发展,数据会越来越多,当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会卡死在那儿了。分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成 ,将数据大表拆分成若干数据表组成,使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的。分库分表有垂直和水平两种。
上图中标的数据达到了4000万,我们也知道mysql单表存储量推荐是百万级,如果不进行处理,mysql单表数据太大,会导致性能变慢。使用方案可以参考数据进行水平拆分。把4000万数据拆分4张表或者更多。当然也可以分库,再分表;把压力从数据库层级分开。
分库分表方案中有常用的方案,hash取模和range范围方案;分库分表方案最主要就是路由算法,把路由的key按照指定的算法进行路由存放。
在我们设计系统之前,可以先预估一下大概这几年的订单量,如:4000万。每张表我们可以容纳1000万,也我们可以设计4张表进行存储。
订单数据可以均匀的放到那4张表中,这样此订单进行操作时,就不会有热点问题。
将来的数据迁移和扩容,会很难。
如:业务发展很好,订单量很大,超出了4000万的量,那我们就需要增加分表数。如果我们增加4个表:
遇到这个情况,我们想到的方案就是做数据迁移,把之前的4000万数据,重新做一个hash方案,放到新的规划分表中。也就是我们要做数据迁移。这个是很痛苦的事情。有些小公司可以接受晚上停机迁移,但大公司是不允许停机做数据迁移的。下次8个表也不够了,又重复上面的工作。。。
range方案也就是以范围进行拆分数据。
range方案比较简单,就是把一定范围内的订单,存放到一个表中;如上图id=55放到tb2表中,id=120的放到tb3表中。设计这个方案时就是前期把表的范围设计好。通过id进行路由存放。
我们小伙伴们想一下,此方案是不是有利于将来的扩容,不需要做数据迁移。即时再增加4张表,之前的4张表的范围不需要改变,id=12的还是在0表,id=1300万的还是在1表,新增的4张表他们的范围肯定是 大于 4000万之后的范围划分的。
有热点问题,我们想一下,因为id的值会一直递增变大,那这段时间的标的是不是会一直在某一张表中,如id=1000万 ~ id=2000万之间,这段时间产生的标的是不是都会集中到此张表中,这个就导致1表过热,压力过大,而其他的表没有什么压力。
hash取模方案:没有热点问题,但扩容迁移数据痛苦。
range方案:不需要迁移数据,但有热点问题。
那有没有一个方案,即不需要迁移数据,又能解决数据热点的问题呢?
答:hash取模方案、range方案两者结合,hash是可以解决数据均匀的问题,range可以解决数据迁移问题。
我们先按range方案对数据进行分组,比如:
组 | id范围 |
---|---|
A | 1-4000 |
B | 4001-8000 |
C | 8001-12000 |
再每组按hash取模方案分库分表,比如:
id尾号 | 数据库 | 数据表 |
---|---|---|
0 | DB1 | TB1 |
1 | DB1 | TB2 |
2 | DB1 | TB3 |
3 | DB1 | TB4 |
4 | DB2 | TB1 |
5 | DB2 | TB2 |
6 | DB2 | TB3 |
7 | DB2 | TB4 |
我们看一下,id在[1,4000]范围内的数据,根据上面的流程设计,用hash的方案都均匀的分配到DB1,DB2两个数据库中的8个表中。
通过上面的方案,就解决了数据热点的问题。那扩容呢?
扩容很简单,我们再加一个组就解决了。
gong, 智能零售研发。