微盟离线数仓模型建设与治理实践

本文首发自 微盟技术中心 微信公众平台~

一、前言背景

为解决各业务线数据重复加工、指标结果不一致等一系列数据问题,基于新商业化WOS 操作系统底层数据架构,需要建设一套数仓模型,便于支持新商业化 WOS 操作系统数据侧的报表、API、业务系统等数据应用场景需求。

二、建设思路

2.1 业务调研

在 WOS 系统重构的时候,微盟业务从之前的快速扩张阶段进入相对稳定的发展阶段,业务发展进入成熟期。由于业务很多且复杂,这里主要简述一下大致流程。从上图可以看出,业务流程主要分两大块,商业化前和商业化后。商业化前是指微盟客户还未成为微盟商户之前一系列的业务动作,商业化后是指微盟客户成为微盟商户之后的一系列的业务动作。按照这个思路把每个业务环节可能产生的数据以及数据对应的系统梳理清楚,方便后续数仓的建设。

2.2.数据域划分

数据域是联系较为紧密的数据主题的集合,是业务对象高度概括的概念层次归类,目的是便于数据的管理和应用。

  • 划分原则:按数据类型进行划分。比如导购订单的数据,那应该是按订单进行划分到对应的数据域,而不是按导购进行划分到对应的数据域,导购在这类数据只是一个维度。
  • 划分范围:数据域划分范围是指数仓DWD、DWS、DIM层。
  • 命名规则:一共划分为数据域和数据子域两层,优先对数据子域命名。数据子域命名规则:
    • 按业务过程命名或者业务过程总称:比如交易流程中,常见的下单、支付等业务过程。该数据对应的数据子域就直接叫下单、支付。
    • 按实体对象命名:比如商品名称、编码图片等商品属性信息,这类数据对应的数据子域就直接叫商品。
    • 按业务名称命名:比如在做工单分析、数据治理或者体量很小的业务需求的时候,这类数据就没必要严格按照业务过程或者实体对象去细化数据子域,故这类数据就直接按治理、工单直接命名数据子域。

数据子域命名结束可以对数据域取一个适当的总称(没有具体规则)。

2.3.数仓分层架构

数据仓库模型设计除了根据业务数据类型纵向划分数据域,还需要横向划分分层架构。这边我们分层架构为ODS、DWD、DWS、DIM、ADS、OUTPUT六层架构。每一层作用:

  • ODS(贴源层):把OLTP的数据几乎无处理的存放在数据仓库系统中,一般采用增量或全量同步,需要关注源系统的性能和重复存储的成本。
  • DWD(明细层):使用维度建模方法,采用维度退化手法将维度退化至事实表,对业务过程进行重新建模,构建符合需求细粒度的明细层事实表。提升数据易用性方便上层数据的加工和计算。明细粒度事实层通常分为三种:事务事实表、周期快照事实表和累积快照事实表。因为具有通用性,需要关注数据的易用性、稳定性。
  • DWS(汇总层):公共汇总粒度事实层以分析的主题对象作为建模驱动,基于ADS上层的应用和产品的指标需求构建公共粒度的汇总指标事实表。沉淀共用指标、减少重复计算,保证指标口径统一。因为具有通用性,需要关注数据的易用性、稳定性。
  • DIM(维度层):基于维度建模理念思想,建立整个企业的一致性维度。降低数据计算口径和算法不统一风险。公共维度层的表通常也被称为逻辑维度表,维度和维度逻辑表通常一一对应。
  • ADS(集市层):分析上层应用,按照业务角度组织数据,快速响应业务需求,可以关联一些维度表进行补充维度。需要关注研发效率、口径一致性、稳定性。注意:该层尽量不要有指标计算逻辑。
  • OUTPUT(导出层):基于ads计算好的结果,推送到下游数据库,可以做一些数据的过滤。因为涉及跟外部系统关联,需要关注目标系统的性能、任务稳定性。注意:该层禁止出现指标加工、维度补充逻辑。

2.4.模型建设

