大数据时代,数据的重要性不言而喻,尤为对于互联网公司,随着业务的快速变化,商业模式的不断创新、用户体验个性化、实时化需求日益突出,海量数据实时处理在商业方面的需求愈来愈大。如何经过数据快速分析出用户的行为,以便作出准确的决策,愈来愈体现一个公司的价值。现阶段对于实时数据的建设比较单一,主要存在如下问题:数据库
实时流数据来源系统较多,处理很是复杂,而且不一样业务场景对实时数据的要求不一样,所以在建设过程主要有如下挑战:缓存
咱们在充分梳理业务需求的基础上,从新对实时流进行了建设,将实时数据分层建模,并对外提供统一的接口,保证数据同源同口径;同时,在数据服务层,增长可配置信息模块解决了配置信息不能自动化的问题,在数据处理策略上作了多线程处理、预计算、数据降级等优化,在数据安全方面增长数据审计功能,更好地提高了产品的用户体验。安全
产品总体建设方案基于美团技术平台,总共分为源数据层、存储层、服务层及WEB层,总体架构以下所示:服务器
图1 总体架构图数据结构
源数据层:主要提供三部分数据,实时数据、离线数据、配置信息、维度信息。
存储层:源数据清洗后放入相应的存储引擎中,为服务层提供数据服务。
服务层:提供三部分功能,数据API服务、预计算服务、权限服务、数据审计服务。
Web层:使用Echarts可视化数据。多线程
依托于美团提供的公共资源平台,数据架构按功能分为数据采集、数据处理、数据存储、数据服务四层,以下所示:架构
图2 数据架构图并发
数据来源主要有两种:业务上报的Log日志及数据库Binlog日志。这些日志经过美团日志中心进行采集后存储在消息中间件Kafka中,并按照不一样的分类存储在不一样的Topic中,供下游订阅。框架
数据处理顾名思义,就是对采集的实时流进行逻辑处理,按业务需求输出对应的实时数据,所以这一步骤是流式计算的关键,分两步进行:数据加工、数据推送。工具
数据加工:数据加工一般须要在流式计算系统中进行,目前流行的流式处理系统主要有Storm、Spark Streaming系统及Flink系统,这些系统都能在不一样的应用场景下发挥很好处理能力,并各有优缺点,以下图所示:
计算框架 | 吞吐量 | 延迟 | 传输保障 | 处理模式 | 成熟度 |
---|---|---|---|---|---|
Storm | 低 | 毫秒级 | At least once | 单条处理 | 成熟 |
Spark Streaming | 高 | 秒级 | Exactly once | 微批处理 | 成熟 |
Flink | 高 | 毫秒级 | Exactly once | 单条处理/微批处理 | 新兴 |
最终咱们选择Storm做为实时数据处理框架,并借助公司提供的通用组件来简化拓扑开发流程和重复代码编码。例如,组件MTSimpleLogBolt的主要功能是将Kafka中读取的数据(Log or Binlog)解析成Java实体对象;组件StormConfHelper的功能是获取Storm做业应用配置信息。
数据推送:将处理好的数据推送到存储引擎中。
数据加工完成后会被存储到实时存储引擎中,以提供给下游使用。目前经常使用的存储引擎主要有MySQL、Druid、Elasticsearch、Redis、Tair比较以下:
存储引擎 | 优势 | 缺点 |
---|---|---|
MySQL | 使用简单,支持数据量小 | 数据量大,对MySQL的压力大,查询性能慢 |
Druid | 数据预计算 | 不支持精确查询 |
Elasticsearch | 查询效率快,支持经常使用聚合操做;能够作到精确去重 | 查询条件受限 |
Redis | 内存存储KV,查询效率高 | 写入资源有限,不支持大数据量写入 |
Tair | 持久化和非持久化两种缓存,查询效率高 | 单节点性能比Redis较弱 |
Kylin | 多维查询预计算 | 不支持实时 |
综上比较,因为实时数据量较大,且数据精度要求较高,所以咱们最终选择交易存储使用ES,流量存储使用Druid,维度存储使用Tair,中间数据存储使用Redis;而离线数据,咱们采用Hive和Kylin存储。
将存储引擎数据统一对外提供查询服务,支持不一样业务应用场景。
整个数据层架构上主要分为实时数据和离线数据两部分:实时数据分为交易的Binlog日志和流量的Log日志,通过Strom框架处理后写入Kafka,再通过DataLinkStreaming分别写入ES和Druid;离线数据经过Hive处理写入Kylin。
图3 产品数据架构
下图所示为一条消息的处理流程:
图4 数据关系
两个Topic分别是order_base(主要存放订单基本信息:订单id、订单状态、支付时间、票量、金额等);order_biz(主要存放订单的扩展信息:订单id、订单类型、出发时间、到达时间、出发城市、到达城市)。咱们最终要拿到一条包括上述所有内容的一条记录。
图5 数据处理流程
具体例子:Bolt在处理一条记录时,首先判断这条记录是base仍是biz,若是是base则写入缓存中base的Category中,若是是biz则写入biz的Category中。以order_id为Key,若是是base则去和biz关联,若是biz存在则表明可以关联上,这时发送关联后的完整数据,同时删除该主键(order_key)记录;若是biz中不存在,则说明没关联上,这时可能biz的数据延迟或者是丢失,为了保证主数据的准确性,这时咱们只发送base的数据,缓存中的数据保留不被删除。若是这条消息是biz,则首先会更新缓存中该主键的biz记录,而后去和base关联,关联上则发送同时删除base中数据,不然不发送。此时咱们会根据ES的Update特性去更新以前的数据。从现实效果来看保证了99.2%的数据完整性,符合预期。
在Topic2es的数据推送中,经过DataLinkString工具(底层Spark Streaming)实现了Kafka2es的微批次同步,一方面经过多并发batch写入ES得到了良好的吞吐,另外一方面提供了5秒的实时写入效率,保证了ES查询的实时可见。同时咱们也维护了Kafka的Offset,能够提供At lease once的同步服务,并结合ES的主键,能够作到Exactly once,有效解决了数据重复问题。
在数据写入ES过程当中,因为数据量大,索引时间区间长,在建设索引时须要考虑合理设计保证查询效率,所以主要有如下三点优化:
整个实时数据开发遵循大交通实时数仓的分层设计,在此也作一下简单介绍,实时数仓架构以下:
图6 实时数仓架构
ODS层:包含美团页面流量日志、模块事件日志以及用户操做的Binlog信息日志,是直接从业务系统采集过来的原始数据。
事实明细层:根据主题和业务过程,生成订单事实和流量事实。
汇总层:对明细层的数据扩展业务经常使用的维度信息,造成主题宽表。
App层:针对不一样应用在汇总层基础上加工扩展的聚合数据,如火车票在抢票业务下的交易数据汇总信息。
规范建模后,业务需求来临时,只须要在App层建模便可,底层数据统一维护。
后台服务主要实现 登录验证和权限验证(UPM)、指标逻辑计算和API、预计算服务、数据质量监控、数据审计功能。因为数据量大且实时性要求较高,在实现过程遇到以下挑战:
针对以上问题,下面进行一一详述:
服务层处理数据过程当中,因为数据量大,在查询时须要必定的响应时间,因此在保证响应性能方面,主要作了如下优化:
图7 性能响应优化
使用缓存避免不了出现一些问题,好比缓存失效、缓存雪崩等问题,针对缓存雪崩问题,经过设置不一样Key的过时时间可以很好的解决;而对于缓存数据失效,咱们有本身的数据降级方案,具体方案以下:
图8 数据降级方案
预计算数据会分别在Redis、Tair和本地缓存中存储一份以保证查询效率,当查询Redis数据不存在时,会去Tair中读取数据,Tair也为空时,会读取本地缓存,只有当本地缓存数据也为空时,才会现查ES作聚合计算,这样也会下降ES的查询压力。
实时监控预警很是重要,在数据出现问题时,一方面可以及时通知咱们快速定位修复数据,另外一方面也可以及时周知业务同窗,避免作出错误分析。基于此,咱们作了两方面的实时监控,其一是对源实时流在Storm处理层面的监控,确保源实时流正确生产;其二是对展现的汇总数据进行监控,确保产品展现指标数据正常。
针对数据出现问题预警,咱们在解决方案上规范了流程:
在以数据取胜的时代,数据的安全不言而喻,咱们采用公司提供的UPM权限接口进行二级权限管理并加入审计功能及水印功能,可以准确记录用户的全部访问以及操做记录,而且将日志数据格式化到数据库中,进行实时监控分析。
实时数据能够为业务特定场景分析决策提供巨大支持,尤为对于大交通节假日及春运期间。在大交通实时战场沙盘产品化过程当中,咱们投入了大量的思考和实践,主要取得如下收益: