首页 > 其他分享 >高并发服务的几条优化经验 转载

高并发服务的几条优化经验 转载

时间:2023-02-09 09:56:59浏览次数:47  
标签:缓存 服务 redis 多线程 并发 几条 qps 日志 转载

如何优化高并发服务,这里指的是qps在20万以上的在线服务,注意不是离线服务,在线服务会存哪些挑战呢?

  1. 无法做离线缓存,所有的数据都是实时读的

  2. 大量的请求会打到线上服务,对于服务的应时间要求较高,一般都是限制要求在300ms以内,如果超过这个时间那么对用户造成的体验就会急剧降

  3. 数据量较大,单次如果超过50W的qps,单条1kb,50万就是5GB了,1分钟30G,对于底层的数据存储与问都有巨大的压力~

如何应对这些棘手的问题,本篇博客来讨论一下

一:向关系型数据库 say no

一个真正的大型互联网面向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.

三:多线程

我记得在刚开始入行的时候,每次面试都会被问到多线程,那时候是一脸懵逼,多线程有这么厉害吗?干嘛都说多线程,为什么要使用多线程,不用行不行?要讲明这个道理,我先来说一个实例.曾经我优化过一个接口,很典型的一个场景。原始的方式是循环一个30-40万的list,list执行的操作很简单,就是读redis的数据,读一次大概需要3ms左右,这是同步的方式,在预览环境测试,直接30秒+超时。后来优化的方式就是把原有的同步调用改为线程池调用,线程池里的线程数或阻塞队列大小需要自己调优,最后实测接口rt只需要3秒。足以见多线程的威力。在多核服务的今天,如果还不用多线程就是对服务器资源的一种浪费。这里需要说一句,使用多线层一定要做好监控,你需要随时知道线程的状态,如果线程数和queueSize设置的不恰当,将会严重影响业务~ 当然多线程也要分场景,如果为了多线程而多线程反而是一种浪费,因为多线程调度的时候会造成线程在内核态和用户态之间来回切换,如果使用不当反而会有反作用

四: 降级和熔断

降级和熔断是一种自我保护措施,这和电路上的熔断器的基本原理是一样的,防止电流过大引起火灾等,面对不可控的巨大流量请求很有可能会击垮服务器的数据库或者redis,使服务器宕机或者瘫痪造成不可挽回的损失。因为我们服务的本身需要有防御机制,以抵挡外部服务对于自身的侵入导致服务受损引起连带反应。降级和熔断有所不同,两者的区别在于降级是将一些线上主链路的功能关闭,不影响到主链路.熔断的话,是指A请求B,B检测到服务流量多大启动了熔断,那么请求会直接进入熔断池,直接返回失败。如何抉择使用哪一个需要在实际中结合业务场景来考虑.

五: 优化IO

很多人都会忽视IO这个问题,频繁的建联和断联都是对系统的重负。在并发请求中,如果存在单个请求的放大效那么将会使io呈指数倍增加。举个例子,比如主会场的商品信息,如果需要商品的某个具体的详情,而这个详情需要调用下游来单个获取.随着主会场商品的热卖,商品越来越多,一次就要经过商品数X下游请求的数量,在海量的qps请求下,IO数被占据,大量的请求被阻塞,接口的响应速度就会呈指数级下降。所以需要批量的请求接口,所有的优化为一次IO

六: 慎用重试

重试作为对临时异常的一种处理的常见手法,常见应对的方式是请求某个服务失败或者写数据库了重新再试,使用重试一定要注意以下几点

  • 控制好重试次数
  • 重试的间隔时间得衡量好
  • 是否重试要做到配置化。之前我们线上出了一个bug,kafka消费出现了严重的lag,单词消耗时间是10几秒,看代码之后发现是重试的次数过多导致的,并且次数还不支持配置化修改,所以当时的做法只能是临时改代码后上线.重试作为一种业务的二次尝试,极大提升了程序的请求success,但是也要注意以上几点。

七:边界case的判断和兜底

作为互联网老手,很多人写出的代码都不错,但是在经历过几轮的故障review之后发现很多酿成重大事故的代码背后都是缺少对一些边界问题的处理,所犯的错误非常简单,但是往往就是这些小问题就能酿成大事故.曾经review过一次重大的事故,后来发现最终的原因居然是没有对空数组进行判空,导致传入下游的rpc是空的,下游直接返回全量的业务数据,影响数百万用户。这个代码改动起来很简单,但是是令人需要反省的,小小的不足酿成了大祸