四种常见的建模方法:
  1. 维度建模:维度建模从分析决策的需求出发而构建模型,为分析需求服务。因为重点关注用户如何快速的完成数据分析,可以直观的反应业务模型中的业务问题,需要大量的数据预处理、数据冗余,有较好的大规模复杂查询的响应性能。
  2. 范式建模:即实体关系(ER)模型,数据仓库之父 Immon 提出的,从全企业的高度设计一个 3NF 模型,用实体加关系描述的数据模型描述企业业务架构,在范式理论上符合 3NF。此建模方法,对建模人员的能力要求非常高。
  3. Data Vault模型:DataVault由Hub(关键核心业务实体)、Link(关系)、Satellite(实体属性) 三部分组成 ,是Dan Linstedt发起创建的一种模型方法论,它是在 ER 关系模型上的衍生,同时设计的出发点也是为了实现数据的整合,并非为数据决策分析直接使用。
  4. Anchor模型:高度可扩展的模型,所有的扩展只是添加而不是修改,因此它将模型规范到6NF,基本变成了K-V 结构模型。

通过分析对比以上建模方法特点,结合互联网行业自身特点,想要快速响应业务需求,完成数据分析等数据处理需求,只能选择维度建模这种方式来快速支持业务对数据的需求。

维度建模

维度建模四个步骤:选择业务过程 > 声明粒度 > 确认维度 > 确认事实

  1. 业务过程是组织完成的操作型活动,比如订单下单、处理售后订单、营销活动创建等。业务过程中事件建立或获取度量,并转换为事实表中的事实。这里需要关注重点是业务过程,并非是某个业务部门。确保某个业务过程的核心数据只被抽取一次,保证数仓中业务数据一致性。
  2. 声明粒度是维度建模重要步骤。粒度是用于确定事实表中行表示声明。在业务过程获取的数据时,原子粒度是最低级别的粒度。建议从原子粒度设计开始,因为原子粒度才能满足对汇总粒度的数据最好解释,也能够满足用户对数据的最细粒度分析需求。在同一个事实表中不要把不同粒度的数据放到一起。
  3. 维度是对某一个业务过程事件所涉及到的谁、何处、何时等背景。维度在数仓非常可以称为"灵魂"。因为维度是数仓BI系统业务分析的入口。
  4. 事实是业务过程事件的度量,大多数是数量值表示。事实表中一行跟按事实表的粒度描述的度量事件是一对一的关系。在事实表里面,我们只允许与声明的粒度保持一致。
模型分层设计原则
数仓建模主要是指DWD、DWS、DIM,而ADS主要是分析业务需求,通过新建模型或者复用数仓现有模型,组装成宽表形式,推送给下游使用。

1、明细粒度事实层DWD (Data Warehouse Detail):通过企业的业务活动事件构建数据模型。基于具体业务过程的特点,构建最细粒度的明细数据表。可以结合企业的数据使用特点,将明细数据表的某些重要维度属性字段适当冗余,即宽表化处理。同时,也可以减少明细数据表及维度表的关联,提高明细表的易用性。设计原则如下所示:

    1. 只选择与业务过程相关的事实。
    2. 分解不可加性事实为可加的组件。
    3. 在选择维度和事实之前必须先声明粒度。
    4. 在同一个事实表中不能有多种不同粒度的事实。
    5. 事实的单位要保持一致。
    6. 标准化处理Null值(或者空字符串)、异常值、离散值。
      1. Null值处理:如果字段类型为数字型,Null赋予-88888,如果字段类型为字符串类型,Null赋予unknown。
      2. 异常值:如果确认是异常值,需要处理掉。
      3. 离散值:如果个别值不应该出现,比如下单时间是1970年,这种也必须处理掉。
    7. 使用退化维度提高事实表的易用性。例如:订单号也是一种维度,退化到下单模型事实表中。

2、公共粒度汇总事实层DWS (Data Warehouse Service):通过分析的主题对象构建数据模型。基于上层的应用和产品的指标需求,构建公共粒度的汇总指标事实表。设计原则如下所示:

  1. 由于各业务方去重指标计算口径和维度都不一样,故 DWS 基于上层的应用和产品的指标需求,对 DWS 各业务过程进行轻度汇总,构建多维度+可累加的指标+用于去重指标计算的字段(各业务方在基于结果再出固定维度的 DWS 模型)。以宽表化手段物理化模型,构建命名规范、累计指标口径一致的统计指标,为上层提供公共指标,建立轻度汇总事实表。
  2. 聚集是不跨越事实的。聚集是针对原始模型进行的汇总。为获取和查询与原始模型一致的结果,聚集的维度和度量必须与原始模型保持一致,因此聚集是不跨越事实的。
  3. 聚集会带来查询性能的提升,但聚集也会增加 ETL 维护的难度。当维度发生变更时,先前存在的、已经被汇总到聚集表中的数据需要被重新调整。
  4. 统计不跨数据域。数据域是在较高层次上对数据进行分类聚集的抽象。数据域通常以业务过程进行分类,例如交易统一划到交易域下, 商品的新增、修改放到商品域下。
  5. 区分统计周期。在表的命名上要能说明数据的统计周期。
  6. 标准化处理Null值(或者空字符串)、异常值、离散值。
    1. Null值处理:如果字段类型为数字型,Null赋予-88888,如果字段类型为字符串类型,Null赋予unknown。
    2. 异常值:如果确认是异常值,需要处理掉。
    3. 离散值:如果个别值不应该出现,比如下单时间1970年,这种也必须处理掉。

