专车数据层「架构进化」往事(一)

发布于 2022-5-17 17:46
浏览
0收藏

很多年前,读了子柳老师的《淘宝技术这十年》。这本书成为了我的架构启蒙书,书中的一句话像种子一样深埋在我的脑海里:“好的架构是进化来的,不是设计来的”。

 

2015年,我加入神州专车订单研发团队,亲历了专车数据层「架构进化」的过程。这次工作经历对我而言非常有启发性,也让我经常感慨:“好的架构果然是一点点进化来的”。专车数据层「架构进化」往事(一)-开源基础软件社区1 单数据库架构


产品初期,技术团队的核心目标是:“快速实现产品需求,尽早对外提供服务”

 

彼时的专车服务都连同一个 SQLServer 数据库,服务层已经按照业务领域做了一定程度的拆分。专车数据层「架构进化」往事(一)-开源基础软件社区这种架构非常简单,团队可以分开协作,效率也极高。随着专车订单量的不断增长,早晚高峰期,用户需要打车的时候,点击下单后经常无响应。

 

系统层面来看:

 

1.数据库瓶颈显现。频繁的磁盘操作导致数据库服务器 IO 消耗增加,同时多表关联,排序,分组,非索引字段条件查询也会让 cpu 飙升,最终都会导致数据库连接数激增;


网关大规模超时。在高并发场景下,大量请求直接操作数据库,数据库连接资源不够用,大量请求处于阻塞状态。

 

2.  SQL优化和读写分离


为了缓解主数据库的压力,很容易就想到的策略:SQL优化。通过性能监控平台和 DBA 同学协作分析出业务慢 SQL ,整理出优化方案:

 

1.合理添加索引;


2.减少多表 JOIN 关联,通过程序组装,减少数据库读压力;


3.减少大事务,尽快释放数据库连接。


另外一个策略是:读写分离

 

读写分离的基本原理是让主数据库处理事务性增、改、删操作( INSERT、UPDATE、DELETE),而从数据库处理 SELECT 查询操作。

 

专车架构团队提供的框架中,支持读写分离,于是数据层架构进化为如下图:专车数据层「架构进化」往事(一)-开源基础软件社区读写分离可以减少主库写压力,同时读从库可水平扩展。当然,读写分离依然有局限性:

 

1.读写分离可能面临主从延迟的问题,订单服务载客流程中对实时性要求较高,因为担心延迟问题,大量操作依然使用主库查询;

 

2.读写分离可以缓解读压力,但是写操作的压力随着业务爆发式的增长并没有很有效的缓解。

 

3  业务领域分库


虽然应用层面做了优化,数据层也做了读写分离,但主库的压力依然很大。接下来,大家不约而同的想到了业务领域分库,也就是:将数据库按业务领域拆分成不同的业务数据库,每个系统仅访问对应业务的数据库。专车数据层「架构进化」往事(一)-开源基础软件社区业务领域分库可以缓解核心订单库的性能压力,同时也减少系统间的相互影响,提升了系统整体稳定性。

 

随之而来的问题是:原来单一数据库时,简单的使用 JOIN 就可以满足需求,但拆分后的业务数据库在不同的实例上,就不能跨库使用 JOIN了,因此需要对系统边界重新梳理,业务系统也需要重构 。

 

重构重点包含两个部分:

 

1.原来需要 JOIN 关联的查询修改成 RPC 调用,程序中组装数据 ;


2.业务表适当冗余字段,通过消息队列或者异构工具同步。


4 缓存和MQ


专车服务中,订单服务是并发量和请求量最高,也是业务中最核心的服务。虽然通过业务领域分库,SQL 优化提升了不少系统性能,但订单数据库的写压力依然很大,系统的瓶颈依然很明显。

 

于是,订单服务引入了 缓存 MQ

 

乘客在用户端点击立即叫车,订单服务创建订单,首先保存到数据库后,然后将订单信息同步保存到缓存中。

 

在订单的载客生命周期里,订单的修改操作先修改缓存,然后发送消息到 MetaQ ,订单落盘服务消费消息,并判断订单信息是否正常(比如有无乱序),若订单数据无误,则存储到数据库中。专车数据层「架构进化」往事(一)-开源基础软件社区核心逻辑有两点:

 

1.缓存集群中存储最近七天订单详情信息,大量订单读请求直接从缓存获取;


2.在订单的载客生命周期里,写操作先修改缓存,通过消息队列异步落盘,这样消息队列可以起到消峰的作用,同样可以降低数据库的压力。

 

这次优化提升了订单服务的整体性能,也为后来订单服务库分库分表以及异构打下了坚实的基础。

已于2022-5-17 17:46:21修改
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