高并发服务的几条优化经验
共 3101字,需浏览 7分钟
·
2022-06-13 08:18
前言:如何优化高并发服务,这里指的是qps在20万以上的在线服务,注意不是离线服务,在线服务会存在哪些挑战呢?①无法做离线缓存,所有的数据都是实时读的 ②大量的请求会打到线上服务,对于服务的响应时间要求较高,一般都是限制要求在300ms以内,如果超过这个时间那么对用户造成的体验就会急剧下降 ③数据量较大,单次如果超过50W的qps,单条1kb,50万就是5GB了,1分钟30G,对于底层的数据存储与访问都有巨大的压力~ 如何应对这些棘手的问题,本篇博客来讨论一下
一:向关系型数据库sayno
一个真正的大型互联网面向c端的服务都不会直接使用数据库作为自己的存储系统,无论你是采用的是分库分表还是底层用了各种优秀的连接池等,mysql/oracle在面对大型在线服务是存在天然的劣势,再如何优化,也难以抵挡qps大于50万流量带来的冲击。所以换个思路,我们必须使用nosql类缓存系统,比如redis/mermCache等作为自己的"数据库",而mysql等关系型数据库只是一种兜底,用于异步去写作为数据查询的备份系统。
场景举例:京东双11主会场,上架了部分商品,这部分商品都是在会场开始上架的时候直接写入redis中的,当上架完成之后,通过异步消息写入到mysql中。面向c端的查询都是直接读redis,而不是数据库.而b端的查询,可以走数据库去查询。这部分流量不是很高,数据库绝对可以抵挡的住。
二:多级缓存
都知道缓存是高并发提高性能的利器之一。而如何使用好缓存进而利用好多级缓存,是需要我们去思考的问题。redis目前是缓存的第一首选.单机可达6-8万的qps,在面对高并发的情况下,我们可以手动的水平扩容,以达到应对qps可能无线增长的场景。但是这种做法也存在弊端,因为redis是单线程的,并且会存在热点问题。虽然redis内部用crc16算法做了hash打散,但是同一个key还是会落到一个单独的机器上,就会使机器的负载增加,redis典型的存在缓存击穿和缓存穿透两个问题,尤其在秒杀这个场景中,如果要解决热点问题,就变的比较棘手。这个时候多级缓存就必须要考虑了,典型的在秒杀的场景中,单sku商品在售卖开始的瞬间,qps会急剧上升.而我们这时候需要用memeryCache来挡一层,memeryCache是多线程的,比redis拥有更好的并发能力,并且它是天然可以解决热点问题的。有了memeryCache,我们还需要localCache,本地缓存,这是一种以内存换速度的方式。本地缓存会接入用户的第一层请求,如果它找不到,接下来走memeryCache,然后走redis,这套流程下来可以挡住百万的qps.
三:多线程
四: 降级和熔断
降级和熔断是一种自我保护措施,这和电路上的熔断器的基本原理是一样的,防止电流过大引起火灾等,面对不可控的巨大流量请求很有可能会击垮服务器的数据库或者redis,使服务器宕机或者瘫痪造成不可挽回的损失。因为我们服务的本身需要有防御机制,以抵挡外部服务对于自身的侵入导致服务受损引起连带反应。降级和熔断有所不同,两者的区别在于降级是将一些线上主链路的功能关闭,不影响到主链路.熔断的话,是指A请求B,B检测到服务流量多大启动了熔断,那么请求会直接进入熔断池,直接返回失败。如何抉择使用哪一个需要在实际中结合业务场景来考虑.
五: 优化IO
很多人都会忽视IO这个问题,频繁的建联和断联都是对系统的重负。在并发请求中,如果存在单个请求的放大效那么将会使io呈指数倍增加。举个例子,比如主会场的商品信息,如果需要商品的某个具体的详情,而这个详情需要调用下游来单个获取.随着主会场商品的热卖,商品越来越多,一次就要经过商品数X下游请求的数量,在海量的qps请求下,IO数被占据,大量的请求被阻塞,接口的响应速度就会呈指数级下降。所以需要批量的请求接口,所有的优化为一次IO
六: 慎用重试
重试作为对临时异常的一种处理的常见手法,常见应对的方式是请求某个服务失败或者写数据库了重新再试,使用重试一定要注意以下几点①控制好重试次数②重试的间隔时间得衡量好③是否重试要做到配置化。之前我们线上出了一个bug,kafka消费出现了严重的lag,单词消耗时间是10几秒,看代码之后发现是重试的次数过多导致的,并且次数还不支持配置化修改,所以当时的做法只能是临时改代码后上线.重试作为一种业务的二次尝试,极大提升了程序的请求success,但是也要注意以上几点。
七:边界case的判断和兜底
作为互联网老手,很多人写出的代码都不错,但是在经历过几轮的故障review之后发现很多酿成重大事故的代码背后都是缺少对一些边界问题的处理,所犯的错误非常简单,但是往往就是这些小问题就能酿成大事故.曾经review过一次重大的事故,后来发现最终的原因居然是没有对空数组进行判空,导致传入下游的rpc是空的,下游直接返回全量的业务数据,影响数百万用户。这个代码改动起来很简单,但是是令人需要反省的,小小的不足酿成了大祸
八:学会优雅的打印日志
总结: 本篇博客讨论了高并发服务在面对大流量时的一些基本注意事项和应对的点,当然实际线上的比目前的更复杂,这里只是给出几条建议,希望我们在高并发的路上保持敬畏,继续探索.更好的深耕c端服务,做更好的互联网应用,加油
热门推荐:
PS:如果觉得我的分享不错,欢迎大家随手点赞、转发、在看。