3、公共维度层DIM (Dimension):基于实际业务,通过定义维度,确定维度主键,添加维度属性,关联不同维度等操作,构建整个企业的一致性数据分析维表,帮助您降低数据计算口径和算法不统一的风险。

  1. 维度表信息不易过大。
  2. 维表和其他表关联,建议走Map Join。
  3. 静态维表不用每日更新,可以按需更新。
  4. 维表中数据的稳定性,业务系统如果有逻辑删除,维度表的数据需要保留下来,不能直接逻辑剔除掉。
  5. 维表是否需要垂直拆分。如果一个维表存在大量属性不被使用,或由于承载过多属性字段导致查询变慢,则需要考虑对字段进行拆分,创建多个维表。
  6. 维表是否需要水平拆分。如果记录之间有明显的界限,可以考虑拆成多个表或设计成多级分区。
  7. 核心维表的产出时间应该有严格监控。
  8. 标准化处理Null值(或者空字符串)、异常值、离散值。
    1. Null值处理:如果字段类型为数字型,Null赋予-88888,如果字段类型为字符串类型,Null赋予unknown。
    2. 异常值:如果确认是异常值,需要处理掉。
    3. 离散值:如果个别值不应该出现,比如下单时间1970年,这种也必须处理掉。

3.实践结果

3.1.数仓分层结果

分层架构: 基于多开发组的场景下,数仓分层架构没有变化,依然是分层 ODS、DWD、DWS、DIM、ADS、OUTPUT 层。但是在 DWD、DWS、DIM 建设方式上抽出了一层公共层概念,也就是公共 DWD、公共 DWS、公共 DIM。把通用的数据(比如:订单基础数据、用户维度数据等)和通用的逻辑放在公共层建设。这里要提一下,对于公共 DWS,由于各个开发组指标算法可能不一样,所以公共 DWS 只是针对数据量大的场景做了一层轻度的聚合,没有计算固定维度的指标,业务方可以基于该 DWS 再计算一个固定维度的 DWS 对应的指标。对于哪些数据和逻辑划分到公共层,目前是依据人为对业务流程、业务落地的数据、需求分析、数据复用度等综合分析判断,也就是所谓的经验。分层依赖: 基于多开发组场景,对分层之间的依赖制定了一些规范:1.DWD(公共开发组)可以依赖ODS2.DWD(业务方开发组)可以依赖ODS、DWD(公共开发组)3.DWS(公共开发组)可以依赖DWD(公共开发组)、DWD(业务方开发组)4.DWS(业务方开发组)可以依赖DWD(公共开发组)、DWD(业务方开发组)、DWS(公共开发组)5.DIM(公共开发组)可以依赖ODS6.DIM(业务方开发组)可以依赖ODS、DIM(公共开发组)7.ADS 可以依赖ADS,不强制。但是公共指标口径逻辑应该沉淀到DWS,否则ADS下线、变更、治理过程中就会导致成本就很高,需要考虑的范围变广,进而影响全流程开发效率。8.OUTPUT直接依赖DWD/DIM/DWS只能是数据导出的场景,可以省去开发ADS层。比如:流量业务open api(行为事件接口)需要把明细日志行为事件推送到外部系统。这种场景可以直接DWD-->OUTPUT。但是OUTPUT任务禁止加工各种join的业务逻辑处理,只能做一些数据过滤的动作。

3.2.数据域划分结果

