1 导读
高并发系统的奥义:高性能、高可用、可扩展。
- 性能反应了系统的使用体验
都是上万QPS的系统,一个响应时间毫秒级,一个秒级,用户体验明显不同 - 可用性则表示系统可以正常服务用户的时间
上万QPS的系统,一个可全年不停机且无异常,一个隔三差五就宕机 - 可扩展性
流量可分为平时流量、峰值流量。峰值流量可能会是平时流量的几倍至几十倍,在应对峰值流量时,通常需在架构方案上做更多准备。易于扩展的系统能在短期内迅速扩容,更加平稳分摊峰值流量。
业务价值->承载高并发->性能优化。
一切的前提是业务价值需要。如果没有足够价值,那可读性才是第一,性能在需要的地方是no.1,但不需要的地方可能就是倒数第一。当下技术框架出来的软件差不到哪去,没有这种及时响应诉求的地方,削峰下慢慢跑就是了。(但工作中常需要在缺少价值的地方着手性能优化。异步,并发编程,逻辑缓存,算法真的会加剧系统的复杂度,得不偿失。如果没那个价值,简单才是王道)。
提高并发度
- 要么加硬件
- 要么降低服务响应时间
做为开发,我们的目光更聚焦在降低响应时间:
1.采用非阻塞的rpc调用(高效的远端请求模式,采用容器的覆盖网络我认为也算)
2.将计算密集和io密集的的逻辑分割开,单独线程池,调整线程比例压榨单机性能(或者说找拐点)。
3.做缓存,io耗时的缓存和计算耗时的缓存(多级缓存,数据压缩降低带宽)。
4.采用享元模式,用好对象池和本地线程空间,尽量减少对象创建与销毁的开销,提高复用。
5.业务拆分,像状态变化后的外部系统通知,业务监控,es或solr等副本数据同步等操作,无需在主流程中做的事都拆掉。走canal监听表数据变化,推mq保最终一致的方式从业务项目完全解偶出来。
6.fork_join,分而治之的处理大任务。并发编程,采用多线程并行的方式处理业务。(规避伪共享,减小锁力度,采用合适的锁)。
7.数据库配置优化,查询优化。(存储优化比较头疼,毕竟不按业务拆单点跑不掉,单点性能就要命。基本只能内存库先行,后台同步数据做持久。然后内存库多副本,自修复,保留一系列自修复失败的修复手段)
2 性能优化原则
业务导向
脱离业务问题,妄自过早优化会徒增系统复杂度,浪费开发时间,也因某些优化可能会对业务上有些折中考虑,还会影响业务。
剑指主要矛盾
优先优化主要的性能瓶颈点
量化指标
在优化过程中,要时刻了解优化让响应时间降低多少,提升多少吞吐量。
持续优化
高并发系统的业务逻辑都很复杂,出现性能问题也有多方面原因。因此,我们在做性能优化的时候要明确目标,比方说,支撑每秒1万次请求的吞吐量下响应时间在10ms,那么我们就需要持续不断地寻找性能瓶颈,制定优化方案,直到达到目标为止。
在以上四个原则的指引下,掌握常见性能问题的排查方式和优化手段,就一定能让你在设计高并发系统时更加游刃有余。
3 性能的度量指标
一般度量性能的指标是系统接口的响应时间,需要收集一段时间的响应时间数据,然后依据统计方法计算特征值,这些特征值就能够代表这段时间的性能情况。常见的特征值有以下几类。
平均值
这段时间所有请求的响应时间数据和/总请求数。
在一定程度上反应这段时间的性能,但它敏感较差,若这段时间有少量慢请求,在平均值上并不能反应出来。
最大值
段时间内所有请求响应时间最长的值。
问题在于过于敏感。
分位值
有很多种,比如90分位、95分位、75分位。以90分位为例,我们把这段时间请求的响应时间从小到大排序,假如一共有100个请求,那么排在第90位的响应时间就是90分位值。分位值排除了偶发极慢请求对于数据的影响,能够很好地反应这段时间的性能情况,分位值越大,对于慢请求的影响就越敏感。
分位值是最适合作为时间段内,响应时间统计值来使用的,在实际工作中也应用最多。
平均值也可以作为一个参考值。
通常使用吞吐量或者响应时间来度量并发和流量,使用吞吐量的情况会更多一些。这两个指标是呈倒数关系:
响应时间1s时,吞吐量是每秒1次,响应时间缩短到10ms,那么吞吐量就上升到每秒100次。所以,一般我们度量性能时都会同时兼顾吞吐量和响应时间,比如我们设立性能优化的目标时通常会这样表述:在每秒1万次的请求量下,响应时间99分位值在10ms以下。
那么,响应时间究竟控制在多长时间比较合适呢?
从用户使用体验的角度来看,200ms是第一个分界点:接口的响应时间在200ms之内,用户是感觉不到延迟的,就像是瞬时发生的一样。而1s是另外一个分界点:接口的响应时间在1s之内时,虽然用户可以感受到一些延迟,但却是可以接受的,超过1s之后用户就会有明显等待的感觉,等待时间越长,用户的使用体验就越差。所以,健康系统的99分位值的响应时间通常需要控制在200ms之内,而不超过1s的请求占比要在99.99%以上。
现在你了解了性能的度量指标,那我们再来看一看,随着并发的增长我们实现高性能的思路是怎样的。
4 性能优化
假如说,你现在有一个系统,这个系统中处理核心只有一个,执行的任务的响应时间都在10ms,它的吞吐量是在每秒100次。那么我们如何来优化性能从而提高系统的并发能力呢?主要有两种思路:一种是提高系统的处理核心数,另一种是减少单次任务的响应时间。