基于Blink构建亲听项目以及全链路debug项目实时响应能力

案例与解决方案汇总页:
阿里云实时计算产品案例&解决方案汇总

本文全面总结了大数据项目组在亲听项目以及全链路debug项目上进行的实时流处理需求梳理,架构选型,以及达成效果

一、背景介绍

1.1亲听项目

亲听项目专注于帮助用户收集、展示、监控和处理用户体验问题,是保证产品的主观评价质量的利器,关于其具体功能可参考在ata搜索"亲听"查看系列文章。目前亲听项目的实时流处理需求来自算法效果监控,算法效果监控需要对上游TimeTunnel日志进行解析后经过处理得到一些关键指标,亲听通过对这些指标的前端展示和阈值监控报警达到算法效果监控目的。

需求要点可以总结如下:

  1. 上游需要处理的TimeTunnel日志的实时数据量大约在日常峰值每秒数万条记录,大促峰值每秒几十万条记录
  2. 从用户搜索行为到亲听系统得到搜索行为指标数据秒级的低延时
  3. 数据的处理逻辑较为复杂且会随着算法迭代需要发生变化

1.2全链路debug

全链路debug专注于帮助用户在线上搜索结果出现异常和问题时帮助开发者复现搜索后端各子系统的中间结果,定位并解决子系统存在的问题,是系统层级质量保证和测试的有力工具。关于其具体功能可参考在ata搜索"全链路debug"查看系列文章。全链路debug的实时流处理需求是实时从TimeTunnel日志中提取出帮助排除搜索线上问题的关键内容,全链路debug利用这些内容帮助进行问题排查。全链路debug的实时流处理需求模型可以用下图描述:

需求要点可以总结如下:

  1. 上游需要处理的TimeTunnel日志的实时数据量大约在日常峰值每秒数万条记录,大促峰值每秒几十万条记录
  2. 需要保存的单条记录较大,平均达到几K左右
  3. 对上游TimeTunnel日志解析逻辑大部分为字段提取和透传且不会频繁变化

二、解决方案

2.1整体架构

应对以上需求,亲听以及全拉链路debug的实时流处理系统的最终架构如下:

亲听:

全链路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项目的实时数据处理需求,极大提升了项目价值

四、作者简介

鸷鸟,来自搜索事业部-工程效率&技术质量-算法工程平台-实时大数据平台
15年加入阿里,主要从事电商体系实时数据研发以及实时大数据平台研发



本文作者:付空

阅读原文

本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/536857.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python的重点_python知识点

"""author:lei"""import os#os.path.join() 将分离的部分合成一个整体filenameos.path.join(/home/ubuntu/python_coding,split_func)print filename#输出为:/home/ubuntu/python_coding/split_func#os.path.splitext()将文件名和扩展…

在既有系统中打通Apache Ignite、MySQL和Node.js