数据域是需要抽象提炼并且长期维护和更新,但是不能轻易变动。在对数据域划分的时候,既能涵盖当前所有业务需求,又能在新的业务进入时无影响的被当前已有的数据域包含或者扩展新的数据域。按照2.1业务调研我们把微盟业务大体分为两块商业化前和商业化后,对应的数据我们划分为:产品域、销售域、财务域、交易域、日志域、商户域、商品域、资产域、角色域、活动域、服务域、配置域、工效域。一共划分13个域,每个数据域下面有对应的数据子域。其中商户域没有划分到角色域是因为商户域比较重要,所以单独划分了一个域。

3.3.模型设计案例

在进行模型设计的时候,并不是一味的按设计原则照搬,而且应该结合实际需求和对业务侧落地的数据的探查结果,进而对性能、成本、复杂度等多方面评估选择最优方案。

案例A:DWD设计

1.需求: 某业务需要统计商城内部订单和商户导入订单的每日下单金额等指标。2.分析: 商城内部订单是商户的客户下单就会产生的订单,订单下单时间都是当天。而导入订单是商户通过 Execl 导入商户线下交易数据,订单下单时间有可能是很久之前。3.设计方案: 为满足此类场景,并非是按部就班,按业务过程,用下单时间增量入表。因为外部订单导入的时候有可能是导入历史的下单时间,且内部订单全量非常大,外部订单当前不是很大,故把内部订单和外部订单分成2个 DWD,内部订单 DWD 增量加载订单数据,外部订单 DWD 全量加载订单数据。如果后续外部订单越来越大,就需要考虑改为增量加载,可以使用导入订单时间,这里要注意一下,商户可能导入订单,后面又删除订单,所以外部订单考虑增量加载的话得关注订单重复导入的问题。

案例B:DWS设计

1.需求:某业务需要统计商户商城店铺的最近一年的访客量(按cuid计算,跨天访客需要去重)2.分析:基于日志的数据和分析需求,日志 DWD 模型设计为 pv 模型、tap 模型、other 模型。由于 pv 模型数据量很大,如果直接用这个数据计算一年的访客量,任务所消耗的资源会很大,且任务执行时长也会很久,不满足数据产出时效。3.设计方案:为解决这种计算量很大的指标,在 DWS 汇总层前面添加一层 DWS 轻度汇总层,轻度汇总层的维度必须满足稠密条件,以达到降低数据量的目的。我们按需要的维度设计 DWS 轻度公共每日汇总层,该层 DWS 数据量相比之前数据量降低70%左右,任务运行资源和时效可以满足需求。当然如果觉得数据量还是偏大,业务方可以 DWS 轻度公共每日汇总层再产出一个 DWS 业务侧每月汇总层(保留cuid),基于该层再计算最近一年的去重 cuid 数。这样的设计好处是把一次性计算的压力分散在每一层模型当中。

案例C:DIM设计

1.需求:某业务需要计算日周月在售商品数。2.分析:由于商品在售状态是可以被商户调整的,且业务方没有变更日志,数据库里面只有商品在售的最新状态。需求是从三个时间周期看店铺的在售商品数。3.设计方案:商品数据量也非常大,如果每天保存一份全量快照,不仅对于存储非常浪费,对于计算月维度的在售数据也很消耗资源。因此我们引入拉链表,第一次初始化全量在售数据,开始日期给初始化日期(开链),结束时间给2099年12月31日,后续只存储新增商品对应的在售状态数据和存量商品变化的在售数据,开始日期给当日计算日期,结束时间给2099年12月31日。最后对存量和增量的所有商品在售数据的结束时间进行全量闭链。 随着商户基本迁移完成,商品在售状态每日新增和变化量是在可接受的量级,基于目前商品在售全量拉链表计算月维度的商品在售数据是可以满足数据产出时效的。

3.4模型分层分布实践结果

整个BI团队新商业化WOS操作系统模型整体比例分布DWD:DWS:DIM:ADS≈1.5:2:1:5。也就是说产出5个ADS数据应用需要建设1.5个DWD,2个DWS,1个DIM。整体比例还行,但是DWS模型的占比略多,还有提升空间。

四、模型治理

4.1.实践遇到的问题

