分库分表
前文说到大部分的业务场景是读多写少,查询的 qps 要远高于写入。所以当业务出现查询性能下降时,可以考虑使用主从读写分离。这确实会缓解很长一段时间,如同智齿消炎后的风平浪静,但智齿不拔总有一天你会受不了反复发炎的痛苦,业务也是。查询的性能瓶颈缓解之后,写入的性能下降往往随着而来,而且来的更猛烈,数据量暴增,查询也会收到牵连。为了解决写入的问题,聪明的人类又使出了分库分表这招。
分库分表的演进
分库分表其实是两件事,但思路都是通过增加若干个主库来解决单表数据量的不可控增长。一个人打不过,可以打电话摇一车人来,这就是核心思想。
首先分库比较低级,通过将一些业务密集的表单独拿出来形成一个独立的库来提供操作。比如用户表,订单表这样的核心场景且数据量庞大的表,一个库拆成两个库。
这样一分为二,可以显著的缓解一个库的连接池压力。但单表数据量还是那么大,查询的压力并没有缓解,即使有索引依然会比较慢。
奔着缩减单表数据量的目的去优化,自然我们会想到可以根据表字段的特征去拆分。目前用的最多的 2 个方案是:
根据 uid 做 hash
根据创建时间区间做分表 当然也肯定有其他更适合的字段,这要根据业务而定。以上的分库思路如下图所示:
注意事项
复杂的系统必然比简单的系统问题更多,分库分表的引入也必然会带来更多的问题。首先得能驾驭才能使用,不然可能适得其反。首先,既然分了 N 个库,那数据查询时就必然要带上一个可以快速索引到对应库的字段。但凡出现一个跨库性能就会直线下降。所以这时候,需要一个分区键来告诉我们去哪一个库去查。分区键在第一种情况下是 uid,但如果想用 name 去查还是要获取对应的 uid,这个时候甚至需要一张映射表,这个映射表也可以分库。按照时间段来分库的缺点在于要记得去创建新库,不记得业务就挂了。
小结
分库分表是比较常规的技术,对此我的建议是:
不要分库分表
如果对数据量的庞大有预估,不要用 mysql。毕竟有很多 NoSQL 支持 auto sharding 了。
真的要分库分表,一定要摸清中间件的使用说明,完全驾驭才能去操作
真的要分库分表,一次就分个 64 个或者更多,可以保证用到你离职或者重构之前
评论