大数据量接口优化
Solr游标查询
当时我们的数据平台需要根据用户输入的限制参数对Solr进行一次查询,普通查询通常会一次性地将所有查询结果加载到内存中,这在处理大量数据时可能会引起内存溢出(OOM)问题。
我在博客园看过一篇文章:全量查询200万数据时内存占用达到了1500MB,很容易导致OOM异常。而分页查询虽然可以避免内存溢出,但因为深度分页和多次与数据库的连接,导致查询时间很长,查询时间长达280秒,并且内存占用也接近500MB
相比之下,Solr的游标查询是一种更为高效的处理大数据量查询的方法。游标查询允许客户端在服务端打开一个游标,并按需检索数据,而不是一次性获取整个结果集。这种方式类似于客户端向服务端分批“pull”的过程,可以有效地减少内存占用并提高查询效率。在相同的测试条件下,游标查询200万数据的内存占用不到500MB,并且查询时间与流式查询相近,只需大约9秒多
Solr的游标查询还支持设置参数以优化性能和内存使用,例如通过CursorMarkParams参数控制游标的位置,以及通过setRows方法限制每次检索的数据量。当游标值没有变化时结束查询
所以当时在项目中使用了Solr的游标查询来处理大的数据量,代码中我看其他地方也有类似的思想,比如MongDB的查询也可以使用游标来查询其他的话像可以保持主键顺序插入,减少叶分裂、减少主键长度,因为二级索引存放主键
还有像深分页问题可以使用覆盖索引+子查询优化
最后可以使用Explain来分析Slq的执行计划,看一下他的type字段,尽量去走索引
搜索服务优化
因为公司还在用原始的SolrQuery来一个个拼接参数和一个个去手动解析结果。当时我使用构造者模式优化了一下,让传参的时候可以链式调用。并且还自定义了结果解析器来把查询的结果封装到一个List里面,然后再用Data数据包装一层,可以增加一些查询的时间参数什么的
就定义了一个抽象类,里面定义了通用模版,然后写一个Builder类来继承这个抽象类,实现里面的规则。然后让它每次设置完参数之后自己调用自己。
文档学习
官网崩溃
问题描述:官网核心功能-搜索崩溃,导致线上故障7分钟
在20:18分左右发现官网搜索出现问题,起初怀疑发布出错,经过检查并没有2.0的服务发布,随后发现进程没有启动,运维同学重启进行后故障解决。
排查是同事在19:50分在线上VI打开大日志文件,触发linux的OOM管理机制,导致jvm进程被杀。
教训:环境意识,意识到生产环境不同于测试环境,崩一次可能造成巨大损失
权限管理,需要对生产环境的访问权限进行严格控制,确保只有经过授权的人员才能执行敏感操作
优化日志管理系统,避免单个日志文件过大,可以考虑日志切割、归档和监控日志文件大小等措施
增强系统的监控能力,确保在出现问题时能够快速发现并发出告警,减少故障响应时间
排查OOM异常
当时是线上有个OOM异常,我们全组一起在线上排查解决,我更多是作为学习者的身份。
当时我学习到的就是,首先重启一下服务,先让服务能正常运行,然后再去赶紧排查
首先同事在本地启动,使用jps和jstat来看进程的占用空间大小,发现老年代的占比达到了90%,所以造成OOM的问题。
紧接着同事下载使用阿里的阿尔萨斯监控这个具体进程
使用dashboard仪表盘来动态查看内存占用详细信息,同时使用阿尔萨斯将内存快照dump到 本地文件中,然后将本地文件使用ftp传输到本机环境
使用visualVM工具进行分析来发现hashmap的node节点实例很多
思考是不是有什么在频繁建立对象或者连接什么的没有关闭导致
紧接着看这个实例的GC引用,发现底层的调用包名OSS,猜测可能链接有问题
根据实例定位到线程,找到方法具体位置,发现上次修改代码误删了一行关闭连接的代码,把代码加上之后,本地启动,并且打开阿尔萨斯的Memory选项看到恢复正常。
自定义组件
渠道宝项目介绍
渠道宝是tob的产品,主要是帮助公司发现渠道商机,然后跟进的一个产品。
公司使用的话一般得分为三个小组,资源外呼组,资源跟进组,线下拜访组。
资源外呼组负责对公司的联系人进行联系,系统会每天给外呼组分配10个渠道资源,外呼组联系公司的管理人员看是否有合作的意向,如果有就生成渠道信息表,给资源跟进组审核
审核通过后,资源跟进组就开始工作。对各个公司的渠道信息表进行管理和处理,是否建立面谈日程安排,以及线下拜访的安排。
线下拜访组就根据信息去进行线下拜访和拜访记录。
然后各个小组这样跟进工作。里面也集成了很多功能,比如消息通知,调用solr搜索服务,用户权限验证,资源自动分配,日程管理
资源分配讲一下
资源分配就是把渠道资源每天分给使用的公司的外呼小组的外呼人员。
因为要每天早上9点分配资源,所以需要用到自动任务,我是写了个task任务,然后在我们公司的自研平台去调用。
这个task任务就是先拉取所有待分配用户数据,拉取所有渠道资源库数据,用户数据按公司分组, 遍历,分配一个公司。
分配的时候是异步来分配每一个公司的每一个用户的
使用CompletableFuture.runAsync来执行异步操作,最大允许8个公司的用户一起跑
聚合操作
先说一下产品的需求:就是客户公司需要定制化的聚合后的数据
聚合操作分两步:
第一步,在Solr中查询一个公司是否之前参与过中标
第二步,根据项目id聚合成map,然后进行通用规则处理,利用反射拿到对应的属性名称和值,然后统计每一个属性下出现最多的值作为最终的属性值
设计模式优化
策略模式+工厂模式优化,类似于审批流场景
条件判断多,影响可读性
基于每一个分支抽象为一个策略,工厂保存所有的策略
使用工厂判断使用什么策略,来调用