在业务快速发展的情况下,为了快速响应业务需求,模型产生问题也是必然的。日常工作中,模型实践过程中,发现如下问题:

  • 依赖不规范:比如数据研发接收到业务需求,然后 OUTPUT 任务直接依赖 ODS,没有进行模型建设。
  • 模型重复建设:比如A开发组建设了商户权益模型,后来B开发组又建设了商户权益模型。
  • 模型过度设计:比如A开发组新来一个需求,只需要在B开发组的模型增加一个字段就可以满足需求,但是B由于某些原因没接受该需求,导致A开发组基于B开发组的模型又设计一个新的模型来支持新的需求。
  • 表命名不规范:由于各个开发人员开发习惯不一样,导致表名在命名上千奇百怪。
  • 表描述不规范:由于之前系统未强制要求写表描述,导致有些模型没有表的描述,以至于后续盘点数据资产就会大大增加时间成本。
  • ADS逻辑未下沉到公共层:由于项目开发时间紧急,导致一些公共逻辑未沉淀到存量DWS、DWD模型或者新增的DWS、DWD模型。

4.2.治理方案

对这些问题分析一下原因,大致可以归类为:1、机制规范不完善 2、产品工具不完善 3、模型管理不完善。为此制定模型治理方案,主要包含3点:

事前

1)规范宣导:通过宣导数据开发流程规范中模型规范的数据域划分原则、模型设计原则、模型分层原则、模型依赖原则等,让大家对模型基本规范达成统一共识。2)产品工具:

  1. 通过产品系统化标准管理,把数仓规划、维度建模、数据指标、数据标准等这些标准定义内容植入系统中,使得增量模型规范化,提高模型规范度。
  2. 数据建模最终是体现在以表的物理形式存在,通过对表创建详细管理,有利于模型日常运维管理和降低数据资产盘点成本。在创建表的时候需要选择模型分层,在选择dwd\dim\dws分层会出现子数据域,选择ads分层会出现主题域(各业务线根据数据应用在数据建模-->数仓规划-->主题域,添加对应主题域)。除此之外还需要补充数据归属业务线、该表的自定义信息(通过下拉词根选择)、表的汇总(明细)形式。
事中

流程规范:在数据研发流程中,主要包含七大环节,分别是:需求评审、设计、开发、自测、测试、上线、运营。1)需求评审这一阶段要明确用户需求,分析清楚有哪些业务过程、维度、原子指标、派生指标等,并跟用户沟通清楚达成口径一致。然后让产品完善需求文档,并且需要把最终定稿需求纳入需求管理系统中。产物:标准需求文档,包含如下:

  1. 项目/需求名称:本需求文档是哪个项目或者是某个需求。
  2. 需求背景/场景描述:需求是由啥原因产生的。
  3. 需求内容/目的:需求要解决啥问题,达到啥目的。
  4. 需求价值:主要衡量是否个性化需求或者通用需求。
  5. 需求优先级:需求在一个迭代版本中优先级。
  6. 迭代模块:需求要改哪块内容。
  7. 指标口径:需求涉及的指标口径算法是什么。
  8. 数据输出展示格式特别说明:数据需要输出展示的时候,数据格式是否有要求。

产出人:产品经理。2)设计根据上述标准需求文档,研发人员需要对需求分析进行分析,产出需求分析结果,包含业务过程、维度、指标等,可以是 Execl、思维导图。根据需求分析结果完成数仓设计。产物:标准设计文档,包含如下:

  1. 需求梳理:主要输出需求维度\指标\口径。
  2. 数仓分层设计数据流向图:主要输出模型分层及模型数据流向。
  3. 数仓逻辑模型设计说明:主要输出模型主要的属性\维度\事实指标及模型之间的关系
  4. 数仓物理模型设计概要说明:主要输出模型所属分层、库名、表名、中文名等概要信息。
  5. 数仓物理模型设计详细说明:主要输出模型分区、字段名、字段名称等表结构详细信息

产出人:研发人员。3)开发需求分析和设计做的都很充分的情况下,基于微盟数据平台系统可以方便快速模型建设和 ETL 开发。开发结束可以,可以通过保存任务、冒烟、回测等工具功能进行代码测试和数据验证。4)自测在开发结束后,研发人员需要进行自测,产物:标准自测文档,包含如下:

  1. 数据完整性检查:数据每一项都应该被记录,可以通过对字段进行为空或者为空字符串进行检查。
  2. 数据唯一性检查:数据是否存在重复,每条数据是否是唯一的,可以通过对主键或者自定义复合字段检测是否重复。
  3. 数据一致性检查:即数据在迁移或者加工前后是否一致,可以通过数仓各层进行的数据量验证,也可以通过报表跟其他报表/业务系统数据验证。
  4. 数据准确性检查:准确性是指该数据是否能反映业务的内容,可以对数据的某些字段的总和检测、平均值检测、最大最小值检测是否与业务状况相似。
  5. 数据有效性检查:有效性是指该数据是否符合规则,如日期字段的数据是否符合统一的日期格式,金额的字段数值范围是否合理,身份证字段数据是否合规等。

