千亿级日志系统架构演进

news2024/12/25 16:46:02

在度假线路类商品系统中,由于商品结构复杂,涉及底层数据表上千张,在日常供应商以及业务维护过程中,每日产生6亿+的数据变动记录。这些数据的变动留痕,不但可供录入方查看,也对日常产研的排障起着至关重要的作用,同时也可以提供给BI做数据进一步分析。商品日志系统建设尤为重要,随着商品日志系统不断发展迭代,已经积累达到1700亿条日志。

本文将介绍线路商品日志系统的演进过程以及在其中遇到的问题。

  • 一、发展轨迹

  • 二、演进过程

  • 2.1 V1.0 DB单表存储

  • 2.2 V2.0 平台化

  • 2.3 V3.0赋能

  • 三、结语

一、发展轨迹

线路商品日志系统的发展大致可以分为以下三个阶段:

2019年以前:单表日志

在 2019 年以前,商品系统尚无统一的日志系统来记录商品的变更,在系统中使用DB日志表,该表以非结构化的方式记录商品基本信息的变动。

2020年~2022年:平台化

在系统改造过程中,建立统一的商品系统日志平台,通过配置的方式记录商品的数据变动日志,覆盖商品维护的全部流程。

2023~2024:开放

经过在线路商品系统的实践,商品系统日志平台经历百亿级数据的考验,并以灵活的配置方式记录数据变动日志,同时支持自定义索引字段,具有接入和使用成本较低的优势。为此,通过对商品系统日志进行改造,逐步向门票、用车等业务线开放使用。

二、演进过程

2.1 V1.0 DB单表存储

图片

在2019年以前,记录线路商品的变动日志较为简单,在DB中建立一张日志表(id,LogContent)来记录日志,数据变动以非结构化的文本记录在LogContent字段内,且仅覆盖商品最基本的信息,在使用时通过数据库查询工具执行sql语句like关键字进行查询,这种方式带来的问题也显而易见:

  • 数据量大,性能低

由于是单表文本字段存储,导致表的数量非常巨大,达到单表10亿+(370GB)的数据,查询超时问题严重,不得不进行定期归档。

  • 可读性差,仅开发人员使用

由于日志内容以文本字段存储,在进行日志查询时,一般由开发人员使用 like 语句直接查询 DB,例如:select id, LogContent from log where LogContent like '%1234%'。查询速度缓慢,严重影响日常排障流程。

  • 扩展性差

由于日志写入与业务代码强耦合,且采用非结构化存储。对于新增日志,需要对业务代码进行改动,在接入时存在一定的成本,且接入后无法直接提供给供应商或业务人员直接使用,最终仍需要开发人员进行查询转换。

2.2 V2.0 平台化

2.2.1 技术选型

针对 V1.0 遇到的问题,重点在于海量日志数据的存储与查询,业内解决海量日志数据存储与查询的方案一般有以下几个:

ES+Hbase

HBase 提供高并发的随机写和支持实时查询,是构建在 HDFS 基础上的 NoSql 数据库,适用于海量日志数据的存储,可支持到 PB 级别的数据存储。但其查询能力有所欠缺,支持 RowKey 快速查询,若有复杂查询则需要自建索引。ES 提供强大的搜索能力,支持各种复杂的查询条件,适合快速检索及灵活查询的场景。ES + HBase 的组合,利用各个组件的优势,结合起来解决海量日志数据存储及查询的问题,但架构较为复杂,需要保证两个组件间数据的一致性。

MongoDB

支持多种查询,具有文档型及嵌套的数据结构,但其支持的数据量级一般在 10 亿级别,对比 HBase 要欠缺得多。如果想要处理 TB 级以上的数据量,需要进行适当的架构设计和优化,例如利用分片集群来水平扩展数据等,付出的成本会比较高。

ClickHouse

Clickhouse 是一个开源的列式数据库,采用列存储的数据组织方式,具有高性能、可伸缩性、容错性和低延迟查询等特点。查询性能出色,可实现秒级甚至毫秒级的查询性能,对于数据压缩和存储效率高,可节省成本。适用于海量数据的存储及查询场景。

