工作生活

分库分表

2019-07-01  本文已影响0人  我是一名搬运工

1、为什么分库分表

        分库的原因:

        1)QPS过高,数据库响应速度来不及,一般mysql单机也就1000左右的QPS,如果超过1000,就要考虑分库。

        分表的原因:

        1)单表太大,复杂SQL的查询速度变慢,一般mysql单表也就1000万左右的量,如果超过1000万,就要考虑分表;

2、垂直拆分与水平拆分

        1)垂直拆分表

        把一个表的多个字段分别拆成多个表,一般按字段的冷热拆分,热字段一个表,冷字段一个表。拆完以后,可以放在一个库,也可以放在多个库里。

        2)水平拆分表

        把一个表按照某个字段,拆分到多个表里面,这个字段叫sharding-key。

3、Sharding-key的选择

方案一:

        可以用id的hash值取模,需要分多少个表,就取什么的模

        这种方案的缺点是如果分表的数量变了的话,所有的数据都要重新放到不同的分表

方案二:

        可以用id的一致性hash,将数据分到不同的表中

        这种方案只需要把在之前的分表,现在需要放在新的分表的数据移动即可。

方案三:

        根据时间范围来分表。

        可以划分最近3个月的数据,3-12个月的数据,12月之前的数据,这种分法可区分数据的冷热程度,对于热数据,加redis缓存访问来提高访问效率,对于3-12个月的数据,由于使用的少,可以放到ES或hbase或mongoDB里面,对于12月之前的数据,可以使用hive只支持离线统计,不支持纪录查询。

        也可以划分相同范围的时间,比如以一个月为范围划分,不断添加新的月度表。

        这种方案的缺点是数据量并发还是都作用在同一张表上,无法提高同一张表的并发效率。

4、全局唯一ID的生成

方案一:雪花模型算法

        通过雪花模型服务生成唯一ID。

方案二:mysql自增初始值与步长

        通过mysql的auto increment,从mysql取ID。

        为避免单点故障,用多台mysql服务器,每台mysql服务器上放一个自增的sequence表,自增的步长就是自增服务器的数量,sequence表的起始值分别是1,2…N。

        缺点是要两台以上mysql,废资源。

方案三:自己写编码规则

        自己写的编码规则不仅能尽量保证唯一性,还能携带业务规则,方便逻辑判断。

        一般自己写的唯一ID都会包括三部分:时间戳+随机数+某个编码。

        其中时间戳用来区分数据的冷热;某个编码可以是某个业务编码,比如用户编码、服务器编码、地域编码等等,这个业务编码也用来区分数据;随机数必须使用高唯一性随机码。

        缺点是规则设计比较难,要充分考虑业务情况。另外,由于使用了随机数,是有可能存在着ID重复的可能性的,所以要有容错机制,即如果插入的时候ID重复,那么重新生成再插入。

5、分库分表的动态扩容

        一开始就设计32个库,32个表,一次弄个够,后面就不扩了。

6、如何解决读写分离主从库数据不一致

        问题出现原因:往主库写数据以后,从库还没来得及从主库复制数据,读请求就已经发到从库了,这时从库的数据就不是最新的,查到的就不是新数据。

        解决办法:配置主库的复制策略为半同步复制,必须有一个slave节点接收到主库复制的数据,主库才认定这条SQL执行成功。

7、如何解决跨库Join的问题

        问题出现原因:分库分表以后,数据处于不同的库里,这个时候需要做关联查询

        解决办法:

        1)首先,对于这类问题,我们的首要方案是尽力避免跨库Join,避免的方式包括:

        ——采用mycat全局表,比如数据字典,在每个库里都需要用到,那我们在每个库里都放一份,然后做成全局表进行同布,这样库表跟数据字典的join就不会跨库了;

        ——采用字段冗余,比如ID和NAME,库库里只有ID,没有NAME,NAME在另一个库里,那我们在设计之初就在表里也加上NAME,这样就不用会查另一个库的表了。不过这样有个问题,就是数据不一致的问题,需要定期更新这部分数据;

        2)其次,如果已经出现了这种情况,那解决方式有:

        ——Mycat中配置表的childtable,作为它的从表,并设置joinKey,这样从表的数据也会跟主表存在一个库里面;

        ——手工查询,先主库查出来,然后一条一条从从库查,这样性能比较低。不过可以对从库的数据查询加缓存,能提高效率。

8、线上环境分库分表后的迁移

        采用双写的方式,修改代码,所有涉及到分库分表的表的增、删、改的代码,都要对新库进行增删改。

        同时,再有一个数据抽取服务,不断地从老库抽数据,往新库写,边写边按时间比较数据是不是最新的。

上一篇 下一篇

猜你喜欢

热点阅读