产出人:研发人员。5)测试在自测结束之后,研发人员需要发邮件告知测试人员对需求进行测试。测试人员准备好测试用例邀请研发和产品进行测试用例评审。用例评审通过后然后进行需求测试。6)上线在测试告知需求测试通过,研发人员需要准备上线邮件、发布和回滚方案。确保需求合规、安全上线。产物:发布和回滚方案文档,包含如下:

  1. 上线前准备具体事项、依赖、时间、负责人、验证人、验证状态。
  2. 发布阶段具体事项、依赖、时间、负责人、验证人、验证状态。
  3. 线上验证具体事项、依赖、时间、负责人、验证人、验证状态。
  4. 回滚前准备具体事项、依赖、时间、负责人、验证人、验证状态。
  5. 回滚阶段具体事项、依赖、时间、负责人、验证人、验证状态。
  6. 回滚后具体事项、依赖、时间、负责人、验证人、验证状态。

产出人:研发人员7)运营在上述过程中,不仅需要对需求研发过程中保证质量,还要事后对线上运营过程中模型质量、ETL 时效等进行治理。a)需求评论:为保证需求研发质量,我们是通过对该需求进行标准评论,总共分为3个评论项:需求文档Review、设计文档Review、开发Review(包含发布\回滚方案)。其中需求文档Review是研发人员对产品经理产出的需求文档进行Review。设计文档Review、开发Review是研发负责人对研发人员的设计文档、代码是否合规、发布\回滚方案是否健壮等进行Review。Review的结果需要在需求管理系统中每一个具体需求的评论处进行标准评论。通过对标准评论的解析,在看板上面展示不同维度的需求健康分统计结果,方便管理层对需求研发流程健康度的管理和治理。b)线上治理:通过一定规则,拉出异常对象,按对象所属owner通过数据治理中心进行派发治理。

事后

针对模型缺失和模型复用度,制定相应指标,形式长期对模型健康度的稳定运营监控。

  1. 模型覆盖度是指数仓中(DWS、ADS、OUTPUT总任务数)-(DWS、ADS、OUTPUT直接引用ODS数据的任务数)/DWS、ADS、OUTPUT总任务数*100%;
  2. 模型复用度是指数仓中DWD、DWS、DIM被下游任务复用次数/DWD、DWS、DIM的任务数。一个模型被一个任务复用计算一次,被多个任务复用则累加。

4.3.治理效果

通过对模型覆盖度的治理,由最初93.37%提升到97.82%,效果还是比较明显。模型覆盖度当前值:97.82% 模型覆盖度上升趋势图

五、结语

目前模型覆盖度已经纳入治理中心进行治理,进展和效果都还可以。但是模型复用度治理还未开始实施。后续打算从这三个维度来提升模型覆盖度:

  • 通过优化数据资产大盘,方便研发人员快速查找现有模型,进而进行复用。
  • 通过数据建模,对新的模型进行维度管理,新增模型纳入审批流程,减少模型重复建设。
  • 通过对开发任务代码进行分段扫描,分析出不合理的重复代码,纳入治理中心进行专项治理。

六、参考资料

1、数据仓库工具箱(第3版)

相关推荐
搬码后生仔1 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
凡人的AI工具箱1 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
Lx3522 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas
小池先生2 小时前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
百罹鸟2 小时前
【vue高频面试题—场景篇】:实现一个实时更新的倒计时组件,如何确保倒计时在页面切换时能够正常暂停和恢复?
vue.js·后端·面试
小蜗牛慢慢爬行3 小时前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
wm10434 小时前
java web springboot
java·spring boot·后端
龙少95436 小时前
【深入理解@EnableCaching】
java·后端·spring
溟洵7 小时前
Linux下学【MySQL】表中插入和查询的进阶操作(配实操图和SQL语句通俗易懂)
linux·运维·数据库·后端·sql·mysql
SomeB1oody10 小时前
【Rust自学】6.1. 定义枚举
开发语言·后端·rust