海量数据下查询慢、数据不一致难题如何解?看某游戏公司的技术实践
导语: 复杂架构的危害是隐性且持续增长的,尤其在海量数据处理的业务场景下,导致系统吞吐量增长、各功能模块相互影响,且数据重复、维护困难。某游戏公司就面临这样的困境,在寻求解决方案的过程中,携手 OceanBase 搭建了存储与实时分析的一体化数仓架构,替换了 ClickHouse,Hive。该公司大数据平台负责人从实时数仓面临的问题与挑战谈起,讲述了他们从确定选型方向到最终实现选型落地的历程,以及使用 OceanBase 的经验,供大家参考。
业务背景:数仓架构复杂,重视数据分析、处理与运营
我们公司是一个游戏公司,以前重研发,现在重运营。对于游戏公司来说,数据分析是非常重要的一块业务,因此,我们非常看重数据分析系统的能力。目前,我们主要使用数仓工具对用户行为(下载、注册、充值)和广告营销数据进行分析,还有其他游戏数据的分析,比如用户打怪升级的现状、战斗的参数等,也会用到数仓。
和大多数公司一样,我们的数仓是典型的 Lambda 架构,如图 1 所示。我们通过数据源获取到数据后先进行预处理如数据质量控制、数据清洗等处理后,将数据放入 Kafka 进行数据缓存。后续的任务调度分成两部分,一部分是通过 Hive 做离线处理,另一部分数据用 ClickHouse 进行实时分析。处理后的数据供应用系统使用,比如 BI 系统、用户系统、营销系统、以及第三方系统如百度、腾讯、头条、抖音等。
图 1 数仓架构
当前的数仓在获取数据后会进行解析和数据质量的处理。当收集到质量不符合规定的(缺字段、字段的类型不对)数据都会进行告警和处理。游戏行业数据处理比较特别的一点是会对数据进行归因,简单来说就是把数据收集流程进行详细解析,以此来判断该数据是通过哪个渠道哪个广告位产生的,后续的广告营销策略也会依赖于数据归因。另外,我们还有一套“数据打宽”流程,这是数据仓库中最为常见的业务加工场景,可以将用户的 IP 解析后显示用户的国家、省市、地区、信息,可以解析用户的手机型号,可以解析用户的年龄和性别等,放入离线数仓和实时数仓中,为用户画像提供支撑。
业务挑战:实时性、一致性、可维护性差,查询慢
我们的数仓架构包括数据贴源层,数据详细层、数据中间层、数据服务层、数据集市等,原始数据通过数据质量检查后,分别写入 Hive 和 ClickHouse 中的 ODS 贴源层,严格来说 kafka 中有什么数据,ODS 层也有什么数据,Kafka 也属于贴源层的范畴,数据通过任务调度系统,进行打宽如解析 ip、解析年龄和加工后,存入数据详细层 DWD,数据在数据中间层 DWM 和数据服务层 DWS 经过一系列指标汇聚处理后,放入数据集市,我们是用 PostgreSQL 数据库和 Redis 中来做的数据集市,其中任务调度系统是我们自研的,可以进行源数字典的管理和数据质量管理及任务调度,可以执行任务重跑、任务优先级调整、数据质量告警等操作,是一个比较强大的调度系统。虽说这个架构是当前较为先进的架构,但在使用过程中也遇到了不少挑战。
挑战 1:实时性。 很多公司的数仓策略都是 T+1,此前我们在使用 Hive 数仓时对其进行了优化,达到了数据从产生到可见只需要 30 分钟。就是说我们 30 分钟就去 load 一遍数据,写入 Hive 再 insert overwrite 到当天的分区里面(可减少数据的碎片)。在实时数仓上 ClickHouse 也达到了一分钟可见。但有些场景需要在毫秒内看到结果,是 Hive 和 ClickHouse 无法达到的。
挑战 2:一致性。 相信用过 Lambda 架构的人都知道 ClickHouse 和 Hive 的数据经常“打架”,二者计算出来的数据不一致。我们允许数据重复,在计算上也做了重复数据的去重处理,但即使重复处理完,仍然有数据不一致的问题,导致 ClickHouse 的数据只能用于实时数据的查看,Hive 数据则会用于最终数据使用。
挑战 3:可维护性。 ClickHouse 实时数仓一套代码,Hive 离线数仓一套代码,一个架构两套系统,维护起来比较困难。
挑战 4:即席查询。 Hive 离线数仓,需要几分钟甚至十几分钟才能看到查询结果。ClickHouse 实时数仓在几秒钟至几分钟就能展示查询结果。即席查询在大多数情况下一切正常,但在以下两种极端情况下会遇到挑战。
一种情况是用户身份信息邦联查询,当用户在注册过程中绑定了身份证,需要通过身份证回查用户账号时,是需要毫秒级的响应。而我们的用户信息是存在 MySQL 中,在数据量较小时,查询达到毫秒级响应是没问题的,但在数量上亿或者数十亿的查询场景下,MySQL 的响应就非常慢甚至不可用。
另一种情况是广告渠道邦联查分析,需通过订单数据邦联用户数据再邦联广告商渠道信息,以往查看广告投放效果需等待要半小时。而我们的需求是 1 秒内可见。
目前 Lambda 架构下的数仓不支持上述需求,这迫使我们探索新的数仓工具。
技术选型:OceanBase 查询测试,性能提升 286 倍
我们调研了 Hudi、Doris 两款数仓工具,Hudi 从数据写入到 Join 查询,至少需要 60 秒;Doris 能实现 10 秒到 60 秒可见,而我们已经在用的 ClickHouse 查询结果的可见时间为 66 秒(见图 2),相比之下,如果选用 Hudi 或 Doris 与使用现有的 ClickHouse 并没有明显的数值提升,没有从根本上解决业务的需求。
图 2 ClickHouse 查询数据 66 秒可见
在进行新工具调研的过程中,我们了解到 HTAP 数据库 OceanBase,并使用 OceanBase 在用户身份证号查找用户 ID 的场景下简单测试了数据查询速度。通过图 3 可以看到,我们在对 OceanBase 未做分区优化只做索引优化的情况下,1.2 亿 Join 查询 34 亿条数据,初次查询用时 0.23 秒,数据预热后 0.01 秒出数据查询结果,性能提升 66/0.23=286 倍。我们认为,这是一个很“吓人”的性能提升。
图 3 OceanBase 查询数据结果毫秒可见
因此,我们当即决定封装 OceanBase 的能力去满足业务需求,包括通过身份证号查找用户 ID、通过用户 ID 查询广告信息、实时红包推广效果等。
生产部署:实时数据写入优化,历史数据导入踩坑
在确定使用 OceanBase 后,下一步的计划就是考虑如何把它用起来。首先,我们对历史数据和实时数据进行区分。
历史数据:我们用 DataX 将历史数据导出为 CSV 文件后,再用 DataX 将 CSV 文件导入 OceanBase。
实时数据:考虑到用户需求是毫秒级响应,我们选用了 Flink SQL 抽取实时数据。经过测试,从数据产生到数据落到 OceanBase,1 秒内完成。
对于历史数据的导入,由于前期对 OceanBase 不够熟悉,在使用过程中,我们也走了一些弯路,很多问题通过在 OceanBase 技术答疑群(钉钉群号:33254054)与技术专家交流得到了解决。在数据导入过程中,通过 DataX 导出 CSV 文件时,配置文件中最好用 2881 端口直连 OceanBase 数据库,如果通过 2883 端口,也就是 OBProxy 代理连接的话,由于 OBProxy 的分发机制,可能将不同的命令分发到另外一台机器上,如果另外一台机器没有部署 DataX 并导出文件的话则会找不到文件,所以我建议使用 Datax 的时候,连接 2881 是最保险的。
对于实时数据的写入,值得一提的是,在写 OceanBase 时,我们也考虑过 Spark。Spark 是通过微批的方式去写,在微批写时,实时性还是比 Flink 差了一些。最大的微批时间间隔为 300 毫秒的延迟。而 Flink 则可以实时写入 OceanBase,因此,我们选择通过 Flink SQL 的方式把数据写到 OceanBase 中。
下面三张图片是 Flink 数据实时 ETL 的加载转化以及写入 OceanBase 的流程代码展示。其中,图 4 是使用 Flink-kafka 抽取实时数据的过程;图 5 为使用 FlinkSQL 转换、加工整理实时数据的过程;图 6 为使用 FlinkSQL 实时加载至目的地 OceanBase 的过程。
图 4 使用 Flink-kafka 抽取实时数据
图 5 使用 FlinkSQL 转换、加工整理实时数据
图 6 使用 FlinkSQL 实时加载至 OceanBase
我也对这些代码进行部分抽取,将其做成脚本成批量提交,在转化成脚本工具化后 Flink Source 数据源可以支持从 Kafka、MySQL、Oracle、OceanBase、MongoDB、PostgreSQL、Sqlserver 等数据源实时同步数据并加工后写入 OceanBase 中,数据形成了闭环,OceanBase 作为数据中台核心/实时数仓的雏形初步完成。
以上代码我们已经部署到生产环境中,目前应用到两个应用场景中:一是通过用户身份证号查找用户 ID,二是通过用户 ID 查找数据归因等信息,比如用户通过哪个广告渠道了解并注册到我们的产品。目前,OceanBase 在业务系统中的位置如图 7 所示。
图 7 使用 OceanBase 后的数仓架构
总结与展望:一个系统支撑 TP 与 AP 场景,解决所有问题
随着 OceanBase 在我们业务系统中的稳定落地,帮助我们解决了上文提到的四个固有问题。
实时性: 从 Kafka 到 Flink 再到 OceanBase,写入与导出的实时性没有任何问题。例如,使用 Flink SQL 抽取实时数据并写入 OceanBase,能实时完成。对于 flink-sql-connector-OceanBase-cdc 工具,我希望它更好的支持历史数据再加工高效效率,以及不重不漏高效的历史数据、实时数据无缝对,我们期待 OceanBase 的 CDC 工具能够迭代出更完美的版本。我们更期待社区开发出 OceanBase 专有的 flink-connector,实现不重不漏高效的写 OceanBase。做好 flink-sql-connector-OceanBase-cdc 读工具和 flink-connector 写工具,就可以不重不漏高效的进行数仓第二层,第三层的加工,将 OceanBase 的生态扩展到了大数据圈,顺带实现了大数据环境下的存算分离。
一致性: OceanBase 可以完美对接我们现有系统中的历史数据和实时数据,实现数据不重、不漏、不丢。
即席查询: 我们在对 OceanBase 未做分区优化只做索引优化的情况下,1.2 亿 Join 查询 34 亿条数据,初次查询用时 0.23 秒,数据预热后 0.01 秒出数据查询结果,性能提升 66/0.23=286 倍。数据可以达到毫秒内可见。
可维护性: 以往我们需要维护 ClickHouse 和 Hive 这两套代码,未来我们计划将所有核心场景逐渐迁移至 OceanBase,简化架构,只需维护一套代码即可实现 TP 和 AP 的双重能力。
下一步,我们计划在用户系统、广告系统、数据分析系统,以及营销和渠道管理分析中推广和使用 OceanBase(见图 8),目前已经开始了代码开发与数据对接。我们的理想状态是将所有的业务数据放到 OceanBase 中进行分析、保存,实现数据闭环,一个系统解决所有问题。
图 8 将 OceanBase 应用至更多系统
此次 OceanBase 落地实践带给我们很多惊喜,正所谓千里之行始于足下,我们要敢于尝试,才能逐渐到达千里之外,感受更美丽的风景。最后,希望 OceanBase 能够越做越好。
评论