通过对以上方案进行对比,我们的数据量级已经超过 MongoDB 一般的处理能力,因此该方案被淘汰。对比 ES + HBase 与 ClickHouse,这两个方案都比较适合海量日志的存储与查询,但是受限于内部成本控制,CK 集群的日志保存时长被控制在一定天数内,无法满足我们业务场景的需求。最终,我们选择 ES + HBase 的方案。

2.2.2 整体架构

图片

基本原理即利用 HBase 解决存储问题,利用 ES 解决搜索问题,并将 ES 的 DocID 与 HBase 的 RowKey 关联起来。通过发挥各个组件的优势,相互结合解决海量日志的存储与查询问题。如上图所示,在接入日志 API 后,所有日志均经过 MQ 进行异步处理,如此既能够将日志写入与业务代码的逻辑解耦,又能确保写入速度的平稳,避免高峰流量对整个 ES + HBase 集群的写入造成压力。

2.2.3 RowKey设计

RowKey设计原则:

唯一性:RowKey应保证每行数据的唯一性;

散列性:数据均匀分布,避免热点数据产生;

顺序性:可以提高查询性能;

简洁性:减少存储空间及提高查询性能;

可读性:以便人工查询及理解;

对于线路商品日志,对于直接可读性要求不高,查询的场景我们是从ES中先查出RowKey,再用RowKey去hbase查询日志原文,整个过程RowKey是人工不可见的,结合我们实际的场景,线路商品数据日志的RowKey由五部分构成{0}-{1}-{2}-{3}-{4}

{0}:传入的pk 转换为md5[pk]值16进制字符串,取前8为

{1}:tableId补0至8位

{2}:pk+4位随机值补0至24位

{3}:log类型补0至16位

{4}:时间戳

图片

2.2.4 扩展

对于线路商品信息的维护分散于不同的模块中,例如录入模块、直连模块等。鉴于此,我们抽象出统一的数据写入服务,并提供统一的日志接入 API,API内部异步写入日志。在底层的数据写入服务中,将所有的写入操作接入日志 API。通过这个方式,将扩展性统一到日志配置中心。

写入流程

图片

日志的写入流程如上图所示,客户端调用日志 API 以进行数据变动日志的写入操作。日志服务在接收到请求后,将其抛入 MQ,由后续的消费组进行消费处理。消费组件在接收到消息后,会进行相应的消费处理,并根据上述的RowKey生成策略为该条日志生成 RowKey,随后将日志文本内容写入 HBase,在写入成功之后,再将索引数据写入到 ES。其中,若 HBase 或 ES 中的任何一个写入失败,都会将此条日志写入补偿 redis 集群,再由补偿逻辑进行后续补偿,以确保整个日志的写入成功。

查询流程

图片

日志的查询流程如上图所示:客户端调用查询 API 并传入查询参数,日志服务接收到请求参数后,将其转换为 ES 分页查询请求,从 ES 集群中查出 RowKey,再汇总 RowKey 并从 HBase 中批量查出日志全文内容。

此外,我们利用上述查询 API,建立一个日志查询页面,供研发人员使用。在该页面,相关开发人员可以便捷地进行数据变动日志的查询。上述日志平台的建立,相对完美地解决线路商品海量数据变动日志的存储及查询问题。同时,抽象日志的配置中心,解决一定的扩展性问题。

整个系统的优点在于:基于表级别日志的商品日志记录,覆盖全面,配置灵活,索引结构化存储,支持海量日志数据的存储及查询。

缺点是:对于使用方而言存在一定的局限性,过于“技术化”,开发人员使用较为方便,但供应商与业务人员使用困难。

2.3 V3.0赋能

2.3.1 业务赋能

存储能力

随着日志写入量的增加,日志查询效率逐渐下降,对 ES 和 HBase 的拆分势在必行。如下图所示,我们对 ES 和 HBase 进行横向的拆分与扩容,并在日志配置中心制定匹配规则,根据接入日志类型的不同,将其匹配到不同的集群进行写入。此外,对于接入方,我们也支持独立集群申请,使用方可以根据自身情况决定是使用独立的集群部署,还是使用公用集群。

图片

搜索能力

搜索能力的提升主要由以下两个部分:

索引字段扩展:支持的索引字段更多。前期我们绝大部分场景的日志的索引条件是产品id或者资源ID,随着接入的日志变多,索引字段也变的丰富起来。对于日志搜索场景我们进行梳理,预留10个可支持不同查询的索引字段(其中四个数值型、4个字符型,2个日期型)供使用方使用,覆盖绝大多数的查询场景。

