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

详解分库分表设计

详解分库分表设计

背景

​ 在传统的单机数据库架构中,所有数据都存储在同一个数据库中,随着业务规模的不断扩大,数据量和并发量也会越来越大,这会给数据库的性能和可用性带来挑战。此外,当单机数据库的容量达到瓶颈时,无法继续扩展,这也限制了应用程序的可扩展性。

​ 为了解决这些问题,分库分表技术应运而生。通过将数据分散存储在多个数据库或表中,可以减轻单一数据库的负载,提高系统的并发性能。此外,分库分表还可以支持水平扩展,使得系统能够随着业务的增长而不断扩展。

总之,分库分表是一种常用的数据库架构设计方案,可以解决数据库在数据量、并发性、可扩展性等方面面临的瓶颈问题,是大规模应用程序必不可少的技术之一。

为什么分库分表

  1. 数据量增大:当数据量逐渐增大时,单个数据库或表可能无法承载所有数据,导致性能下降,甚至崩溃

    分库分表可以将数据分散到多个数据库或表中,每个数据库或表都只负责一部分数据,从而提高系统的性能和可靠性。

  2. 提高并发能力:当多个用户同时访问同一个表时,容易造成数据库的性能瓶颈,导致响应变慢。

    分库分表可以将数据分散到多个数据库或表中,从而提高并发访问能力,减少系统的瓶颈。

  3. 数据隔离:在多租户场景下,不同的租户需要使用不同的数据库或表,以保证彼此的数据隔离。分库分表可以将不同租户的数据分散到不同的数据库或表中,从而保证数据的隔离性。

  4. 降低单节点的压力:当系统需要支持大量数据的读写操作时,单个数据库或表可能无法承载,此时可以将数据分散到多个数据库或表中,从而降低单个节点的压力。

什么是分库分表

  1. 分库:将一个数据库拆分为多个数据库

    1. 水平分库:指将一个大型数据库分成多个较小的、相似的数据库,每个数据库包含数据的不同部分

      例如:将用户数据根据其 ID 值的范围分配到用户库DB1、用户库DB2中。

      这种分片方式可以提高系统的扩展性和性能,因为可以将负载分散到多个数据库中

    在这里插入图片描述

    特点:

    1. 每个库的结构都一样,存储同一业务类型的数据

    2. 每个库的数据都不一样,没有交集

    3. 所有库的并集是全量数据

    4. 垂直分库:是指将一个大型数据库,根据业务关系分成多个较小的数据库。

      例如,将用户数据存储在用户库,订单数据存储在订单库中。

      这种分片方式可以提高系统的灵活性和可维护性,因为可以根据需要对不同的数据库进行单独的优化和维护

    在这里插入图片描述

    特点:

    1. 每个库的结构都不一样,存储不同业务类型的数据

    2. 每个库的数据都不一样,没有交集

    3. 所有库的并集是全量数据

    水平分库和垂直分库并不是互斥的概念,两者可以结合使用来实现更高效的数据库分片方案

  2. 分表:将一个数据表拆分为多个数据表

    1. 水平分表:是指将一个表中的数据按照某个规则分散到多个表中,这个规则通常是基于某个列的取值进行的

      例如,可以根据用户ID,通过范围、Hash、取余等规则将用户表分成多个子表,每个子表中存储特定范围内的用户数据

      水平分表可以提高数据查询效率,因为查询只需要在一个小的子表中执行,而不是在整个表中执行

在这里插入图片描述

  特点:

  1. 每个表的结构都一样,存储**同一实体、相同类型**的数据
  2. 每个表存的数据都不一样,没有交集
  3. 所有表的并集是全量数据
  1. 垂直分表:指将一个表按照列的方式进行分割,将一部分列存储到一个表中,另一部分列存储到另一个表中。这个分割通常是基于列的相关性进行的,典型的如主表和扩展表

    例如,可以将一个包含用户主要信息、用户辅助信息的表分成两个表,一个包含用户主要信息,另一个包含用户辅助信息。

    可以提高数据的存储效率,因为每个表只包含必要的列,而不是整个表的所有列。

在这里插入图片描述

  特点:

  1. 每个表的结构都不一样,存储**同一实体、不同类型**的数据
  2. 每个表存的数据都不一样,字段至少有一列交集,一般是主键,用于关联数据
  3. 所有表的并集是全量数据

拆分策略

  1. 范围切分:按照数据的某个范围将表拆分成多个子表。例如,可以按照时间范围将订单表拆分成每个月的子表。

    优点:

    水平扩展:按照范围进行分库分表可以实现水平扩展,当数据量增加时,可以方便地增加更多的数据库或表;比如以2000万标准拆分,超过2000万的转移到新表,而之前2000万内的记录就无需再做迁移了

    缺点:

    热点问题:如果某些数据访问频率很高,但是按范围切分后,又被分在同一个区段,这样大量请求会集中在这一区段,没有很好的负载均衡效果

  2. 按照哈希值切分:按照数据的哈希值将表拆分成多个子表。例如,可以使用用户ID的哈希值将用户表拆分成多个子表。

    HASH取模策略:指定的路由key(一般是主键ID)对分表总数进行取模,把数据分散到各个表中

    优点:

    ​ 负载均衡,没有明显的热点倾斜问题

    缺点:

    扩展不灵活,如果一开始按照HASH取模分成4个表了,未来某个时候,表数据量又到瓶颈了,需要扩容至,这就比较棘手了,需要重新进行数据迁移

  3. 按照地理位置切分:如果数据与地理位置相关,则可以按照地理位置将表拆分成多个子表。例如,可以按照城市将商家表拆分成多个子表。

  4. 按照业务类型切分:如果数据有不同的业务类型,则可以按照业务类型将表拆分成多个子表。例如,可以按照产品类型将商品表拆分成多个子表。

  5. 按照访问频率切分:如果某些数据被频繁访问,则可以将其放入单独的表中,以便更快地访问。例如,可以将最近一年的订单数据放入单独的表中,以便更快地查询最近的订单。

