• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

张秋天

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

分库分表问题

分库分表-数据库瓶颈

分库分表,首先得知道瓶颈在哪里,然后才能合理地拆分(分库还是分表?水平还是垂直?分几个?)。

IO瓶颈、CPU瓶颈,都会导致数据库活跃连接数增加。

对于服务层,数据库连接少、甚至无连接可用,会产生大量超时报错

IO瓶颈

磁盘读IO瓶颈,热点数据太多,数据库缓存buffer pool 放不下,每次查询时产生大量io,降低查询速度 -> 分库 和 垂直分表。

网络IO瓶颈,请求的数据太多,网络带宽不够 -> 分库。

CPU瓶颈

SQL问题,如SQL包含join,group by,order by,非索引字段条件查询等,增加CPU运算的操作

  • SQL优化,建立合适的索引
  • 在业务Service层进行业务计算

单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈。水平分表

 

分库分表

水平切分-分片架构

分库还是分表?

建议分库,而不是分表: 

  • 分表,公用一个数据库文件,仍然有磁盘IO 竞争
  • 分库,将数据迁移到不同数据库实例,甚至数据库机器上,扩展性更好

水平切分算法:范围法、哈希法

 

1、水平分库-分片架构

数据量很大,单库容量成为瓶颈。线性提升数据库写性能,降低单库数据容量。

 

系统绝对并发量上来了,分表难以根本上解决问题,还没有明显的业务归属来垂直分库。

库多了,io、cpu 压力自然成倍缓解。

 

分片特点

以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库。

  • 每个库 之间 不直接产生联系,不像主从间有binlog同步
  • 每个库的结构一样;
  • 每个库的数据都不一样,没有交集;所有库的并集是全量数据;

2、水平分表

以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表。

  • 每个表的结构都一样;
  • 每个表的数据都不一样,没有交集;所有表的并集是全量数据;

场景

  系统绝对并发量没有上来

  单表的数据量太多,影响了SQL效率,加重了CPU负担。

分析

表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。

 

垂直切分

和业务结合比较紧密。 

垂直分库

数据量、请求量,系统绝对并发量上来了,可以抽象出单独的业务模块。

 

以表为依据,按照业务归属不同,将不同的表拆分到不同的库。

  • 每个库的结构都不一样;
  • 每个库的数据也不一样,没有交集;所有库的并集是全量数据;

 

垂直分表

场景

系统绝对并发量没有上来

表的记录不多,但是字段多,热点数据、非热点数据在一起,单行数据所需的存储空间较大。

 

导致,buffer pool 缓存的数据行减少,查询时会去读磁盘数据,产生大量的随机读IO,产生IO瓶颈。

解决

以字段为依据,根据业务对数据进行垂直切分。

考虑属性 长度、访问频率 两个因素,将表中字段拆到不同的表(主表、扩展表)。

  • 长度短,访问频率高,热点数据放一起,主表
  • 长度长,访问频率低,非热点数据放一起,扩展表

 

长度短、访问频度高的属性,buffer pool能缓存更多的热点数据,命中率会更高,减少了随机读IO。

  

关联数据

拆了之后,要想获得全部数据就需要关联两个表来取数据。

千万别用join

  join增加CPU负担

  将两个表耦合在一起(必须在一个数据库实例上)。

 

在业务Service层做关联,分别获取主表、扩展表数据,然后用关联字段关联得到全部数据。

 

 

 

 

 

分库分表步骤

一、容量估算评估分库、分表个数

  • 容量估算依据2点:现有数据、增长趋势,照着业务规划预估容量

二、选key(均匀)

  • 数据量均匀
  • 请求量均匀

三、分表规则(分库分表分片键的设计)

  • range、hash、一致性hash、snowflake分片

四、执行(一般双写)

五、扩容问题(尽量减少数据移动)

 

分库分表问题

一、非partition key查询

基于水平分库分表,拆分策略为常用的hash法。

除了partition key,只有一个非partition key 作为条件查询

  • 映射法
  • 基因法
  • 冗余法

二、非partition key跨库跨表分页查询问题

用NoSQL法解决(ES等)

三、跨节点聚合

四、跨节点join

五、扩容问题

六、分布式事务

2pc、3pc 对性能损耗大,可改用事务补偿机制。

 

水平扩容库,升级从库法

双倍扩容策略,减少数据迁移。无需停止应用服务器

有 2 个节点 A、B,双倍扩容至4 个节点

1)新增两个数据库 A2、B2 作为从库,设置主从同步关系:A=>A2、B=>B2,主从数据同步

2)调整分片规则

  • 原 id%2=0 => A 改为 id %4=0 => A,id%4=2 => A2
  • 原 id%2=1 => B 改为  id %4=1 => B,   id%4=3 => B2

3)解除主从同步关系

四个节点的数据都已完整,只是有冗余(多存了和自己配对的节点的那部分数据),择机清除。

 

2的幂和数据迁移

容量规划按照2的幂来规划的,扩容的时候,也按照2的幂进行的

基本扩容都选择容量翻倍

2的特性,哈希取余,可以使用位运算来计算余数,高效。

扩容为原来的2倍,只需要迁移一半的数据。

 

 

100亿数据迁移执行流程

大概有10个步骤:

1、 环境准备:线上库配置完成

2、 全量同步:数据迁移工具上新建2张表(积分表、明细表)的全量任务

3、 增量同步:全量迁移完成后开启增量(自动回溯全量开始时间,消息多次消费会进行幂等)

4、 数据校验:全量数据校验,查看数据是否一致

5、 切流测试:改造代码预发测试(采集线上流量进行回放,多种case跑一下,切流开关等校验),没问题发布上线

6、 二次校验:再次全量进行校验&订正(数据追平)

7、 开启双写:打开双写(保证数据实时性)既写老库,又写新库

8、 开启读灰度:低峰时段,进行灰度切流userId%x,进行验证,逐步流量打开,持续观察

9、 只写新库:写流量切到新库,只写新库,不写老库。完成数据迁移方案

10、 迁移完成:系统稳定运行一段时间,迁移&双写代码下线,老库进行资源释放

 
 
 

分库分表如何容量预估,怎么计算需要多少个库多少个表?

 
 
 
 

posted on 2025-11-23 23:18  张秋天  阅读(2)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3