图片

ES索引分区:随着接入的日志增多,单个索引文件也愈发庞大,直接影响日志的查询性能。一般而言,对于日志类型数据,常见的方案是依据时间建立索引,该方案的优势如下:

1)提升查询性能。若日志携带时间范围进行查询,则可仅搜索特定时间段的索引,避免全量索引的查询开销。

2)便于数据管理。可以按照时间删除旧的索引,从而节省存储空间。

通过对日志进行分类,主要包括商品信息、开关班、价格库存等模块。随后结合业务使用场景、每天产生的增量数据以及服务器资源进行评估,最终决定按周建立索引,且索引数据保留一年。

1)利用定时任务在每周一时创建下一周的索引;

2)利用定时任务每周删除已过期的索引;

图片

基于以上存储能力与搜索能力的扩展提升之后,我们在日志配置中心定制了【业务线<-->日志集群】的路由规则,来决定接入的其它业务线日志最终存储的日志集群,提供了更加灵活与具有弹性的业务线接入能力。

图片

2.3.2 供应商赋能

展示能力

图片

在 V2.0 版本中,日志页面仅限于研发人员使用,底层数据过于技术化,业务与供应商难以理解。通常情况下,如果能将日志的查询前置到供应商及业务环节,将极大地减少研发人员平时工作中的排障时间。

为此,我们提供 B 端的日志查询页面,给供应商及业务人员平时排查问题使用。我们对日志内容进行格式化的转换处理,将其转换为供应商和业务人员能够理解的信息,包括行转列、新旧对比、KV 转换、关联数据查询等。日志内容不再是抽象的文本,而是展示为与平时使用的商品系统相对应的内容。这对业务和供应商更加友好。

扩展能力

基于上一步展示能力的提升,对于新接入的日志如何能快速为业务及供应商提供 B 端的页面进行查看,这一步将大幅节省开发排查时间。对底层日志数据需要转换为业务及供应商能看懂的信息的场景进行分析,并总结 7 种数据展示的方式,分别如下:

1)文本字段类:此种展示内容最为简易,无需进行转换,用户可直接理解日志记录的内容,前端展示的即为此内容。

图片

2)数据关联类:此类日志内容中记录的是一个 id,但实际内容存在于另一个关联表的数据中,例如 id:1 表示的是跟团游,不能将 id:1 的日志展示给用户,而需转换为“跟团游”,这就需要进行一步关联 db 表的查询转换。

图片

3)枚举类:此类日志内容记录的是一个 key 值,实际用户能理解的是该 key 值所代表的含义,例如产品钻级:0,就需要转换为:“不分级”,这就需要关联枚举值的配置文件进行查询转换。

图片

4)位存储类:此类日志内容记录的是一种计算后的结果数值。例如支付方式是通过按位与计算然后累加的结果。这种情况就需要按照一定的计算方式将其还原回去。

图片

5)字段组合:此类日志记录的是分散的数据,但实际需要将数据结合在一起查看才会更具业务意义,例如资源适用人档,日志中分为最大、最小记录。实际展示时需要结合到一起展示范围。

图片

6)外部接口:此类日志记录的是一种依赖外部接口的值,例如日志记录的是城市 id:2,代表的是上海,这就需要调用外部接口将 2 转换为上海。

图片

7)差异对比类:此类日志需对结果进行解析以作对比,从而使用户能够更为直观地理解。通常存在两种情形:其一,日志内容所记录的即为两份对比数据,此种情况仅需依循规则予以解析即可;其二,若日志数据属于当次的快照数据,则需与前一次快照数据进行对比,以找出差异。最终达成如下图所示的展示效果。

图片

针对以上这些日志解析的场景,我们最终构建一个日志转换配置。对于新加入的日志,在绝大多数场景下,我们只需修改底层的数据提取及转换配置,便可较为快速的配置出日志查询页面,提供给供应商使用。

三、结语

本文详细介绍度假商品日志平台的演进历程,以及在各个阶段遇到的问题及解决方案。在整个演进过程中,针对海量日志数据存储与搜索的技术挑战,我们采取一系列措施,实现千亿级数据查询在 500ms 内的响应。

