• MySQL数据库分库分表


    为什么要分库分表

    关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。切分的目的就在于减少数据库的负担,缩短查询时间。

    数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。数据切分根据其切分类型,可以分为两种方式:垂直(纵向)切分和水平(横向)切分。

    数据库的瓶颈

    1、IO瓶颈

    磁盘读IO瓶颈,热点数据太多,数据库缓存放不下,每次查询时会产生大量的IO,降低查询速度 -> 分库和垂直分表。第二种:网络IO瓶颈,请求的数据太多,网络带宽不够 -> 分库。
    2、CPU瓶颈

    SQL问题,如SQL中包含join,group by,order by,非索引字段条件查询等,增加CPU运算的操作 -> SQL优化,建立合适的索引,在业务Service层进行业务计算。第二种:单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈 -> 水平分表。

    分库分表

    水平分库

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

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

    场景:系统绝对并发量上来了,分表难以根本上解决问题,并且还没有明显的业务归属来垂直分库。分析:库多了,io和cpu的压力自然可以成倍缓解。

    在这里插入图片描述
    水平切分后同一张表会出现在多个数据库/表中,每个库/表的内容不同。

    水平分表

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

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

    场景:系统绝对并发量并没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为瓶颈。分析:表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。

    在这里插入图片描述
    水平切分的优点:

    • 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力;
    • 应用端改造较小,不需要拆分业务模块。

    缺点:

    • 跨分片的事务一致性难以保证;
    • 跨库的join关联查询性能较差;
    • 数据多次扩展难度和维护量极大。

    垂直分库

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

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

    场景:系统绝对并发量并没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为瓶颈。分析:表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。

    在这里插入图片描述

    垂直分表

    概念:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
    结果

    • 每个表的结构都不一样;
    • 每个表的数据也不一样,一般来说,每个表的字段至少有一列交集,一般是主键,用于关联数据;
    • 所有表的并集是全量数据;

    场景:系统绝对并发量并没有上来,表的记录并不多,但是字段多,并且热点数据和非热点数据在一起,单行数据所需的存储空间较大。以至于数据库缓存的数据行减少,查询时会去读磁盘数据产生大量的随机读IO,产生IO瓶颈。分析:可以用列表页和详情页来帮助理解。垂直分表的拆分原则是将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。这样更多的热点数据就能被缓存下来,进而减少了随机读IO。拆了之后,要想获得全部数据就需要关联两个表来取数据。但记住,千万别用join,因为join不仅会增加CPU负担并且会讲两个表耦合在一起(必须在一个数据库实例上)。关联数据,应该在业务Service层做文章,分别获取主表和扩展表数据然后用关联字段关联得到全部数据。

    垂直切分的优点:

    • 解决业务系统层面的耦合,业务清晰;
    • 与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等;
    • 高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈。

    缺点:

    • 部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度;
    • 分布式事务处理复杂;
    • 依然存在单表数据量过大的问题(需要水平切分)。

    分库分表工具

    • sharding-sphere:jar,前身是sharding-jdbc;
    • TDDL:jar,Taobao Distribute Data Layer;
    • Mycat:中间件。

    分库分表的问题

    非partition key的查询问题

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

    端上除了partition key只有一个非partition key作为条件查询。

    映射法

    在这里插入图片描述

    基因法

    在这里插入图片描述

    写入时,基因法生成user_id,如图。关于xbit基因,例如要分8张表,23=8,故x取3,即3bit基因。根据user_id查询时可直接取模路由到对应的分库或分表。
    根据user_name查询时,先通过user_name_code生成函数生成user_name_code再对其取模路由到对应的分库或分表。id生成常用snowflake算法。

    端上除了partition key不止一个非partition key作为条件查询。

    映射法

    在这里插入图片描述

    冗余法

    在这里插入图片描述

    后台除了partition key还有各种非partition key组合条件查询。

    NoSQL法

    在这里插入图片描述

    冗余法

    在这里插入图片描述

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

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

    注:用NoSQL法解决(ES等)。

    扩容问题

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

    • 水平扩容库(升级从库法),扩容是成倍的。
    • 水平扩容表(双写迁移法),双写是通用方案。
  • 相关阅读:
    最大路径和问题(摘樱桃问题)
    SpringBoot激活profiles的几种方式
    Redis 哨兵模式的实现详解
    后端Web开发之Maven
    idea打包项目,使用maven
    一、基本数据类型(数组)
    新版本IntelliJ IDEA(如2023)中运行Spring Boot找不到VM options进行端口的修改的问题解决
    翁恺C语言程序设计网课笔记合集
    Python 面试题解析
    Linux下提取文件夹下的所有文件名称
  • 原文地址:https://blog.csdn.net/qq_47305937/article/details/126191052