有个系统,前端有个数据查询功能,原始逻辑大概是这样的:前台指定查询开始和结束时间,后台调用MongoDB,提取时间范围内的全部数据直接吐出csv格式文件。

当初估计没考虑数据量太大的情况,后来随着驻地的用户量上升,每日的数据量都变的很庞大,问题随之而来~

系统默认慢查询的触发时间是3秒,驻地查一周数据失败时会出现两种情况:MongoDB查询返回数据量太大,3秒根本无法全部返回,直接触发慢查询,Nginx前端报错;MongoDB返回数据成功,PHP吐csv的时候触发慢查询被直接杀死,导致csv数据不全。

大概流程图如下:
数据导出原始逻辑

当时给驻地的答复是:缩小查询时间……再我看来,这建议简直特么的智障……这建议不是逼驻地把一周的数据按天为单位查7次么?太特么傻B了。简直是打我的脸(这系统最初是前辈做的,后来我全部接手了,所以我算是继父)。

吐槽完毕,于是思考后,有了如下优化:
抽离按时间范围提取mongo数据的逻辑到后台脚本,前端请求后端生成csv,后端拉起shell运行后即返回,前端Ajax轮询后端shell生成的进度文件,达到100%,则激活前端下载按钮,允许用户下载csv文件。
如此,再也不会出现超时的情况,故额外扩展了其他字段的筛选功能以及前台Datatables展示功能。
对于前台Datatables展示功能,后端直接用shell中的sed实现翻页提取数据,不仅效率高,也避免了php运行太久超时等问题。

大概流程图如下:
数据导出调优升级后逻辑

局限性:调用shell使用的是exec,所以php.ini必须确保该函数可用,而为了避免安全问题出现,该函数通常是被禁用的。

核心思路:后端服务会超时,就丢给不会超时的shell,然后实时输出运行状态供前端查询确认。

该逻辑经过优化后,从此天下太平~

 

Related Posts: 数据查询超时的逻辑优化 :

avatar