参与XXX项目的XXXX模块开发,里面有个GPS数据对接的需求,对方通过FTP服务器发送csv文本数据,30秒一个文件,一个文件大约10万条数据。

一开始的想法是先把文件下载到本地,然后开启多线程处理数据,处理一条更新一次表数据(这很疯狂!!!)。运行一个星期,发现当数据库性能被占用很多时,更新表数据会有严重延迟,最终造成数据丢失。

处理数据性能被浪费在更新表数据上面,就加上了数据缓冲区,当一定时间或者数据量积累到一定程度时,批量插入数据,性能一下大大提升。

接着觉得所有数据处理都在后台,哪怕打印日志也不能明显的展示数据处理速率,不够直观,于是开始改业务逻辑。分成两个服务,一个下载GPS文件并解析数据,然后将数据发送到RabbitMQ;另一个从RabbitMQ消费数据,启动多个服务消费。

这样通过消息队列可以起到削峰作用,另外选择RabbitMQ是因为它包含可视化插件,开启插件就可以通过 http:127.0.0.1:15672 去访问了。此外,支持多种交换机,功能丰富,还支持前端连接RabbitMQ(通过sockjs和stomp插件)。如果数据量再增加一个数量级,就需要Kafka了。

这就完了吗?并没有!

因为GPS数据里面包含的车辆信息非常少,页面展示时关联车辆信息表和GPS表显然不现实,所以每当有一条数据过来时,都需要先去查询其车辆信息,对数据库的压力也非常大(车辆信息数据量很大,有几千万)。分析后发现需要的车辆信息直到该车报废都不会有太大的变化,于是把这些静态数据用Redis缓存下来。

缓存半天+随机数,防止缓存雪崩;也有些车牌号不规范,导致查不到数据,为防止造成缓存穿透,也做了相应的处理(将不规范的车牌号记录到日志里面,后续与对方协商,或者打上补丁)。

对于我方来说,数据传输最好通过消息队列,处理起来很方便。但是对于对方而言,通过FTP传输很方便,因为不管有多少单位需要这个数据,只要给对方FTP的账户、密码,然后保证带宽足够就完了,没有开发量。

总而言之:在合适的情况下,增加缓冲区,减少对数据库的访问;利用消息队列削峰;静态并且频繁使用的数据利用 Redis 缓存。