曾经经历过几家电商业务的单位,有医疗电商、快销品电商、本地服务生活电商等。为了简化,我拿交易系统和商品系统两个比较有代表性的业务,来分析下电商平台的发展过程,遇到的瓶颈,以及架构上是怎么解决的。
单体架构
一般的电商系统开始都是一个单体架构,所有的代码都打包在一个应用里,部署的时候会有多个实例,我们通过负载均衡,把用户请求分发到具体的实例中。这个时候,所有的数据表还在一个数据库里。

SOA架构

我们对系统进行拆分,把整体系统分为多个子系统。我们把系统拆分为交易系统和商户系统,通过内部的负载均衡进行相互调用,这个时候,底层数据库还没有拆分,两个系统还是访问同一个数据库。通过拆分,系统整体就变成了 SOA 架构。
问题:内部服务通过中心化的负载均衡进行访问,中心化的负载均衡增加了服务的调用时间。此外,在电商场景下,内部的服务很多,服务调用的频率很高,每秒可能有上百万次,导致了负载均衡的连接能力不够。而且负载均衡是单点,如果它出了问题,很容易引发系统整体的可用性问题。
服务调用去中心化

针对内部服务路由中心化的问题,我们去掉了内部的负载均衡,加入了服务注册中心,比如 ZooKeeper。
当服务实例启动或退出时,它们会自动在注册中心进行注册或销毁,服务的客户端和注册中心保持长连接,可以实时地获取可用的服务列表;然后在客户端,根据相应的算法选择服务实例,直接调用服务。每次调用无需经过注册中心,如果注册中心有问题,也只是新的服务实例无法注册,或者是已有的服务实例无法注销,这对客户端调用服务的影响是非常有限的。
垂直分库

对于单个数据库性能和容量瓶颈,解决的办法就是,我们对数据库进行垂直拆分,按照业务拆分为交易数据库和商品数据库,这样就可以满足它们各自的容量和性能需求,同时也避免了不同业务数据表之间的相互耦合。
水平分库及高可用部署

针对单个数据库的可用性问题,我们可以采用 MHA 高可用方式部署。比如数据库部署一主多从,通过 MHA 机制,我们可以实时检测主库的可用性,如果主库有问题,系统会自动 Failover(故障转移)到最新的从库。另一方面,我们还可以利用多个从库支持读写分离,减轻主库的访问压力。
当系统体量发展到了一定程度,我们又碰到了新的问题:单个机房的服务器不够用,无法在同一个机房找到更多的机器部署交易系统和商品系统。
多机房部署

对于单机房服务器不够的问题,我们可以在新的机房部署交易系统和商户系统,为了落地方便,所有服务还是注册到旧机房的注册中心,数据还是存放在旧机房的交易数据库和账户数据库。这样,我们通过在新机房部署应用,对应用节点进行水平扩展,从而解决了单机房机器不足的问题。
但这里产生了跨机房访问的问题:首先,我们只有一个服务注册中心,服务实例一部分部署在老机房,一部分部署在新机房,对于服务调用者来说,它会同时访问新旧机房的服务实例;其次,数据库部署在老机房,新机房的应用会访问旧机房的数据库。跨机房的网络可用性也经常是一个问题
服务调用本地化

为了避免服务的跨机房访问,我们在新机房也单独部署了服务注册中心,让每个机房的服务注册到同机房的注册中心。这样,客户端的服务调用会路由到同机房的服务端,实现了服务调用的本地化,大大降低了跨机房通信带来的延时和不可用性问题。
依赖分级管理

对于强依赖,我们实时同步调用,比如在用户下单时调用库存服务,由于库存非常重要,必须实时扣减,如果调用库存服务失败,下单也失败。对于大量的弱依赖,我们以异步消息的方式进行信息同步,比如对于积分服务,可以通过柔性事务来保证数据的最终一致性,这样大大提升了核心系统的性能和可用性。
欢迎交流:微信号 greencoatman

