数据库分库分表梳理

Posted 小D学Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库分库分表梳理相关的知识,希望对你有一定的参考价值。

使用分库还是分表

  • 仅数据量大,但并发数小,对CPU要求较低,可使用分表,可减少跨库等问题

  • 数据量大而且并发读高,对CPU以及其它内存资源有要求,使用分库

常见分库分表算法

  • 范围切分

    • 优势 - 扩容简单,设计简单

    • 缺点 - 数据量不均;请求量不均,当扩容刚开始时容易查询请求都落在旧库上;区分键需趋势递增

  • hash切分

    • 优势 - 资源分配较均

    • 缺点 - 扩容时比较复杂,需提前规划好

分库后存在哪些问题

  • 非关联属性查询问题

  • 跨库无法保证一致性

  • 分布式事务

  • 主键生成问题

    • 跨步长自增的数据库实现()不方便扩容)

    • 基于分布式id生成器来生成id(趋势递增/雪花算法)

非关联属性查询问题拆分

常见业务类型

  • 用户侧,对实时性以及一致性有一定要求

  • 运营后台侧,内部系统,访问量低,对可用性要求不高,一致性要求也没那么严格

针对用户侧的设计

先假设一个场景,uid能直接定位到库,但login_name定位不了,现在需满足根据login_name能直接定位到库的需求

方案如下

  • 映射法 -- 表直接关联 login_name --> id,映射表一般数据量较小,无需分库,若需分库则按login_name分库

  • 基因法

  • 若是内部属性可直接在其字段上加上一个库的标志位,如商户号可直接在其规则中加上一个01这种库的基因

  • 若是外部属性如此例的登录名是由用户决定的,需将login_name按照一定的算法抽出分库基因,再基于此基因生成对应的uid

基因法详解


若有多个需查询的属性,可使用基于uid的基因来生成其它内部使用的属性,如uid生成之后基于其基因x生成orderId

扩容问题

升级从库法

  • 若在uid上做了基因标记,则需在做基因是预留多标记位;非关联属性的基因关联也是同理需预留标记位;

  • 若是采用的是映射法则无需理会非关联属性;

数据库分库分表梳理

此时,当需要扩容的时候,我们把A0和B0升级为新的主库节点,如此由2个分库变为4个分库。同时在上层的分片配置,做好映射,规则如下:

uid%4=0和uid%4=2的分别指向A和A0,也就是之前指向uid%2=0的数据,分裂为uid%4=0和uid%4=2

uid%4=1和uid%4=3的指向B和B0,也就是之前指向uid%2=1的数据,分裂为uid%4=1和uid%4=3

因为A和A0库的数据相同,B和B0数据相同,所以此时无需做数据迁移即可。只需要变更一下分片配置即可,通过配置中心更新,无需重启。

数据库分库分表梳理

由于之前uid%2的数据分配在2个库里面,此时分散到4个库中,由于老数据还存在(uid%4=0,还有一半uid%4=2的数据),所以需要对冗余数据做一次清理。而这个清理,不会影响线上数据的一致性,可是随时随地进行。

处理完成以后,为保证高可用,以及下一步扩容需求。可以为现有的主库再次分配一个从库。


分表的数据迁移


同步双写方案

第一步:应用配置双写,部署;

第二步:将老库中的老数据复制到新库中;

第三步:以老库为准校对新库中的老数据;

第四步:应用去掉双写,部署;

基于权重表以及基因法来设计分库

db_sharding(id,db_name,weight,sharding_name)

设计一张分库的权重表按照权重控制数据生成时的落在哪一个数据库,然后生成的id带分库的基因

基于以上设计即可动态扩容数据库,又可直接基于id来定位到库

在需要新增库时,在权重表新增记录,将新库对应的权重设置大一些则可将新增的数据都引向新数据库



参考链接


https://juejin.im/entry/5cb02e0d5188251ac7233c0e

以上是关于数据库分库分表梳理的主要内容,如果未能解决你的问题,请参考以下文章

DB 分库分表:关于使用框架还是自主开发以及 sharding 实现层面的考量

一种基于 MyBatis 框架的分库分表方案!

oracle分库分表

MySQL实现分库分表代码实战(Mango中间件)

系统从未分库分表动态切换到分库分表

系统从未分库分表动态切换到分库分表