在海量并发业务的场景下,比如电商抢购、微信红包这样的场景下,我们经常会遇到各种各样的性能问题,在应对这些问题的时候,应该有怎样的方法论去指导我们解决问题,基于这几年的开发经验,做一个简单的分享。性能优化包含两个方面的理解:
在比较大的互联网公司中,一般不会直接使用开源的框架做业务开发,这里就涉及到框架的性能问题,一般的框架都需要解决几个问题
不过,本文不讨论框架层面的性能优化,更多的是介绍业务层面的相关技术手段
以上技术手段在MY微信红包中的具体实现
1.前端保护后端
在高并发的场景中,瞬间的并发量是非常大的,因此请求应该呈现一个漏斗型往下递减
所以,我们在前端CGI层利用缓存(如redis、memcache等)做了一些优化,比如在抢红包的场景中,用redis存储红包剩下的个数,每个人是否抢过这个红包这些标识, 尽量只让真正可以抢红包的请求通过CGI层落入逻辑层,快速的过滤掉不合理的请求。
在前端,我们一般用CDN(或者类似的数据靠近服务)做前端页面的加速;
接入层作为后端的第一个模块,接收最多的请求,一般的优化方式有合并请求,数据预加载等,在云监控的场景中,前端接入层需要接收大量的数据点,需要屏蔽无效的数据点,这里就会有数据预加载的请求,将接入的信息(变更频率很低)预加载到内存中,请求进来之后根据内存中的预存储数据做数据的过滤。
2.业务流程解耦
在业务开发过程中,我们经常会遇到耗时的场景,比如在抢红包入账的场景中,入账的操作是一个事务,耗时比较长,放在核心流程中,会影响整体的吞吐量,或者是在监控数据上报的场景中,后续的数据梳理和告警判断都是很重的业务逻辑,这就需要我们去解耦这个流程,利用消息队列对这个入账的流程或者其他的处理流程进行解耦,保证并发量 ,如下图,是笔者最近开发的事件中心架构,就用到CKafka做业务的解耦
3. 数据库分库分表
分库分表作为一个比较老的手段,依然是很有效的增加并发能力的方法(因为我们很多不经意的查询或者更新都会导致锁表)。例如在红包的根据红包ID,将红包落入不同的表中,这样在抢红包的场景中,DB的锁的压力就分散到各个表中,这里如何做分表是调优的关键,核心思想就是均匀的分配数据。
本身如何均匀的做数据分配也是一个比较难的问题,我们在监控数据的存储中,也会遇到这样的问题,监控的数据一般会用KV存储,基于LSM的HBASE和在这个基础上做了优化opentsdb是比较主流的选择,opentsdb不仅针对时序数据的特点做了优化,同时,针对rowKey的生成方式也做了比较多的改进,避免数据分布不均导致数据热点的产生,这里不展开讨论。
4. 柔性可用,过载保护可降级
在数据层发生灾难、系统负载高的情况下,保证业务的最核心流程可用,牺牲一些用户体验来达到系统的稳定。例如对抢红包的返回结果进行降级,不返回红包列表等,只让用户看到自己抢的红包的结果。
5. Set化部署
以最近参与的云监控项目为例,腾讯云现在的地域非常广,最新的地域现在在俄罗斯(欢迎试用),海外地域到国内的数据延迟一般在300ms以上,这就要求我们在所有地域都有Set去做就近接入,减少因为网络延迟带来的影响,云监控现在在每个地域都是单独部署,只有告警发送模块等少量服务是集中部署的
工作接近五年,前面的三年多的时间一直从事的是2C产品的开发,经历过苦哈哈的计算内存空间的时候,因为2C的数据体量远比2B的产品要大,TX以前的A/B/C的服务器性能也一般(从现在看来),在这种场景下成长起来的程序员都会比较抠门,更多的去想如何节省机器,当然现在我觉得也是有一定参考价值的,希望对你有用