mysql水平分库分表,以及线上分表方案

什么情况下去要进行分库分表?

        在业务量不大的情况下,通常使用单表在进行操作,但是随着表数据越来越大,性能也越来越差;

        mysql单表 qps 2k,树深度3层-4层,大概是单表能承受的相对最大极限;

ps: 本文不讨论分区表;

分表策略

1. rang分表,id、日期等

        单表1000,分4个库,4张表

        将每个表的初始id确定,0 - 500万, 500 - 1000 ,1000- 1500, 1500 - 2000

        插入:服务器每隔一段时间查询当前使用的 表 a (0-500)是 否快要达到临界点(450/ 500),

        如果到到达则更新到下一张表 b(500-1000),可以解决边界问题。

扫描二维码关注公众号,回复: 15114864 查看本文章

        查询:根据id就可以分配到不同表即可。

        缺点 : 高并发热点数据

        在通常业务中,新用户的活跃度是远高于老用户的,意味着热点数据全部分配在同一张表上,存在部分的资源浪费情况;

        解决方案:

                可购买不同的数据库配置存放;

        优点:

                分表比较简单,再次扩容只需要添加表就行,不存在迁移;

                id 自增生成,不依赖第三方

                很适合id自增的表分库分表

2. hash分表

        使用第三方的id生成器;比如雪花;

        将id通过hash取模分配到不同的表中。

        优点: 数据分布均匀,不会出现热点数据在一张表的情况,

        缺点: 需要维护一个高可用的id服务(可参考美团高可用雪花生成算法)

线上分表

        在线分表最需要在意的问题就是增量数据,无论是rang还是hash都存在这种问题。

        在线分表不能像停服更新一样,一次将大量数据挪到新库里,需要批量迁移,防止数据库打死;

        为了保证新旧表数据一致,还需要保持双写(新库就库都需要写);

        数据迁移:

        根据分表规则,一小段一小段的将数据迁移到新库,这个段不能太大,防止数据库被锁死

        比如1千万条数据,每次迁移1千条数据;

        对每条数据做hash分组,分批次插入,直到出现重复,代表迁移完成;

        事务顺序:

        锁旧表

        批量数据,根据hash分组到4张表

        插入新表 <---- 其中 这一步并不会锁新表,

        在排除断电等极端情况下,插入失败只会是出现重复,

        那么就意味着已经追上最新数据了,就可以停止迁移了

        解锁旧表

        缺点: 代码实现比较困难,对分布式服务还要考虑旧表何时断开等诸多细节,速度慢。

        双写同步:

        需要同时向新旧两表插入或修改

        事务顺序为:

                锁原表

                锁新表

                写入

                解锁原表

                解锁新表

        情况1:

                原表更新成功,新表更新失败。

        情况2:

                原表更新失败,新表更新失败

如出现情况2,则代表本次更新失败,但是数据是一致的,是可以接受的。

情况1则会出现数据不一致,但是原表更新成功,可以通过数据迁移完成同步,也是可以接受的。

猜你喜欢

转载自blog.csdn.net/weixin_56766616/article/details/127786185