当前位置: 首页 > news >正文

【架构实战】数据库分库分表实战

一、为什么需要分库分表

当数据量超过单机数据库的承载能力时,分库分表成为必然选择:

  • 单库数据量过亿:查询性能急剧下降
  • 单表数据量过大:索引效率降低,DML操作变慢
  • 连接数耗尽:数据库连接成为稀缺资源
  • 存储空间不足:单机的磁盘容量有上限

二、分库分表策略

1. 垂直拆分

按业务将表或库拆分开:

原来:用户库(用户表、订单表、支付表) 拆分后: 用户库(用户表) 订单库(订单表) 支付库(支付表)

2. 水平拆分

按数据规则将表拆分:

-- 按用户ID取模分表users_0:WHEREuser_id%4=0users_1:WHEREuser_id%4=1users_2:WHEREuser_id%4=2users_3:WHEREuser_id%4=3

3. 常见的分片键选择

分片键适用场景注意事项
用户ID电商、社交查询需带用户ID
时间日志、订单冷数据归档方便
地区区域性业务跨区查询困难
哈希均衡分布查询复杂度高

三、分库分表中间件

ShardingSphere

# application.ymlspring:shardingsphere:datasource:ds0:url:jdbc:mysql://localhost:3306/db0driver-class-name:com.mysql.cj.jdbc.Driverds1:url:jdbc:mysql://localhost:3306/db1driver-class-name:com.mysql.cj.jdbc.Driverrules:sharding:tables:t_order:actual-data-nodes:ds$->{0..1}.t_order_$->{0..1}table-strategy:standard:sharding-column:order_idsharding-algorithm-name:order_inline

MyCat

四、实战代码

Java SDK 使用示例

// ShardingSphere JDBC@ConfigurationpublicclassDataSourceConfig{@BeanpublicDataSourcedataSource(){MapdataSourceMap=newHashMap<>();dataSourceMap.put("ds0",createDataSource("db0"));dataSourceMap.put("ds1",createDataSource("db1"));ShardingRuleConfigurationconfig=newShardingRuleConfiguration();config.getTables().add(createTableRule());returnDataSourceFactory.createDataSource(dataSourceMap,config);}}// 分片键获取publicLonggetShardingKey(Orderorder){returnorder.getUserId()%4;}

五、跨库查询解决方案

1. 禁止跨库JOIN

// 业务层面解决:先查用户,再查订单Useruser=userMapper.selectById(userId);Listorders=orderMapper.selectByUserId(userId);

2. 异构表

-- 在订单库冗余用户信息CREATETABLEt_order(order_idBIGINT,user_idBIGINT,user_nameVARCHAR(50),-- 冗余字段amountDECIMAL(10,2),created_atDATETIME);

3. ES搜索引擎

MySQL(分库分表) → 数据同步 → Elasticsearch ↓ 复杂查询由ES处理

六、分布式ID生成

分库分表后,需要分布式ID:

// Snowflake算法publicclassSnowflakeIdGenerator{privatefinallongtwepoch=1288834974657L;privatefinallongworkerIdBits=5L;privatefinallongdatacenterIdBits=5L;publicsynchronizedlongnextId(){longtimestamp=timeGen();longid=((timestamp-twepoch)<<22)|(datacenterId<<17)|(workerId<<12)|sequence;returnid;}}// 使用SnowflakeIdGeneratoridGenerator=newSnowflakeIdGenerator(1,1);longorderId=idGenerator.nextId();

七、常见问题与解决方案

Q1:扩容时如何迁移数据?

  • 方案1:双写(新老库同时写)
  • 方案2:定时任务迁移
  • 方案3:使用一致性哈希减少迁移量

Q2:如何保证分页查询?

-- 反例:深分页问题SELECT*FROMt_orderORDERBYidLIMIT1000000,10-- 正例:游标分页SELECT*FROMt_orderWHEREid>1000000ORDERBYidLIMIT10

Q3:分布式事务如何处理?

使用 Seata AT 模式或 TCC 模式

八、总结

分库分表是系统扩展的必经之路,但增加了系统复杂度:

  • ✅ 突破单机性能瓶颈
  • ✅ 提高系统可用性
  • ❌ 跨库查询困难
  • ❌ 运维复杂度增加

思考题:你的系统中数据量最大的是哪张表?有没有考虑过分库分表?


个人观点,仅供参考

http://www.jsqmd.com/news/537492/

相关文章:

  • OpenClaw+nanobot:个人财务数据分析助手
  • 苍穹外卖项目密码加密存储详解:从MD5到Spring Security的进阶之路
  • 【紧急预警】Python工业网关Log4j2变种漏洞(CVE-2024-XXXXX)正在产线蔓延!3行patch代码立即生效
  • 软考-信息系统项目管理师-项目沟通管理-知识点及考点预测
  • Fast DDS vs. ROS 2 vs. ZeroMQ:在机器人项目中,我们该如何选择中间件?(性能、易用性、生态对比)
  • SEO_掌握这七个SEO核心技巧,让排名稳步上升
  • 基于Dify打造Z-Image-Turbo可视化工作流:无需代码构建AI应用
  • STM32L0待机模式唤醒后程序跑飞?用LL库/HAL库正确处理系统复位与初始化
  • 告别插件冲突!手把手教你手动安装Obsidian动态目录插件(Dynamic Table of Contents)
  • 基于AntV X6构建智能客服对话流程图:AI辅助开发实战与性能优化
  • NMOS vs PMOS防反接:3个实际案例告诉你哪种方案更省电
  • 基于YOLOv12与Flask-SocketIO的番茄成熟度Web端实时检测系统设计与性能对比
  • GLM-OCR轻量级部署方案:CPU模式运行(FP16量化),满足边缘设备需求
  • 告别配对烦恼:用Auracast蓝牙广播,让手机、耳机和电视实现一拖多音频共享
  • NaViL-9B惊艳案例:手写体识别+语义理解+颜色布局描述三合一效果
  • 壹方设计联系方式查询:如何高效联系并了解其高端整案家居服务详情 - 品牌推荐
  • 融合二自由度模型与卡尔曼滤波的质心侧偏角动态观测器设计
  • Superpowers 系统学习笔记:AI编程Agent的完整开发方法论
  • Kali Linux下inviteflood实战:如何用SIP洪水攻击测试你的VoIP系统安全(附防御建议)
  • SM4加密在Uniapp中的性能优化与安全实践
  • 壹方设计联系方式查询:如何高效联系官方服务网点并了解其整装家居服务特色 - 品牌推荐
  • AI辅助编程新体验:使用IDE插件集成MiniCPM-o-4.5模型
  • 造相-Z-Image效果对比:Z-Image在中文语义理解准确率上超越SDXL实测
  • 从状态机到用户体验:为你的Arduino项目添加EC11编码器进度条反馈
  • Windows 10/11 下保姆级教程:用 TensorRT 8.4.3.1 给 YOLOv8 模型加速(附完整属性表配置与常见DLL缺失解决方案)
  • 深入理解 SageMaker HyperPod 的异构 GPU 调度:从 Whisper 部署看 EKS 集群架构设计
  • 腾讯Covo-Audio:70亿参数全双工语音交互黑科技
  • YOLO12在无人机视觉中的应用:航拍目标检测
  • YOLOv12惊艳效果展示:注意力机制让目标检测更精准
  • Linux桌面定制——快速迁移状态栏位置的终端技巧