分库分表工具

  1. ShardingSphere:ShardingSphere是一套开源的分布式数据库中间件解决方案,支持分库分表、读写分离、数据加密等功能。

    官网:https://shardingsphere.apache.org/index_zh.html

  2. Mycat:Mycat是一款基于MySQL协议的开源分布式数据库中间件,支持分库分表、读写分离、数据分片等功能。

    官网:http://www.mycat.org.cn/

  3. TDDL:TDDL是阿里巴巴开源的一款分布式数据库中间件,支持MySQL、Oracle等数据库,提供了分库分表、读写分离、数据分片等功能。

  4. Cobar:Cobar是阿里巴巴开源的一款分布式数据库中间件,支持MySQL、PostgreSQL等数据库,提供了分库分表、读写分离、数据分片等功能。

分库分表问题

  1. 主键(自增 ID)唯一性问题:在表设计时,经常会使用自增 ID 作为主键,这就导致后续在迁库迁表、或者分库分表操作时,会因为主键的变化或者主键不唯一产生问题,解决方案主要有

    1. 采用分布式全局统一 ID 生成机制:如 UUID、雪花算法、数据库号段等方式
  2. 分布式事务:由于数据被分散在多个数据库或表中,事务的处理会变得更加复杂。例如,如果一个事务涉及多个数据库或表,那么如何保证这些操作的原子性就需要更加细致的设计。

  3. Join/分页查询:在分库分表的情况下,查询跨越多个数据库或表就变得更加复杂。例如,如果需要对一组数据进行全文搜索,那么就需要在多个数据库或表中执行查询,这可能会影响查询性能。

    1. 分开查询,再组装数据

    2. 冗余字段:如果每次join操作只是为了获取少量的字段,那么可以考虑直接将这些字段冗余到表上

    3. 数据同步:

      ​ 将数据源之间的数据同步到一个单独的数据仓库中,然后在这个数据仓库中进行join操作。这种方法可以解决跨库跨表的join问题,但是需要额外的存储和同步成本,并且可能存在数据同步延迟和一致性问题

  4. 数据迁移:在分库分表的情况下,如果需要将数据迁移到新的数据库或表中,就需要考虑如何迁移数据,并且在迁移的过程中如何保证数据的一致性。

  5. 系统复杂度:由于分库分表需要管理多个数据库或表,系统的复杂度也会随之增加。例如,需要考虑如何监控每个数据库或表的状态,如何处理数据库或表的故障等等问题。

  6. 数据迁移:在分库分表的情况下,如果需要将数据迁移到新的数据库或表中,就需要考虑如何迁移数据,并且在迁移的过程中如何保证数据的一致性。

  7. 系统复杂度:由于分库分表需要管理多个数据库或表,系统的复杂度也会随之增加。例如,需要考虑如何监控每个数据库或表的状态,如何处理数据库或表的故障等等问题。

相关文章:

  • 微信小程序项目实例——扫雷
  • 一个完整的渗透学习路线是怎样的?如何成为安全渗透工程师?
  • 云上办公系统项目
  • Python自动化抖音自动刷视频
  • 基于Vue+Vue-cli+webpack搭建渐进式高可维护性前端实战项目
  • C#等高级语言运行过程
  • 人脸活体检测系统(Python+YOLOv5深度学习模型+清新界面)
  • 超详细的堆排序,进来看看吧。
  • HTTP 缓存的工作原理
  • STM32开发(九)STM32F103 通信 —— I2C通信编程详解
  • Leetcode 6322. 检查骑士巡视方案 暴力模拟法 第337场周赛,第二题
  • 蚂蚁一面面试经历
  • Spring事务和事务传播机制
  • ChatGPT加强版GPT-4面世,打工人的方式将被颠覆
  • oracle和mysql的区别
  • ES6指北【2】—— 箭头函数
  • 【翻译】babel对TC39装饰器草案的实现
  • 10个最佳ES6特性 ES7与ES8的特性
  • angular2 简述
  • ComponentOne 2017 V2版本正式发布
  • CSS相对定位
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • Java反射-动态类加载和重新加载
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Python利用正则抓取网页内容保存到本地
  • React系列之 Redux 架构模式
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • vue中实现单选
  • 从零开始的无人驾驶 1
  • 飞驰在Mesos的涡轮引擎上
  • 分类模型——Logistics Regression
  • 服务器从安装到部署全过程(二)
  • 来,膜拜下android roadmap,强大的执行力
  • 蓝海存储开关机注意事项总结
  • 如何设计一个微型分布式架构?
  • 使用 Docker 部署 Spring Boot项目
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 我看到的前端
  • 项目实战-Api的解决方案
  • 新手搭建网站的主要流程
  • 一文看透浏览器架构
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 函数计算新功能-----支持C#函数
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • (07)Hive——窗口函数详解
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (libusb) usb口自动刷新
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (转)scrum常见工具列表
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .gitignore文件设置了忽略但不生效