- 1 数据库概述
- 1.1 DBMS 简史
- 1.2 数据库理论
- 1.3 事务 Transaction
- 1.4 SQL
- 1.5 数据库接口
- 本章参考
- 2 Relational 关系数据库
- 2.1 关系理论
- 2.2 Oracle
- 2.5 Microsoft SQL Server
- 2.6 DB2
- RDBS 比较
- 本章参考
- 3 NoSQL 非关系数据库
- 3.1 NoSQL 分类
- 3.2 键值 key-value 数据库
- 3.3 列存储数据库
- 3.4 图形数据库
- 本章参考
- 4 NewSQL
- 4.1 NewSQL 分类
- 4.2 分布式数据库 Distributed
- 本章参考
- 5 时序数据库 TSDB
- 5.1 简介
- 5.2 时序数据库比较
- 本章参考
- 6 SQL 引擎
- 6.1 SQL 引擎分类
- 6.2 SQL On Hadoop
- 本章参考
- 7 其它数据库
- 7.1 内存数据库 In-memory
- 7.2 嵌入式数据库 Embed
- 7.3 搜索引擎
- 本章参考
- 8 各种数据库分析比较
- 8.1 数据库排行 db-engines
- 8.2 数据库技术选型
- 8.3 DB 性能比较
- 8.4 国产数据库产品列表
- 8.5 DB 常用 SQL 比较
- 本章参考
- 9 SQL 调优
- 9.1 SQL JOIN
- 9.2 SQL 执行流程
- 10 数据库大型应用实例
- 10.1 负载均衡技术
- 10.2 数据库的高可用 HA
- 10.3 数据库的读写分离
- 10.4 数据库拆分(分布式)
- 10.5 跨库查询
- 本章参考
- 参考资料
- 附录
10.4 数据库拆分(分布式)
垂直/水平拆分(分库分表)
首先进行垂直切分,按照表的内容将不同的表划分到不同的数据库中。(业务内容切分)
然后是水平切分,根据用户的 ID 将不同用户的内容再划分的不同的数据库中。
通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库上,实现分布存储,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是 N 台服务器,这样就可以降低单台机器的负载压力。
垂直( 纵向) 拆分 :是指按功能模块拆分,比如分为订单库、商品库、用户库…这种方式多个数据库之间的表结构不同。
水平(横向) 拆分:将同一个表的数据进行分块保存到不同的数据库中,这些数据库中的表结构完全相同。
图 表结构不同的 垂直(纵向) 拆分 图
图 表结构相同的水平(横向) 拆分图
垂直(纵向) 拆分
1, 实现原理 :使用垂直拆分,主要要看应用类型是否合适这种拆分方式,如系统可以分为,订单系统,商品管理系统,用户管理系统业务系统比较明的,垂直拆分能很好的起到分散数据库压力的作用。
业务模块不明晰,耦合(表关联)度比较高的系统不适合使用这种拆分方式。但是垂直拆分方式并不能彻底解决所有压力问题,例如有一个 5000w 的订单 表,操作起来订单库的压力仍然很大,如我们需要在这个表中增加(insert)一条新的数据,insert 完毕后,数据库会针对这 张表重新建立索引,5000w 行数据建立索引的系统开销还是不容忽视的,反过来,假如我们将这个表分成 100 个 table 呢,从 table_001 一直到 table_100,5000w 行数据平均下来,每个子表里边就只有 50 万行数据,这时候我们向一张只有 50w 行数据的 table 中 insert 数据后建 立索引的时间就会呈数量级的下降,极大了提高了 DB 的运行时效率,提高了 DB 的并发量,这种拆分就是横向拆分
2, 实现方法 :垂直拆分方式实现起来比较简单,根据表名访问不同的数据库就可以了。
水平(横向) 拆分
(1) 顺序拆分 :如可以按订单的日前按年份才分,2003 年的放在 db1 中,2004 年的 db2,以此类推。当然也可以按主键标准拆分。
优点:可部分迁移
缺点:数据分布不均,可能 2003 年的订单有 100W,2008 年的有 500W。
(2) hash 取模分 : 对 user_id 进行 hash(或者如果 user_id 是数值型的话直接使用 user_id 的值也可),然后用一个特定的数字,比如应用中需要将一个数据库切分成 4 个数据库的话,我们就用 4 这个数字对 user_id
的 hash 值进行取模运算,也就是 user_id%4
,这样的话每次运算就有四种可能:结果 为 1 的时候对应 DB1;结果为 2 的时候对应 DB2;结果为 3 的时候对应 DB3;结果为 0 的时候对应 DB4,这样一来就非常均匀的将数据分配到 4 个 DB 中。
优点:数据分布均匀
缺点:数据迁移的时候麻烦;不能按照机器性能分摊数据 。
(3) 在认证库中保存数据库配置
就是建立一个 DB,这个 DB 单独保存 user_id 到 DB 的映射关系,每次访问数据库的时候都要先查询一次这个数据库,以得到具体的 DB 信息,然后才能进行我们需要的查询操作。
优点:灵活性强,一对一关系
缺点:每次查询之前都要多一次查询,会造成一定的性能损失。
分库分表的主要问题
- ACID 原则:保证数据一致性,如 Binlog(二进制日志)、
- 多表之间的关联查询
- 无法使用外键约束
- 无法使用全局 ID,如 Oracle 的 Sequence、MySQL 的 AUTO_INCREMENT 自增 ID。
Sharding 中间件
MySQL Cluster 和 MySQL Sharding
- MySQL Cluster 是数据库集群,主要用于提升数据库的并行处理能力。
- MySQL Sharding 是分片,不仅可以提升数据库的并行处理能力,还解决单表数据量大的问题。
表格 48 Sharding 中间件比较
功能 | Cobar | MyCat | TDDL | Shark |
---|---|---|---|---|
是否开源 | √ | √ | 部分 | √ |
架构模型 | Proxy | Proxy | 应用集成 | 应用集成 |
数据库支持 | MySQL | 任意 | MySQL、Oracle | MySQL |
外围依赖 | 无 | 无 | Diamond | 无 |
读写分离 | √ | √ | √ | √ |
分库分表 | √ | √ | √ | √ |
分库分表示例
1)根据用户 ID(简称 uid)进行分库分表
根据 uid 计算数据库、表编号: (表数 TBL_NUM 固定为 10,数据库数 DB_NUM 可取任意值,为 2 的整数指数倍~4/8/16/32/64)
数据库编号(分库号) = (uid / TBL_NUM) % DB_NUM + 1
表编号(分表号) = uid % TBL_NUM (0~9)
当 uid=9527 时,根据上面的算法,其实是把 uid 分成了两部分 952 和 7,其中 952 模 8 加 1 等于 1 为数据库编号,而 7 则为表编号。所以 uid=9527
的订单信息需要去 DB1 库中的 order_7 表查找。
分库分表信息存储字节数
- 分库
DB_NUM <=10:1(分库)+1(分表)= 2byte
- 分库
DB_NUM >10:2(分库)+1(分表)= 3byte
使用 DB_NUM= 64 来做冗余分库信息。 实际库编号=(数据库编号- 1) % 8 + 1
如上例: uid=9957
,分库号 57,分表号 7,分库分表存储为 577
,实际分库号需二次计算得 (57-1)%8+1=1
。
2)订单 ID 结构
订单为全局唯一。
版本号 | 分库分表信息 | timestamp | 机器号 | 自增序列号 |
---|---|---|---|---|
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论