这是我参与「第五届青训营 」伴学笔记创作活动的第 20 天
今天学习了数据库分库分表相关知识
-
分库分表的原因:
- 单机数据库的存储能力、连接数是有限的,它自身就很容易会成为系统的瓶颈。当单表数据量在百万以里时,我们还可以通过添加从库、优化索引提升性能。
- 一旦数据量朝着千万以上趋势增长,再怎么优化数据库,很多操作性能仍下降严重。为了减少数据库的负担,提升数据库响应速度,缩短查询时间,这时候就需要进行分库分表。
-
为什么需要分库?分库指的是不同的数据库实例
- 容量:我们给数据库实例分配的磁盘容量是固定的,数据量持续的大幅增长,用不了多久单机的容量就会承载不了这么多数据,解决办法简单粗暴,加容量!
- 连接数:单机的容量可以随意扩展,但数据库的连接数却是有限的,在高并发场景下多个业务同时对一个数据库操作,很容易将连接数耗尽导致
too many connections报错,导致后续数据库无法正常访问。可以通过max_connections查看MySQL最大连接数。
-
为什么需要分表?分表指的是不同的数据表
- 数据过多,慢的根本原因是
InnoDB存储引擎,聚簇索引结构的 B+tree 层级变高,磁盘IO变多查询性能变慢 - 阿里的开发手册中有条建议,单表行数超500万行或者单表容量超过2GB,就推荐分库分表,然而理想和实现总是有差距的
- 数据过多,慢的根本原因是
-
判断数据具体存在于哪个数据库中的方式?
-
取模方法
- 优点:实现简单,数据分布相对比较均匀,不易出现请求都打到一个库上的情况。
- 缺点:取模算法对集群的伸缩支持不太友好,集群中有N个数据库实
·hash(user_id) mod N,当某一台机器宕机,本应该落在该数据库的请求就无法得到处理,这时宕掉的实例会被踢出集群。此时机器数减少算法发生变化hash(user_id) mod N-1,同一用户数据落在了在不同数据库中,等这台机器恢复,用user_id作为条件查询用户数据就会少一部分
-
给定范围限定法
- 优点:单表数据量是可控的,水平扩展简单只需增加节点即可,无需对其他分片的数据进行迁移
- 缺点:由于连续分片可能存在
数据热点,比如按时间字段分片时,如果某一段时间(双11等大促)订单骤增,存11月数据的表可能会被频繁的读写,其他分片表存储的历史数据则很少被查询,导致数据倾斜,数据库压力分摊不均匀。
-
先给定范围再取模法
- 有效的避免数据分布不均匀的问题,数据库水平扩展也简单,直接添加实例无需迁移历史数据
-
其他特殊衡量指标法
-
-
分库分表造成的问题
- 分页、排序、跨节点联合查询
- 事务一致性
- 全局唯一主键
- 多数据库高效治理
- 历史数据迁移
-
分库分表模式
-
一个是在服务器端直接进行数据分发,一个是通过代理数据分发
-
如何选择
client模式和proxy模式,我们可以从以下几个方面来简单做下比较。1、性能
性能方面
client模式表现的稍好一些,它是直接连接MySQL执行命令;proxy代理服务则将整个执行链路延长了,应用->代理服务->MySQL,可能导致性能有一些损耗,但两者差距并不是非常大。2、复杂度
client模式在开发使用通常引入一个jar可以;proxy代理模式则需要搭建单独的服务,有一定的维护成本,既然是服务那么就要考虑高可用,毕竟应用的所有SQL都要通过它转发至MySQL。3、升级
client模式分库分表一般是依赖基础架构团队的Jar包,一旦有版本升级或者Bug修改,所有应用到的项目都要跟着升级。小规模的团队服务少升级问题不大,如果是大公司服务规模大,且涉及到跨多部门,那么升级一次成本就比较高;proxy模式在升级方面优势很明显,发布新功能或者修复Bug,只要重新部署代理服务集群即可,业务方是无感知的,但要保证发布过程中服务的可用性。4、治理、监控
client模式由于是内嵌在应用内,应用集群部署不太方便统一处理;proxy模式在对SQL限流、读写权限控制、监控、告警等服务治理方面更优雅一些
-