1、基础
首先 我们了解下 衡量一个软件系统好坏的参数。
运营类:
PV 页面浏览量 就是页面被请求多少次就算多少次。
UV 同一个客户端访问网站记为一次,在一段时间内不论刷新多少次,都只记为一次 独立IP访问数 同一个IP计数加1,不管是什么设备访问。例如用电脑和手机两个设备访问一个网站,IP相同。也只计算一次。
DAU 日活跃用户数, 一日之内有多少个用户登录使用了产品。
MAU 月活跃用户数,一月之内有多少个用户登录使用了产品。
运维类:
QPS 每秒钟处理请求的数量(不是接收请求,而是将用户的请求处理完才算) = 并发量 / 平均响应时间
TPS 每秒钟事务数
RT(响应时间) 一般取平均响应时间。
并发数 指一段时间内,同时处理事情的程序有多少个。 一段时间内: 并不特指1S, 而是说处理一个时间所花费的平均时间。 QPS * 平均响应时间
吞吐量 单位时间内处理请求的数量。
2、遇到问题
现在系统的QPS,TPS下降, RT上升,并发量下降,吞吐量降低。于是我们要优化系统。 可以从硬件入手, 软件入手,需求优化, 数据库优化。
对于数据库来说 单表的数据量过大,表创建的不合理,SQL写的不合理,数据库连接达到上限(并发量已经到顶了)。
3、解决问题的方案
解决方案:
数据库的连接达到上限了,简单的就是 一主多从的形式,分散访问流量。 复杂的就是 根据业务,进行划分边界,拆服务,拆库达到专库专用的效果。
单表的存储量过大, 就是分表,如果分表还解决不了,那就分库。 把表分到多个库中,这时的夸库的事务非常麻烦,要考虑好取舍。
本次的主要内容数据分片。
数据分片指按照某个维度将存放在单一数据库中的数据分散地存放至多个数据库或表中以达到提升性能瓶颈以及可用性的效果。 数据分片的有效手段是对关系型数据库进行分库和分表。分库和分表均可以有效的避免由数据量超过可承受阈值而产生的查询瓶颈。 除此之外,分库还能够用于有效的分散对数据库单点的访问量;分表虽然无法缓解数据库压力,但却能够提供尽量将分布式事务转化为本地事务的可能,一旦涉及到跨库的更新操作,分布式事务往往会使问题变得复杂。 使用多主多从的分片方式,可以有效的避免数据单点,从而提升数据架构的可用性。
分库分表进行数据的拆分使得各个表的数据量保持在阈值以下,以及对流量进行疏导应对高访问量,是应对高并发和海量数据系统的有效手段。数据分片的拆分方式分为垂直分片和水平分片。
垂直分片:1个库变为多个库,拆分模块, 专库专用。降低单库的访问量。 垂直分片往往需要对架构和设计进行调整。通常来讲,是来不及应对互联网业务需求快速变化的;为什么来不及? 因为互联网业务大部分都是突然性的数据剧增,拆分模块是很费时间的做法,没办法再短时间内解决问题,就比如 一个红包活动上线后,可能在两天后的某一时刻达到高峰,QPS达到几万,对于数据库来说每秒钟就有几万个的请求插入和查询,很容易就达到阈值。而且,它也并无法真正的解决单点瓶颈。 垂直拆分可以缓解数据量和访问量带来的问题,但无法根治。如果垂直拆分之后,表中的数据量依然超过单节点所能承载的阈值,则需要水平分片来进一步处理。
水平分片: 不是根据业务逻辑去拆分模块,而且将一张表通过某些字段 根据一种规则拆分出多个表或者多个库。每个分表仅包含一部分数据。
数据分片带来的好处就是,提高了性能,可用性。 带来的问题就是,跨库的事务怎么解决,多库多表对于数据管理员来说很是痛苦,包括我们找数据的时候,要根据字段自己区分下在哪个库然后在库里的哪个表,就是很麻烦。
示例。
划分边界: 例如:任务, 订单, 用户,结算。
还是有一些表无法划分考勤表和工资表。
下面以订单模块为例:
order
order_talent
order_talent_count
order_talent_record
order_talent_stage
attendance
employee_salary
这些表抽离独立为订单库。边界的划分也是比较复杂的,要在熟悉业务的前提下才能做出正确的划分。
比较简单的:
1、 以关联键来说order_talent表也可以作为suppliers_talent的子表,但是订单人才表没有分到用户模块下也是因为综合业务来考虑它在订单模块会更方便使用。
比较复杂的:attendance(人才考勤表) 和 employee_salary(人才工资表), 虽然他们是跟随订单人才表走的, 但是最开始数据入库时,可能没有绑定订单人才id,也没有订单id。第一种做法放在订单库中,不分表,但是要强制配路由。 另外一种订单库和任务库中都有这张表,订单库中进行分表,只有在绑定了订单人才以后才进行订单库,其他状态的时候 数据进入任务库。
边界划分拆完库之后,下面按照一定的策略进行分片。
1、以主键id范围分片
2、以主键id取模分片
3、以某个时间字段范围分片
4、以分片容量的分片 (有点类似id范围了)
确定了分片之后,我们要在项目中怎么去使用存储读取数据呢?比如要插入一条数据,那我们先要写好规则,按照我们的规则,这条数据最终会落到哪个库的哪张表上。读取数据的时候,我们要根据规则判定是要读所有库的所有表,还是具有指向性的读取某库的第几张表数据。 更复杂的是我们如果进行联表读取。 解决这些问题的工具有很多。
下一章讲如何分片的工具