同时将日志系统开放,将问题查询解决前置到供应商及业务人员,极大降低一些数据变动查询需求的复杂度,减轻研发及TS同事重复性的工作。此外,我们还对日志平台进行横向的扩容配置,以支持更多的业务线可以接入。截至目前,多个业务线总数据存储量达到千亿级别。

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

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

相关文章

使用 SSM 框架编写的解决方案

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

如何微调(Fine-tuning)大语言模型?

&#xfeff; 导读 本文介绍了微调的基本概念&#xff0c;以及如何对语言模型进行微调。 从 GPT3 到 ChatGPT、从GPT4 到 GitHub copilot的过程&#xff0c;微调在其中扮演了重要角色。什么是微调&#xff08;fine-tuning&#xff09;&#xff1f;微调能解决什么问题&#xf…

Java | Leetcode Java题解之第401题二进制手表

题目&#xff1a; 题解&#xff1a; class Solution {public List<String> readBinaryWatch(int turnedOn) {List<String> ans new ArrayList<String>();for (int i 0; i < 1024; i) {int h i >> 6, m i & 63; // 用位运算取出高 4 位和低…

unity3d入门教程四

unity3d入门教程四 10.1坐标与旋转10.2物体的运动10.3&#xff08;练习&#xff09;掉头飞行11.1向量11.2向量间运算11.3向量夹角11.4物体的指向11.5&#xff08;练习&#xff09;飞向目标12.1屏幕坐标12.2屏幕的边界 10.1坐标与旋转 比如&#xff0c;节点的坐标用 Vector3 类型…

Python 常用模块(二):json模块

目录 1. json 模块介绍1.1 json 模块快用导航1.2 什么是JSON1.2.1 JSON的特点1.2.2 JSON的基本语法1.2.3 JSON数据类型1.2.4 JSON示例1.2.5 JSON使用场景1.2.6 JSON的优缺点1.2.7 JSON和XML的比较 1.3 json 模块 2. dump() 方法 --- 转换为 JSON 格式写入文件2.1 语法参考2.2 实…

电巢科技2024中国光博会圆满收官

2024年9月11日-13日&#xff0c;备受瞩目的第二十五届中国国际光电博览会(CIOE中国光博会)在中国深圳国际会展中心圆满闭幕。 电巢科技以其前沿的Ecosmos元宇宙产品体验区&#xff0c;及联袂中国光博会打造的三大特色栏目——《逛展最前线》《光引未来大咖说》以及《智能消费电…

【Linux】查看操作系统开机时初始化的驱动模块列表的一个方法

这个方法是摸索出来的&#xff0c;也不一定对&#xff1a; 1、驱动层module_init(module_init_function)作为模块初始化&#xff0c;并且提供模块内部初始化的函数名&#xff1b; 2、找到所有驱动目录drivers下所有module_init(module_init_function)&#xff0c;在内核6.9.0…

探索 Python 代码重构的魔法:rope 库的神秘力量

文章目录 探索 Python 代码重构的魔法&#xff1a;rope 库的神秘力量背景&#xff1a;为何选择 rope&#xff1f;什么是 rope&#xff1f;如何安装 rope&#xff1f;简单的库函数使用方法场景应用常见问题与解决方案总结 探索 Python 代码重构的魔法&#xff1a;rope 库的神秘力…

影视直冲?对接卡券特权充值接口对于用户来说有什么优势?

对用户来说有哪些优势&#xff1a; 便利性&#xff1a;用户可以直接在应用程序或网站上充值和使用卡券&#xff0c;无需通过多个平台或渠道&#xff0c;提高了用户体验。实时性&#xff1a;卡券充值和使用状态可以实时更新&#xff0c;用户可以立即看到余额变化和卡券状态。安…

建造者模式:灵活构建复杂对象的利器

在软件开发中&#xff0c;创建一个复杂对象通常需要多个步骤和参数&#xff0c;直接在客户端代码中进行这些操作不仅繁琐&#xff0c;而且难以维护。建造者模式&#xff08;Builder Pattern&#xff09;提供了一种优雅的解决方案&#xff0c;使得对象的创建过程更加清晰、灵活和…

以最小成本实现最大销售:《稻盛和夫的实学:经营与会计》中的企业经营哲学

