消费日志数据,月数据量上十亿的数据量,校验规整数据入库。主要遇到遇到的问题如下:
入库IO性能瓶颈
缓存出库流量过大
消费数据延迟
方案步骤
1.日志依次入库
按照消费的速率,把处理正确的日志一条一条入库。
优点:无延迟,只要消费的够快我入库的就会很快。
缺点:IO消耗比较大,IO成了瓶颈。
2.调用官方的批量入库SDK(失败)
优点:有官方写好的入库逻辑,只需要按接口调用,入库速率有保证,IO消耗低。
缺点:官方提供的在线文档和我们用的数据库版本不统一,没有我们用的高版本数据库的API。
3.内存攒一批然后入库
在内存中把入库的数据攒一批,比如攒够一千条再入库。
优点:IO会降下来,入库速率也有保证。
缺点:如果系统重启,内存的攒的数据会丢失,最多每个表丢999条数据。如果数据库入库速率跟不上,会一直往内存放数据,导致内存数据爆满。
4.利用redis做缓存再入库
把缓存的内存的数据,修改到缓存到redis,利用redis的List结构,攒够1000条,然后全部取出然后入库。
优点:重启数据不会丢失,入库速率和IO适中。
缺点:redis出库宽带消耗过大,因为是一次取的数据过多。还有多个服务同时取出相同的一千条数据的风险。
5.redis缓存出库策略优化
入redis策略不变,出库一个一个用pop弹出。就是一个消息队列。左边进,右边弹出。
优点:不会存在被多个服务同时消费掉一条数据,redis出库宽度性能得到大幅度优化。因为是匀速消费,做到了销峰,内存不会一直累加,导致内存爆满。
缺点:
redis弹出之后,是一个一个的,还是需要在内存中攒一批数据入库。
如果重启还是会丢失数据需要redis用一个备份队列,把攒的数据同时存到redis,等重启之后,先去备份队列消费入库,做到数据不丢失。
pop弹出速率跟不上。导致入库速率没有达到最大性能。
6.把整合好的数据再入日志服务然后消费
把规整好的数据放到sls里面,然后再起一个任务消费然后赞一批入库
优点:可能性能高于redis的入库出库策略。规整好的日志其他业务线也可正常使用不用校验。
缺点:日志系统会存在多份数据。
7.最终方案
服务拆分为生产者和消费者,延续6的方案。
消费者消费的时候,在内存攒一批入库,同时在redis缓存一份,入库完删掉,如果服务重启或者入库失败,去Redis缓存里面先把未入库的数据入库再消费正常数据。
8.未实现的其他方案
用Rabbitmq替代redis的消息队列,提高速率。
规整好的数据直接借助日志服务投递到数据库,但只能适用于固定字段的投递,字段有变动不能适配。
历时两周,改了5 6个版本,脑子都快不够用了。算是个简单的业务记录复盘吧,以后遇见相同的业务逻辑拿来参照。