为什么80%的码农都做不了架构师?>>> 介绍 在本系列的第一篇文章中,安装了Node.js、Ignite的Node.js瘦客户端包,并且测试了一个示例应用。在本文中,可以看一下Ignite在处理其它数据源(比如关系数据库&#…

java hashmap 的api_JAVA基础--JAVA API集合框架(ArrayList、HashSet、HashMap使用)

一、集合Collection1. 集合介绍变量:表示的内存中的一个空间,只能保存确定类型的单个数据数组:表示的是内存中的多个连续的空间,这些空间中可以存储多个同类型的数据。后期继续学习面向对象技术,我们在程序中开始创建对…

Vue进阶知识笔记

利用v-for循环出的多个li标签&#xff0c;点击不同的li变换颜色 方法一 <ul v-for"(item,index) in list" :key"index" class"details"><li ref"lisd" click"faillist(index)" :class"{active:ind index}&qu…

teamcity mysql 配置_CentOS 7 上 TeamCity 安装

CentOS 7 上 TeamCity 安装非入门教程, 初次接触centos/docker的朋友需要谨慎一. 安装 MySQL为了后续的需要, 这里安装了 Docker, 当然如果你已经有了 MySQL 或者其它推荐的数据库[MySQL, PostgreSQL, Oracle, MS SQL], 则可忽略1. 安装 Docker补充:# 启动dockersudo systemctl…

Python网络请求库Requests,妈妈再也不会担心我的网络请求了(二)

本文同步发表于我的微信公众号&#xff0c;扫一扫文章底部的二维码或在微信搜索 极客导航 即可关注&#xff0c;每个工作日都有文章更新。 一、概况 接着上篇说&#xff0c;如果你真以为Requests网络请求库只有Get请求和Post请求&#xff0c;那就大错特错了。它还一些其他用法&…

dbunit java_java - 错误地抛出了Java DBUnit AmbiguousTableNameException - 堆栈内存溢出

我正在尝试DBUnit(2.6.0)&#xff0c;我正在尝试导出我的完整数据库(PostgreSQL)。 但是抛出以下异常&#xff1a;线程“main”中的异常org.dbunit.database.AmbiguousTableNameException&#xff1a;FLYWAY_SCHEMA_HISTORY这是正确的行为&#xff0c;因为我有两个具有相同名称…

Docker 命令详解(run篇)

参考&#xff1a;https://www.cnblogs.com/yfalcon/p/9044246.html 命令格式&#xff1a;docker run [OPTIONS] IMAGE [COMMAND] [ARG...]Usage: Run a command in a new container中文意思为&#xff1a;通过run命令创建一个新的容器&#xff08;container&#xff09; 常用选…

java 同步 lock_关于java:同步是否像Lock.lock()一样驻留并发线程?

当我们调用lock.lock()或尝试输入synchronized块时&#xff0c;如果其他某个线程已经获得了该锁&#xff0c;则我们的线程将阻塞。 现在我的问题是&#xff0c;当我们查看lock.lock()的实现时&#xff0c;它会将获取锁委托给AQS&#xff0c;而AQS实际将当前线程驻留在该线程中(…

Idea项目中常见错误及笔记(Old)

1、Idea基础设置&#xff1a; File-->settings--> 1>修改字体&#xff1a;Font 2>修改编码格式&#xff1a;File Encodings(全部UTF-8,右下方复选框勾中--防止程序中的汉字转为ASCII码) 3>修改行号&#xff1a;Appearance&#xff1a;show line numbers show me…

java接口服务编排_GOKU API Gateway CE V3.1.0 发布:新增服务编排、配置版本管理等...

Goku API Gateway (中文名&#xff1a;悟空 API 网关)是一个基于 Golang 开发的微服务网关&#xff0c;能够实现高性能 HTTP API 转发、服务编排、多租户管理、API 访问权限控制等目的&#xff0c;拥有强大的自定义插件系统可以自行扩展&#xff0c;并且提供友好的图形化配置界…

maxcompute 2.0复杂数据类型之array

2019独角兽企业重金招聘Python工程师标准>>> 1. 含义 类似于Java中的array。有序、可重复。 2. 场景 什么样的数据&#xff0c;适合使用array类型来存储呢&#xff1f;这里列举了几个我在开发中实际用到的场景。 2.1 标签类的数据 为什么说标签类数据适合使用array类…

java中匿名数组_Swagger UI:数组中的多个匿名对象

对象数组的定义如下&#xff1a;type: arrayitems:type: objectproperties:prop1:type: stringprop2:type: integer# etc.在您的示例中&#xff0c;响应包含具有属性 balanceDisplaySettings 的对象&#xff0c;并且此属性包含对象数组 . 这可以定义如下&#xff1a;paths:/Pat…

java ioutils 写入文件_文件输入输出流工具: IOUtils使用总结

序言以前写文件的复制很麻烦&#xff0c;需要各种输入流&#xff0c;然后读取line&#xff0c;输出到输出流...其实apache.commons.io里面提供了输入流输出流的常用工具方法&#xff0c;非常方便。下面就结合源码&#xff0c;看看IOUTils都有什么用处吧&#xff01;常用的静态变…

权限组件(6):权限分配的角色管理

效果图&#xff1a; 为了方便开发&#xff0c;先把中间件注释掉&#xff0c;要不还要在角色-权限表中添加对应关系。又因为二级菜单和面包屑导航需要中间件的变量&#xff0c;所以要在layout.html里面把这两个也注释掉。setting.py# rbac.middlewares.rbac.RbacMiddleware layo…

java 面试700问_JAVA面试700问(一)

1、Java环境中的字节码是什么&#xff1f;由Java 编译器生成的一种代码。由JVM生成的一种代码。Java源文件(Java Source File)的别名。一种写在类的实例方法中的代码。答案&#xff1a;由Java 编译器生成的一种代码。2、什么是Java垃圾回收机制&#xff1f;操作系统周期性的删除…

02-Django基础知识

一、内容回顾 1、web应用程序 2、HTTP协议 a、http协议特性 b、http请求格式 c、http响应格式 3、wsgiref模块 4、Django下载与简单应用 a、Django简介&#xff08;MTV&#xff09; b、下载django命令 c、创建项目命令 d、创建app应用 e、启动项目   二、今日概要 1、路由层&…

java条码大小_java - ML Kit条形码扫描:无效的图像数据大小

我想在捕获的图像中检测条形码。我使用android的camera2捕获图像。此后&#xff0c;将检索图像的元数据并将图像保存到设备。元数据全部传递到下一个活动&#xff0c;该活动是应用程序尝试检测条形码的地方。下一个活动是从先前保存的文件创建一个byte []。接下来&#xff0c;使…

MongoDB数据库泄露8亿电邮地址;微软开源Windows计算器;Linux 5.0 Kernel发布丨Q新闻...

本周要闻&#xff1a;华为正式宣布起诉美国政府&#xff1b;360 首席安全官谭晓生宣布离职&#xff1b;阿里开源 Flutter 应用框架 Fish Redux&#xff1b;微软开源 Windows 计算器&#xff1b;Linux 5.0 Kernel 发布&#xff1b;电邮验证服务泄漏 8 亿电邮地址&#xff1b;Chr…

mysql 视图 分页_mysql查看所有存储过程,函数,视图,触发器,表,分页

查询数据库中的存储过程和函数方法一&#xff1a;select name from mysql.proc where db your_db_name and type PROCEDURE //存储过程select name from mysql.proc where db your_db_name and type FUNCTION //函数方法二&#xff1a;show procedure status; //存储过程sh…