`

简单后端系统在云平台上的演进之路

阅读更多

一款应用发布之初,用户量小,用一台服务器就可以支撑全部需求,所以最初的部署情况是,最前面是一台绑定了公网IP的nginx服务器作为负载均衡,后面放了3台应用服务器来处理业务上的请求,最后面搭建了一台MySQL Database。

 

1、构建私有网络

 

随着用户数的增长,用户可以构建私有网络,将运行内部服务的主机放置在私有网络中,主机对外开放的仅有80端口,这样能和云平台上的其它用户主机实现有效的隔离。可引入云负载均衡器(有更高的性能、可用性,并提供监控和告警)。负载均衡器主要用于分发请求到后端多台应用服务器,当其中一台应用服务器挂掉,负载均衡器可以进行自动隔离。

 

 

2、业务分区与扩展

 

水平扩展业务服务器的前提是保证每台服务器都是无状态的,将 session 信息下放到缓存或数据库中存储,保证请求被负载到任何一台服务器可以正常处理。利用云的自有映像功能将业务服务器制作成模版,后续可以基于模版快速启动新的主机。通过日志分析每个接口的耗时,将耗时长但非重要业务的请求分到单独的Web服务器上进行处理,从而给主Web服务器留出更多资源去处理关键业务的请求。

 

3、面向服务的架构

 

随着产品功能越来越丰富,原有单一的业务项目越来越庞大,各种功能逻辑交织在一起,当一个功能出现故障,可以引发全局不可用。此时需要考虑将单一的业务项目分拆成多个独立子服务。子服务之间可以基于消息的通信,亦或基于 RPC 的通信方式。其好处是:

-故障隔离:子服务出现故障不会影响全局;

-独立扩展:每一个被拆分出的子服务有着不同的访问压力;

-独立部署:一个大服务的配置因功能过多会异常复杂,一旦被拆分就可根据不同的特性需求定制配置项,从而提高可管理性;

-团队协作开发:开发者都有着自己精通的方向,从而提高开发效率;

-抽象出数据访问:在后续进行数据层面(数据库、缓存)扩展时,可通过修改子服务的Data Service,实现对下层数据的透明。

 

4、数据层的扩展

 

随着业务的增长,数据层面临的压力会越来越大,单机数据库已经不足以支撑。对于大多数的业务场景来说,数据的操作都是读多写少,而且读都集中在少部分的热点数据上,首先应该引入缓存层来缓解数据库的读压力,如果缓存容量需求比较大,可以构建缓存集群,在上层按照 consistent hashing 算法将数据分散到多个节点,后续需要增加新缓存节点时,只有少部分的数据会失效。

 

接着引入新的数据库种类,Redis 已经成为诸多企业的首选标配,因为其支持丰富的数据类型和数据查询接口,且内存型的数据库天然具有更高的性能。将业务中关系性要求不高的数据,从 MySQL 转移到 Redis 中,尤其是列表类的数据以及计数统计类的数据。给 MySQL 减负的同时提高数据的查询性能。

 

对于 MySQL 的扩展可以分为几个步骤来做。首先,增加 MySQL slave 节点,在上层将部分读请求分发到 slave 节点上去,由于 slave 同步可能有延时,业务应该能容忍短暂的数据不一致现象。即便有 slave 作为数据副本,也应该定期对数据库进行冷备份,方便当业务出现误操作时,能够回滚或恢复到曾经的某个时间点。

 

分库分表技术。将比较庞大的数据表拆分出来单独存放,可以给主数据库腾出来一部分空间,分担读写压力。拆分的时候,还可以按照功能逻辑,把相关联的数据表存在一个库里。当数据库单表非常庞大,对读写都造成瓶颈时,需要开始考虑水平分表 sharding,这种扩展方式可以同时解决单表容量过大,读压力和写压力很大的问题,但带来的研发和运维难度也会增大,推荐把上述的优化做完以后,最后在有必要的情况下再做。

 

水平分表的要点。首先要从数据表的字段中,选择一个合理的分区键(shard key),这个键应该是所有该表查询条件里,最经常用到的字段,这样才会使大部分的查询,能够提前判断应该向哪些特定的分区(shard)发送请求,如果查询条件中不带shard key,需要遍历所有的分区,并将结果进行merge。有了 shard key 还要设计一种分区算法,比如常见的有按照区间,如 user_id in [0, 100] 在 shard 1,user_id in [101, 200] 在 shard2,还比如按照 hash 取模等等。设计分区算法的时候要充分考虑业务特点,多从读写操作的角度思考,这么设计能否将压力和数据均匀分摊到每个 shard 上去。

 

还需要考虑数据层的扩展如何对上层透明,比如引入分布式数据库中间件,或者结合业务逻辑把数据库操作做成一个独立的子服务,供其它服务调用。如果不做成子服务,至少在业务代码里有独立的一层来封装对数据库的操作。

 

5、多机房部署和异地容灾

 

云平台通过自营的骨干网光纤和多路环网技术,使得当机房出现网络故障时对用户无感知,在基础设施上保障了高可用性。但是用户的业务如果能够多机房部署,可以在分摊访问负载的同时加速区域访问,比如加速中国南北方的用户或者海外用户的访问。多机房部署通常见的方案:

 

-异地冷备份:把主机房全套业务在异地重新构建一遍,且不需要提供线上服务,只有在主机房出现故障的时候才切换到备用机房,部署相对要简单一些。但有两方面缺点,一是成本比较高,需要双倍的费用且只是用来做冷备份,平时完全用不上;另外,当主机房突然挂掉时,备用机房再起动起来提供服务,数据需要预热,这是非常缓慢的过程,可能会出现服务响应慢,甚至不能正常提供服务。

 

-异地多活。从易到难有三阶段:第一,反向代理,用户请求到第二个机房,但不做任何处理被转向第一个机房这样会对两地的延时有一定的要求。第二,在第二个机房部署应用服务器和缓存,大部分的数据请求可以从缓存中读取,不用进行跨机房请求,但当缓存失效时,依然落到第一个机房的数据库去查询。所以,这个方式不太彻底;第三,全套服务的部署,包括HTTP服务器、业务服务器、缓存和数据库的 slave。此方式使得进入第二个机房的请求,只需要在机房内就可以完成请求处理,速度更快,但会遇到数据一致性和缓存一致性的问题,针对这点也会有一些解决方法。

 

小结

 

架构不是设计出来的,而是进化而来的,构建稳定可靠的业务系统需要注意以下这些:

 

-分析用户行为,理解你的业务,如社交、电商、视频;不同的业务有不同的行业属性和特点,对于社交来讲,比较典型的特点是数据量庞大、数据查询维度多,需要合理的做数据层面的扩展;电商的特点是定期举办大促销活动,届时会需要大量的计算资源、应用服务器来扛流量峰值,此时可利用云计算平台的弹性实现快速扩展业务;视频业务有非常明显的流量高峰期和低峰期,可利用云计算弹性优势,来调用API方式调整业务带宽资源,从而达到节省成本目的。

 

-合理规划系统,预估系统容量,如 10w / 100w / 1000w PV(DAU):不同的系统容量有可能对应不同架构的部署方式,找到最适合自己的那一个;

 

-系统是可横向扩展的 scalable;

 

-不遗余力地解决单点问题;

 

-为出错而设计 design for failure:App的后端架构在开发之就要为可能出现的各种问题进行准备,比如异地备份等;

 

-设计面向服务的架构,拆分子系统,API 交互,异步处理;

 

-构建无处不在的缓存:页面缓存、接口缓存、对象缓存、数据库缓存;

 

-避免过度设计,好的系统架构不是设计出来的,而是进化而来的;

 

参考文章:

https://community.qingcloud.com/topic/395

https://community.qingcloud.com/topic/8

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics