| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 记一次线上接口慢查询问题排查 -> 正文阅读 |
|
[大数据]记一次线上接口慢查询问题排查 |
目录 问题描述? ? ? ?有一个分类预测的接口,主要业务逻辑是输入一段文本,接口内部调用模型对文本进行分类预测。 模型数据是直接在内存中,所以预测的过程本身很快。预测完成之后,往预测记录表插入一条数据。后续有其他应用会对该记录进行矫正,判断是否预测成功,以便后续进行自学习。 ? ? ? ?接口上线初期好评如潮,不管是做智能派遣还是经办单位流转预测使用效果都很好,随着自学习功能加入,预期应用应该会越跑越好。但是前两天客户现场突然反馈系统很慢,做智能派遣和流转的时候要三四秒甚至五六秒才能出结果。 ? ? ? ?最开始想的是现场的分类模型太多,模型树也比较深,所以一次多级预测不可避免会比较耗时,但是核查后发现最多的模型树只有四级,单个模型直接验证预测结果都是毫秒出结果,但是直接调用接口就很慢。 如果不是算法模型的问题,也不是机器资源的问题,那一定是代码逻辑中有没有考虑到的点,而且随着数据量激增,问题越来越明显。 ? ? ? ?经过简单排查,发现问题非常低级,造成慢的主要原因是因为预测记录表的数据已经将近100w了,而且这个表没有任何索引,只有一个自增主键,程序中,因为业务逻辑需要,每次调用预测接口都会有一个查询再更新或者插入的动作,并且是同步的。那么随着数据量的激增,接口的RT注定会越来越慢。 解决方案? ? ? ?问题是个小问题,主要原因还在于接口设计的初期没有做深入的考虑,代码写的很漂亮,只可惜不经考验,绣花枕头一个。对于这种问题,最直观的方案就是解耦,预测和预测记录入库做成异步的。 当然如果有业务场景硬要求不得不做成同步,也可以从代码层面和数据库层面做优化增加处理速度。 1 消息中间件(1)可以直接引入kafka或者RocketMQ进行解耦,这种比较保险,数据不会丢,而且可以做到核心功能和非核心功能解耦。是主流解决方案,并且支持横向扩展和分布式。 (2)如果不想使用MQ,也可以直接使用Redis,Redis也可以实现消息队列的功能,参考这里 2 代码及数据库优化? ? ? ?如果不得不同步操作,那就要从代码层面进行优化和调整,主要以下几个思路: (1)给查询的字段添加索引,通过数据库的能力提升IO (2)设置分区表或者天表(月表)的概念,降低单表的数据量 (3)代码优化,将查询后的更新或者插入合并为一个sql操作,参考这里
? ? ? ?对于异步解耦这种方案,如果之前应用本身没有MQ、Redis,为了解决该问题安装这些中间件,从某种程度上来说这无疑增加了系统复杂度好运维集成的工作量。基于此,我们也可以使用java自身的多线程来实现异步,基本思路就是在需要进行IO操作的地方,直接开启一个新线程去处理。 ? ? ? ?但是如果请求量很大,这无疑会造成频繁的线程创建、释放资源问题,如果引入线程池,又可能会出现因为资源用完阻塞的情况,这不能根本上解决同步的问题。? ? ? ? ?可以通过java多线程模拟消息队列,在需要进行IO操作的业务代码处,将业务数据封装为Bo放到一个队列中。有一个独立的线程对队列进行消费处理即可。可以参考这里 ? ? ? ?我主要是使用了ConcurrentLinkedQueue来解决了此问题,基本思路是,创建了一个定时任务,每30秒执行一次,每次都去处理ConcurrentLinkedQueue队列中的数据,将数据入库。 而业务代码中是将业务数据封装成Bo放到队列中去了。 3?ConcurrentLinkedQueue方案定时任务
异步处理
业务流程
其他? ? ? ?如上的改造方式实际上是有隐患和弊端的 (1)如果接口调用量很大,难免会有消息积压,这时候如果节点挂了,那数据就丢失了。 (2)消息如果有大量积压,有可能撑爆内存,这样是会影响应用正常使用,也会造成数据丢失。 (3)无法支持多个消费程序。 (4)消费入库的逻辑实际上和核心的预测功能没关系,但是如果因为消费数据多,势必会影响核心预测功能的使用。这从软件架构上来说是不合理的。 ? ? ? ?上述这些问题通过MQ或者Redis都能很好的解决。? ? ? ? ?但是,但是任何事情没有绝对的,很多时候需要因地制宜,需要根据实际的业务要求、数据要求、项目紧急情况、成本预算等等,考虑到底使用哪种解决方案。 ? ? ? ?比如:通过单节点多线程ConcurrentLinkedQueue的方式就能解决99%的问题,所需要的成本预算是1,开发周期1天,而通过MQ能解决99.9%的问题,所需成本预算是10,开发周期7天。客户允许的容错是5%。这时候明显没有必要使用MQ的方案,没意义。 ? ? ? ?其实我所想表达的意思是,任何事情没有绝对的,我们始终应该抱着一种开放的心态去面对问题,没必要为了0.1%的优点引入99%的额外投入。 参考文献 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/16 5:14:38- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |