zoukankan      html  css  js  c++  java
  • Mysql分库分表

    关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严重。此时就要考虑对其进行切分了,切分的目的就在于减少数据库的负担,缩短查询时间。

    数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。

    • 垂直切分:纵向切分,根据业务耦合性,拆分表或库
      • 垂直分库:根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。与"微服务治理"的做法相似,每个微服务使用单独的一个数据库。
      • 垂直分表:垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中
    • 水平切分:横向切分,通过下标来分库分表
      • 水平分库:根据业务键拆分为不同库,库表结构、表名均相同,数据不同
      • 水平分表:根据业务键拆分为不同表,表结构相同,表名不同

    垂直切分的优点

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

    垂直切分的缺点

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

    水平切分的优点

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

    水平切分的缺点

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

    1. 水平切分键值选取

    根据数值范围:按照时间区间或ID区间来切分

    • 优点
      • 单表大小可控
      • 天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移
      • 使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。
      • 冷热数据分离,
      • 切分策略简单
    • 缺点
      • 数据量和请求量不均,热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询
      • uid必须要满足递增的特性

    hash取模:采用hash取模的切分方式

    • 优点
      • 数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈
    • 缺点
      • 后期分片集群扩容时,需要迁移旧的数据(使用一致性hash算法能较好的避免这个问题)
      • 容易面临跨分片查询的复杂问题。

    2. 拆分带来的问题

    事务一致性问题

    • 分布式事务,没有简单的方案,一般可使用"XA协议"和"两阶段提交"处理。
    • 对于那些性能要求很高,但对一致性要求不高的系统,往往不苛求系统的实时一致性,只要在允许的时间段内达到最终一致性即可,可采用事务补偿的方式

    跨节点关联查询 join 问题

    • 全局表,也可看做是"数据字典表",就是系统中所有模块都可能依赖的一些表,为了避免跨库join查询,可以将这类表在每个数据库中都保存一份
    • 字段冗余:一种典型的反范式设计,利用空间换时间,为了性能而避免join查询
    • 数据组装:在系统层面,分两次查询,第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。最后将获得到的数据进行字段拼装。
    • ER分片:先确定表之间的关联关系,并将那些存在关联关系的表记录存放在同一个分片上

    跨节点分页、排序、函数问题

    • 需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序,最终返回给用户

    全局主键避重问题

    • UUID:UUID是主键是最简单的方案,本地生成,性能高,没有网络耗时。但缺点也很明显,由于UUID非常长,会占用大量的存储空间;另外,作为主键建立索引和基于索引进行查询时都会存在性能问题
    • 结合数据库维护主键ID表

    数据迁移、扩容问题

    3. 什么时候考虑切分

    能不切分尽量不要切分

    不到万不得已不用轻易使用分库分表这个大招,避免"过度设计"和"过早优化"

    数据量过大,正常运维影响业务访问

    • 对数据库备份,如果单表太大,备份时需要大量的磁盘IO和网络IO
    • 对一个很大的表进行DDL修改时,MySQL会锁住全表,这个时间会很长,这段时间业务不能访问此表,影响很大。
    • 大表会经常访问与更新,就更有可能出现锁等待。将数据切分,用空间换时间,变相降低访问压力

    随着业务发展,需要对某些字段垂直拆分

    数据量快速增长

    安全性和可用性

    参考博客

    [数据库分库分表思路](https://www.cnblogs.com/butterfly100/p/9034281.html)

  • 相关阅读:
    Java运行时数据区域
    线程的实现原理
    redis分布式锁的实现
    Incorrect string value: 'xF0x9Fx92x8BTi...'错误
    linux命令之less命令
    Hive数据类型和DDL操作
    Hive安装、配置和使用
    CentOS 7安装配置MySQL 5.7
    Spring+SpringMVC+MyBatis整合
    MyBatis的事物管理和缓存
  • 原文地址:https://www.cnblogs.com/steven158/p/15618330.html
Copyright © 2011-2022 走看看