当前位置: 首页 > 科技观察

系统请求1次10s,我被客户爆骂,一怒之下优化数据库提升百倍性能

时间:2023-03-18 13:15:24 科技观察

系统请求一次10秒,被客户骂了一顿。一气之下,我优化了数据库,性能提升了一百倍。删除和修改操作会去主库,而读请求会去从库。通过读写分离,大大提高了读取数据的处理能力,但遗憾的是,没有办法提高主库写入数据的能力。新的挑战那么主库什么时候会写数据压力过大呢?其实这个问题我们之前也讲过,就是多个业务共享一个物理数据库,比如产品相关的表,订单相关的表,用户相关的表等等,所有的表都放在一个mysql数据库中,像这样:此时商品模块、订单模块、用户模块都部署在同一个物理数据库上。模块和用户模块通用。这就很尴尬了,由于这三个模块共享同一个数据库的资源,难免会相互影响。比如某天商品模块做了一些活动。比较尴尬的是商品模块没有读写分离。那么这个有时候商品模块可能会对这个物理数据库进行大量的读操作。这个时候这个物理数据库的CPU、内存、网络负载都非常高。但是,数据库的资源是有限的。由于商品模块占用了大量的数据库资源,订单模块可用的资源非常少。这时候会导致订单数据库写入数据很慢,写入一个订单的数据会突然增加。说到2s,这对于阶数来说是绝对不能接受的,那么有什么办法可以打破这种局面呢?当然有,那就是垂直拆分。如何进行垂直拆分?垂直拆分实际上分为垂直分库和垂直分表。我们这里指的是垂直分库。说白了就是把一个数据库拆分成多个数据库。那么如何拆分呢?其实可以从数据表的维度上拆分,将表归为一类。比如之前有100张表的数据库,现在我把它分成了10个mysql数据库,每个数据库有10张表的数据,这样每个数据库的压力就减轻了。会很小。垂直拆分说白了就是对一个大系统中的多个表进行分类,一般是按照模块一个一个拆分数据库,每个数据库只存储一种类型的数据表,每个数据库都有一批表,而且都是同一模块的表。比如一般的外卖系统,包括商品模块、订单模块、用户模块等,垂直拆分就是把各个模块的表放到单独的库中,分而治之,说白了就是分布式系统。拆分微服务后的效果:这样可以解决刚才的问题,因为根本原因是这三个模块共享一个数据库的资源。因此,当商品模块占用数据库服务器大量资源时,为订单模块预留。资源自然就减少了,那么打破这种局面的办法就是我们需要把这三个模块的数据库分开,让它们不共用一个物理数据库,而是给每个业务模块配备自己独立的物理数据库服务器,来说白了,就是把数据库垂直划分,从一个共享的大杂烩数据库拆分成独立的产品数据库、订单数据库和用户数据库。但是,在实际的分库中,我们可能需要考虑一种情况,就是有些模块是比较相关的,可能经常需要一起查询。所以这个时候我们也可以把一些强关联的模块的表放在一个库里,避免跨库查询带来的效率下降。那么这个时候,由于我们已经把不同模块的表放到了不同的数据库中,并且每个数据库都有自己独立的物理服务器,所以这个物理数据库的CPU、内存、网络的负载能力是相互依赖的。隔离,所以不存在之前相互占用资源的问题。垂直拆分有什么好处?垂直拆分可以带来很多好处。比如可以帮助我们减轻数据库的压力。我们按照模块划分数据库之后,现在不同模块的数据表已经划分到多个数据库中了。每个数据库中的数据不会有那么多数据,查询效率会更高。另外,当单个数据库的数据量减少时,相应的CPU、内存、网络负载的压力也会相应降低,整体查询效率也会提高。垂直拆分之后,业务会变得更加清晰,维护数据也会很方便,因为一个库被拆分成多个库,每个库中的表是一个业务模块,所以一个库只有一个模块业务很清楚。此外,数据维护也是如此。如果需要查找哪个模块的数据,可以在对应的库中查找。不会像拆分前那样,多个模块的数据会混在一起,数据的维护也很简单,因为多个模块的数据是解耦的。现在,修改一个库中的数据不会影响其他库中的数据。此外,系统扩展将变得更加容易。现在每个模块都被拆分了。例如,订单模块已从外卖系统中拆分为单独的模块。该订单模块的数据存储在一个数据库中,与其他模块的数据是独立的。如果订单模块的业务需要复杂化,就需要进行扩展。比如订单的表结构需要设计的更复杂,可以增加更多的业务设计,对其他模块透明,便于扩展;它不会和以前一样。多个模块的多张表耦合在一个库中,不易扩展,会影响其他业务。垂直拆分有什么缺点吗?好了,说了这么多垂直分库的好处,有没有什么缺点呢?答案是肯定的。首先,系统会变得更加复杂,因为现在垂直拆分之后,多个模块的表被分到了不同的数据库中。如果有查询操作需要关联多张表,此时,不能简单的使用join来进行关联查询。比如a表在A库,b表在B库,这时候不能简单的join连接。而是需要先通过接口获取a表的数据,再通过接口获取b表的数据。操作变得复杂。此外,交易处理也会变得更加麻烦。如果你想在之前处理交易,你可以在数据库中处理它们。如果有问题,只需回滚事务即可。但是现在要操作的数据可能分布在多个数据库中。如果在运行过??程中某个环节出现问题,事务不能简单的回滚,因为现在是跨多个数据库的事务。是时候使用分布式事务方案了,这个方案就更复杂了。而且,单个数据库的性能很快就会遇到瓶颈。虽然现在一个大系统中的多张表是根据不同的模型从多个数据库中切出来的,但是每个数据库都有一个对应模块的表,而某个模块可能数据量会特别大,比如订单模块,比较到其他模块,数据量会非常大。而且这里通常单个表中的数据太多。比如订单表可能已经有6000W条数据。这个时候order表的读写效率已经开始明显下降。像这样单表数据太多的问题,不是垂直分库可以解决的,所以这时候就需要对订单表做进一步的拆分,也就是水平拆分。由于我们实战主要是针对外卖订单业务,所以我们只有一个订单数据库。其实我们已经做了垂直分库,所以我们就不在这个垂直分库上进行实战了。横向分库分表是我们的。届时我们将带领大家设计横向分库分表的实施方案和数据迁移方案。敬请期待!