八:学会优雅的打印日志

日志作为追溯线上问题的最佳利器,可谓保留bug现场的唯一来源。虽然有arthas这样的利器方便我们排查问题,但是对于一些比较复杂的场景,还是需要日志来记录程序的数据.但是在高流量的场景中,如果全量打印日志对于线上来说就是一种灾难,有以下缺点:

  • 严重占用磁盘,估算以下,如果接口的qps在20万左右,日志一秒就几千兆,一天下来就是上千GB
  • 大量的日志需要输出,占用了程序IO,增加了接口的RT(响应时间) 如果需要解决这个问题,我们可以利用限流组件来实现一个基于限流的日志组件,令牌桶算法可以限制打印日志的流量,比如一秒只允许打印一条日志 - 基于白名单的日志打印,线上配置了白名单用户才可以打印出来,节省了大量了无效日志输出

总结

本篇博客讨论了高并发服务在面对大流量时的一些基本注意事项和应对的点,当然实际线上的比前的更复杂,这里只是给出几条建议,希望我们在高并发的路上保持敬畏,继续探索.更好的深耕c端服务做更好的互联网应用,加油!

链接:https://www.cnblogs.com/wyq178/p/15811956.html

标签:缓存,服务,redis,多线程,并发,几条,qps,日志,转载
From: https://www.cnblogs.com/testzcy/p/17104169.html

相关文章

  • SQL 优化大全,收藏直接起飞! 转载
    转自:https://mp.weixin.qq.com/s/n2yb1Kl4fMbndzG_z1-4tw大家好,今天分享一篇关于SQL优化的硬核文章,全文有点长,建议收藏后慢慢看。很多朋友在做数据分析时,分析两分钟,跑数......
  • 并发、并行、串行
    并发并,顾名思义,就是首先是多条“路”共同执行。并发的意思就是一个CPU在某一个时间执行多个任务。例如写代码,既要查数据库,又要码代码,一直在查数据库和码代码中切换......
  • 【转载】一款含金量超高的专利数据库使用简介——德温特创新索引
    原文地址:一款含金量超高的专利数据库使用简介——德温特创新索引(njust.edu.cn)  ========================================  科睿唯安的德温特是全球最知......
  • 大哥,这是并发不是并行,Are You Ok?
    本文内容整理自**博学谷狂野架构师**多线程概述基础概念进程和线程进程是程序运行资源分配的最小单位​ 进程是操作系统进行资源分配的最小单位,其中资源包括......
  • 阻塞式并发队列
    --BlockingQueue:阻塞式队列--可以实现生产者消费者模式 --LinkedBQ:链表实现    --ArrayBQ:数组实现,有限队列    --Delay......
  • 【转载】过滤器+spring拦截器处理服务请求日志打印
    思路:通过拦截器拦截HttpServletRequest请求,从请求对象中获取请求流,解析请求参数,封装对象打印请求参数日志痛点:Requestbody只能读取一次,因为是流。想想看,java中的流也是......
  • 并发相关知识点
    并发并发不提高,可用就是耍流氓基础设施在分层架构中,最底层就是基础设施,一般来说包含物理服务器、IDC、部署方式等等,就像一个金字塔,只有底座稳定了,上层才能稳定。基础......
  • 如何保证redis的高可用,高并发
    高可用考虑如何用redis来加多台机器,保证redis是高并发的,还有就是如何让redis保证自己不是挂掉以后就直接死掉了,即redis高可用高并发redis实现高并发主要依靠......
  • [转载]Linux关于磁盘操作命令
    一、查看篇1.1、du:查看文件和目录的使用空间语法:du[参数] [文件或目录]参数说明-a列出所有的文件与目录容量。-h以G、M、K为单位,返回容量。-s列......
  • Python 高级编程之并发与多线程(三)
    目录一、概述二、并发与并行原理1)并行2)并发3)并发和并行区别三、Python多线程1)进程与线程关系2)Python多线程GIL介绍3)Python创建多线程1、thread2、threading(常用)4)守护线......