1.1亲听项目前端
亲听项目专一于帮助用户收集、展现、监控和处理用户体验问题,是保证产品的主观评价质量的利器,关于其具体功能可参考在ata搜索"亲听"查看系列文章。目前亲听项目的实时流处理需求来自算法效果监控,算法效果监控须要对上游TimeTunnel日志进行解析后通过处理获得一些关键指标,亲听经过对这些指标的前端展现和阈值监控报警达到算法效果监控目的。算法
需求要点能够总结以下:sql
1.2全链路debugjson
全链路debug专一于帮助用户在线上搜索结果出现异常和问题时帮助开发者复现搜索后端各子系统的中间结果,定位并解决子系统存在的问题,是系统层级质量保证和测试的有力工具。关于其具体功能可参考在ata搜索"全链路debug"查看系列文章。全链路debug的实时流处理需求是实时从TimeTunnel日志中提取出帮助排除搜索线上问题的关键内容,全链路debug利用这些内容帮助进行问题排查。全链路debug的实时流处理需求模型能够用下图描述:后端
需求要点能够总结以下:api
2.1总体架构架构
应对以上需求,亲听以及全拉链路debug的实时流处理系统的最终架构以下:less
亲听:运维
全链路debug:函数
对于亲听和全链路debug的实时流处理需求最终选择上述架构主要出于实时性和扩展性两方面考虑
2.2实时性
亲听和全链路debug的实时流处理需求在实时性要求上是相似的,即要对接tt日志,在tt日志记录写入到对于亲听和全链路debug的使用方可见延时要控制在秒级,这种实时性的需求能够分解为两个部分,第一是对实时流数据的处理,而是对实时流数据处理结果的存储和查询服务。对于实时流数据的处理,目前公司内的中间件产品blink能很好知足咱们的需求,blink提供对接TimeTunnel的api接口,同时具有很好的实时流处理性能和运维体验;对于实时流处理结果的存储和查询,须要支持几万到几十万qps的写压力以及在天天累计几十T数据量状况下毫秒级延时的读性能,hbase可以基本知足对读写的需求,可是druid和drill可以在知足读写性能的同时提供更好的数据查询体验和实时流处理逻辑的可扩展性,因此对于实时流数据处理结果的存储和查询服务咱们是优先考虑druid和drill的,可是全链路debug的实时流处理结果有一个特色就是单条记录数据大小平均为几K左右,这么大的单条记录的大小将致使druid须要的内存量过大且查询性能低下而不可用,因此对于全链路debug的实时流处理结果的存储和查询服务选择了hbase。
2.3扩展性
在亲听实时流处理系统的下游引入tt->druid,而后使用drill查询druid提供查询服务,是出于对扩展性的考虑。druid是一种支持实时流处理和查询的olap系统(ATA),对接druid使得能够把一部分实时流数据的处理逻辑交给druid,这样当实时流处理逻辑须要修改时,不少状况下就能够经过修改查询逻辑(只要修改一个请求druid时的json配置文件)而不须要修改blink任务(须要修改代码、打包、编译、调参、上线)实现,大幅提高实时流处理系统的扩展性,而亲听实时流处理需求频繁变化的业务特色很是须要这种扩展性;drill是高性能的SQL查询引擎,经过drill对接druid提供查询服务不但使查询语法从druid的json文件变为sql可读性大幅加强,同时drill对druid查询结果具备的二次处理能力也进一步加强了经过修改查询逻辑能够知足的实时流处理逻辑变化,进一步加强系统可扩展性。
在blink和druid之间增长了TimeTunnel进行数据中转以保证blink产出流数据被转化为下游druid支持的流数据源形式。
2.4经验总结
使用table api编写
stream api做为blink的底层api,具备较高的灵活性,可是可读性很很差,进而很是影响代码的可维护性和扩展性,当要在实时任务中加入新需求时常常要改动不少地方而且很容易出错,全部实时任务咱们选择使用table api编写,table api使用类sql语法描述实时流处理逻辑,使得数据流处理逻辑变得很是清晰,可读性大幅加强,进而节约代码的维护和扩展成本。
进行字段归类合并
咱们经过梳理业务方最终须要使用的字段内容,将blink任务输出到TimeTunnel中记录的字段进行了分类合并,除了出于druid查询性能考虑将若干须要进行group by以及count distinct查询的原有字段保留,其他所有按照诸如搜索请求相关信息、用户相关信息、搜索返回宝贝相关信息这样的概念将原有字段分组后合并为多值字段,而每一个合并后的多值字段又会在blink代码中用一个udtf函数统一处理。这样作的好处在于代码逻辑上变得更清晰,当实时流处理需求发生变化,须要产出新的内容或修改现有内容产出逻辑时,只需找到新增内容或待修改内容对应的多值字段,修改对应udtf逻辑并从新上线blink任务便可,下游的druid build无需进行任何修改;同时用有限的几个udtf对整个实时流输出记录的处理逻辑进行归类,避免了记录处理逻辑频繁变化可能致使的代码中过期字段和udf泛滥,可读性降低,修改易出错的问题。
drill处理逻辑前移
请看下面这个sql:
select * from druid.sqa_wireless_search_pv where INSTR(auction_tag, '15')
这个sql drill的处理逻辑是从druid表中召回druid.sqa_wireless_search_pv表中所有记录后逐条进行auction_tag字段的比对,过滤出包含‘15’字符串的记录,这种召回所有记录进行处理的操做对于drill来讲会形成很大的性能问题,占用集群资源急剧上升,查询延时大幅提升,甚至致使集群oom使查询服务中断服务。在使用drill进行查询时应尽可能避免执行相似召回大量记录进行处理的sql,咱们对亲听算法效果监控现有sql进行了梳理,找到召回记录数目可能会太高的sql,经过将处理逻辑前移到blink任务阶段大幅优化drill查询性能(例如上面的sql只要将比对auction_tag字段是否含有‘15’的逻辑交给blink处理,并让blink任务新增产出一个tag字段,这样druid就能够针对tag字段建索引,经过where tag==‘true’这样的语句就能够直接召回须要的记录)
目前tt->blink->hbase和tt->blink->tt->druid是在公司内使用很是普遍的两种实时流处理架构,能以秒级延时完成线上实时日志处理,这两种实时流处理架构比较好地知足了亲听和全链路debug项目的实时数据处理需求,极大提高了项目价值
感兴趣的能够本身来个人Java架构群,能够获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。