在《经营与会计》中稻盛和夫提出&#xff0c;会计是现代企业经营的中枢&#xff0c;经营者必须掌握企业活动的真实状态&#xff0c;才能带领企业长期持续的发展。 经营企业要以现金为基础&#xff0c;把握赚的钱在哪里&#xff0c;以什么形式存在&#xff0c;根据手上确凿无疑…

技术分享-商城篇-营销模块-优惠券种类(二十六)

前言 在之前的文章技术分享-商城篇-优惠券管理-功能介绍及种类&#xff08;二十四&#xff09; &#xff0c;有对优惠券设计做了阐述&#xff0c;优惠券作为一种强大的促销工具&#xff0c;不仅能够吸引新客户&#xff0c;还能促进现有客户的复购与订单金额的提升。但是优惠券…

HTML+CSS - 网页布局之网格布局

1. dispaly设置 display是 CSS 中用于设置元素的显示方式的属性。它决定了元素如何被渲染到页面上。不同的display值会改变元素的显示行为&#xff0c;包括布局、排版以及对其他元素的影响。 其中网格容器是最常用的几种方式之一&#xff0c;在文档中创建类似于网格的效果&…

迷你洗衣机哪个牌子好又实惠?5大主流产品综合实测分享!

在日常生活中&#xff0c;内衣洗衣机已成为现代家庭必备的重要家电之一。选择一款耐用、质量优秀的内衣洗衣机&#xff0c;不仅可以减少洗衣负担&#xff0c;还能提供高效的洗涤效果。然而&#xff0c;市场上众多内衣洗衣机品牌琳琅满目&#xff0c;让我们往往难以选择。那么&a…

有性价比高的无线蓝牙耳机吗?四款适合学生党的开放式耳机推荐

最近也是大学生高中生都开学了&#xff0c;我想很多学生都想寻找一款性价比高的真无线蓝牙耳机来提升学习和休闲时的音频体验吧。但是市场上的蓝牙耳机品牌和型号繁多&#xff0c;所以并非所有都适合学生群体的预算和需求。只能是由比较专业的耳机测评专家来推荐给学生党入手了…

git编译安装报错

编译安装步骤 卸载旧的 yum -y remove gitcd /usr/local/src/wget https://www.kernel.org/pub/software/scm/git/git-2.15.1.tar.xztar -vxf git-2.15.1.tar.xzcd git-2.15.1make prefix/usr/local/git allmake prefix/usr/local/git installecho "export PATH$PATH:/usr…

C++教程(一):超详细的C++矩阵操作和运算(附实例代码,与python对比)

python教程&#xff08;一&#xff09;&#xff1a;超详细的numpy矩阵操作和运算&#xff08;附实例代码&#xff09; 在之前的章节中&#xff0c;我们详细介绍了python中numpy的矩阵操作。但在自动驾驶开发中&#xff0c;我们一般采用C进行功能开发&#xff0c;因此C矩阵运算…

8月最新大模型新书-《自然语言处理:大模型理论与实践》(附PDF)西财赵宇教授新作

介绍 本书主要面向高校本科生、研究生及教学科研人员&#xff0c;适合作为教学用书。同时&#xff0c;它也适合计算语言学家、语言学家、数据科学家和NLP开发人员等专业人士使用。为了照顾不同读者的学科背景差异&#xff0c;书中附录部分专门介绍了与NLP密切相关的基础知识&a…

HAL库学习梳理——SPI(收发Flash数据实验)

实验现象&#xff1a;将LED灯的状态保存到Flash里&#xff0c;掉电读取Flash并设置LED。 1&#xff0c;STM32CubeMx 配置 1.1 SPI引脚说明 外设连接 1.2 参数配置 配置工作模式 主机工作模式 SPI 工作参数设置 1.3 GPIO配置 SPI接线配置 SPI引脚的GPIO配置 2&#xff0c;程序…

大模型开源:ChatGLM-6B (介绍以及本地部署)

简介 ChatGLM-6B 是一个开源的、支持中英双语问答的对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&#xff0c;具有 62 亿参数。结合模型量化技术&#xff0c;用户可以在消费级的显卡上进行本地部署&#xff08;INT4 量化级别下最低只需 6GB 显存&#xff…