在Java工程中,有些措施可以明显提高程序的性能,降低程序运行耗时:
批量处理
主要用于Java程序和其他系统交互的时候,比如:和MySQL、Redis、Mongodbd等存储系统交互、和第三方的接口交互;批量读写能大量减少和这些系统的交互次数,有效降低耗时。多线程处理
把原本顺序执行的程序使用多线程并发处理,例如:读多个表,可以多线程并行读。不过需要注意的一点是,如果Java进程CPU使用率已经很高了,就不建议增加线程了,此时如果增加线程有可能出现反向结果,毕竟多线程涉及上线文切换,是一笔不小的开销。使用Google集合框架的Lists.partition函数可以轻松的把集合分成指定数量的多批量集合,然后每个线程处理其中一个批次。异步处理
对于一些在线项目,请求过程中某些处理是可以考虑异步处理的,例如:在召回过程中,保存推荐历史、记录推荐埋点等操作,没必要等这些操作执行完毕再响应客户端,可以跑线程异步做这些操作,经验证能够大幅度降低RT,尤其是对P99的降低有很大帮助。缓存
引入缓存可以大幅降低RT、增加QPS,哪怕缓存时间很短(比如几分钟),也可以大量减少流量打到存储系统。能把数据缓存到本地绝不缓存到Redis,能读Redis绝不读MySQL等存储系统。缓存时需要处理好缓存雪崩和缓存穿透等问题。缓存雪崩可以通过打散缓存时间解决,使用Caffeine时实现Expiry即可;对于缓存穿透,对于不存在的数据可以缓存特定的值,由于不存在的数据有可能会在后面的某个时间点出现,所以对这部分数据的缓存时间可以稍微短一点。另外对于一些计算的结果也可以做缓存,比如:物料是否是指定类型的视频,判断需要遍历物料的一级分类,同一个物料会被多次召回,那么这个结果就可以缓存,不需要每次都计算一次。熔断降级
熔断降级除了可以保护系统,还可以稳定调用时长,减少平均RT不要处理过多的数据
例如:向量重排,每次返回给用户8条数据,那么向量重排只需要排出8个物料即可return,实在没必要把召回的几千个物料都排个序。