5個互聯網大廠實時數倉建設實例,例例皆經典

来源:https://www.cnblogs.com/88223100/archive/2022/03/16/5_examples_of_real-time_data_warehouse_construction_in_Internet_giants.html
-Advertisement-
Play Games

目前各大公司的產品需求和內部決策對於數據實時性的要求越來越迫切,需要實時數倉的能力來賦能。傳統離線數倉的數據時效性是 T+1,調度頻率以天為單位,無法支撐實時場景的數據需求。即使能將調度頻率設置成小時,也只能解決部分時效性要求不高的場景,對於實效性要求很高的場景還是無法優雅的支撐。因此實時使用數據的... ...


一、实时数仓建设背景

1. 实时需求日趋迫切

目前各大公司的产品需求和内部决策对于数据实时性的要求越来越迫切,需要实时数仓的能力来赋能。传统离线数仓的数据时效性是 T+1,调度频率以天为单位,无法支撑实时场景的数据需求。即使能将调度频率设置成小时,也只能解决部分时效性要求不高的场景,对于实效性要求很高的场景还是无法优雅的支撑。因此实时使用数据的问题必须得到有效解决。

2. 实时技术日趋成熟

实时计算框架已经经历了三代发展,分别是:Storm、SparkStreaming、Flink,计算框架越来越成熟。一方面,实时任务的开发已经能通过编写 SQL 的方式来完成,在技术层面能很好地继承离线数仓的架构设计思想;另一方面,在线数据开发平台所提供的功能对实时任务开发、调试、运维的支持也日渐趋于成熟,开发成本逐步降低,有助于去做这件事。

二、实时数仓建设目的

1. 解决传统数仓的问题

从目前数仓建设的现状来看,实时数仓是一个容易让人产生混淆的概念,根据传统经验分析,数仓有一个重要的功能,即能够记录历史。通常,数仓都是希望从业务上线的第一天开始有数据,然后一直记录到现在。但实时流处理技术,又是强调当前处理状态的一个技术,结合当前一线大厂的建设经验和滴滴在该领域的建设现状,我们尝试把公司内实时数仓建设的目的定位为,以数仓建设理论和实时技术,解决由于当前离线数仓数据时效性低解决不了的问题。

现阶段我们要建设实时数仓的主要原因是:

  • 公司业务对于数据的实时性越来越迫切,需要有实时数据来辅助完成决策;
  • 实时数据建设没有规范,数据可用性较差,无法形成数仓体系,资源大量浪费;
  • 数据平台工具对整体实时开发的支持也日渐趋于成熟,开发成本降低。

2. 实时数仓的应用场景

  • 实时 OLAP 分析;
  • 实时数据看板;
  • 实时业务监控;
  • 实时数据接口服务。

三、实时数仓建设方案

接下来我们分析下目前实时数仓建设比较好的几个案例,希望这些案例能够给大家带来一些启发。

1. 滴滴顺风车实时数仓案例

滴滴数据团队建设的实时数仓,基本满足了顺风车业务方在实时侧的各类业务需求,初步建立起顺风车实时数仓,完成了整体数据分层,包含明细数据和汇总数据,统一了 DWD 层,降低了大数据资源消耗,提高了数据复用性,可对外输出丰富的数据服务。

数仓具体架构如下图所示:

从数据架构图来看,顺风车实时数仓和对应的离线数仓有很多类似的地方。例如分层结构;比如 ODS 层,明细层,汇总层,乃至应用层,他们命名的模式可能都是一样的。但仔细比较不难发现,两者有很多区别:

  • 与离线数仓相比,实时数仓的层次更少一些:
  • 从目前建设离线数仓的经验来看,数仓的数据明细层内容会非常丰富,处理明细数据外一般还会包含轻度汇总层的概念,另外离线数仓中应用层数据在数仓内部,但实时数仓中,app 应用层数据已经落入应用系统的存储介质中,可以把该层与数仓的表分离;
  • 应用层少建设的好处:实时处理数据的时候,每建一个层次,数据必然会产生一定的延迟;
  • 汇总层少建的好处:在汇总统计的时候,往往为了容忍一部分数据的延迟,可能会人为的制造一些延迟来保证数据的准确。举例,在统计跨天相关的订单事件中的数据时,可能会等到 00:00:05 或者 00:00:10 再统计,确保 00:00 前的数据已经全部接受到位了,再进行统计。所以,汇总层的层次太多的话,就会更大的加重人为造成的数据延迟。
  • 与离线数仓相比,实时数仓的数据源存储不同:
  • 在建设离线数仓的时候,目前滴滴内部整个离线数仓都是建立在 Hive 表之上。但是,在建设实时数仓的时候,同一份表,会使用不同的方式进行存储。比如常见的情况下,明细数据或者汇总数据都会存在 Kafka 里面,但是像城市、渠道等维度信息需要借助 Hbase,mysql 或者其他 KV 存储等数据库来进行存储。

接下来,根据顺风车实时数仓架构图,对每一层建设做具体展开:

1) ODS 贴源层建设

根据顺风车具体场景,目前顺风车数据源主要包括订单相关的 binlog 日志,冒泡和安全相关的 public 日志,流量相关的埋点日志等。这些数据部分已采集写入 kafka 或 ddmq 等数据通道中,部分数据需要借助内部自研同步工具完成采集,最终基于顺风车数仓 ods 层建设规范分主题统一写入 kafka 存储介质中。

命名规范:ODS 层实时数据源主要包括两种。

一种是在离线采集时已经自动生产的 DDMQ 或者是 Kafka topic,这类型的数据命名方式为采集系统自动生成规范为:cn-binlog-数据库名-数据库名 eg:cn-binlog-ihap_fangyuan-ihap_fangyuan

一种是需要自己进行采集同步到 kafka topic 中,生产的 topic 命名规范同离线类似:ODS 层采用:realtime_ods_binlog_{源系统库/表名}/ods_log_{日志名} eg: realtime_ods_binlog_ihap_fangyuan

2)DWD 明细层建设

根据顺风车业务过程作为建模驱动,基于每个具体的业务过程特点,构建最细粒度的明细层事实表;结合顺风车分析师在离线侧的数据使用特点,将明细事实表的某些重要维度属性字段做适当冗余,完成宽表化处理,之后基于当前顺风车业务方对实时数据的需求重点,重点建设交易、财务、体验、安全、流量等几大模块;该层的数据来源于 ODS 层,通过大数据架构提供的 Stream SQL 完成 ETL 工作,对于 binlog 日志的处理主要进行简单的数据清洗、处理数据漂移和数据乱序,以及可能对多个 ODS 表进行 Stream Join,对于流量日志主要是做通用的 ETL 处理和针对顺风车场景的数据过滤,完成非结构化数据的结构化处理和数据的分流;该层的数据除了存储在消息队列 Kafka 中,通常也会把数据实时写入 Druid 数据库中,供查询明细数据和作为简单汇总数据的加工数据源。

命名规范:DWD 层的表命名使用英文小写字母,单词之间用下划线分开,总长度不能超过 40 个字符,并且应遵循下述规则:realtime_dwd_{业务/pub}_{数据域缩写}_[{业务过程缩写}]_[{自定义表命名标签缩写}]

  • {业务/pub}:参考业务命名
  • {数据域缩写}:参考数据域划分部分
  • {自定义表命名标签缩写}:实体名称可以根据数据仓库转换整合后做一定的业务抽象的名称,该名称应该准确表述实体所代表的业务含义
  • 样例:realtime_dwd_trip_trd_order_base

3) DIM 层

  • 公共维度层,基于维度建模理念思想,建立整个业务过程的一致性维度,降低数据计算口径和算法不统一风险;
  • DIM 层数据来源于两部分:一部分是 Flink 程序实时处理 ODS 层数据得到,另外一部分是通过离线任务出仓得到;
  • DIM 层维度数据主要使用 MySQL、Hbase、fusion(滴滴自研 KV 存储) 三种存储引擎,对于维表数据比较少的情况可以使用 MySQL,对于单条数据大小比较小,查询 QPS 比较高的情况,可以使用 fusion 存储,降低机器内存资源占用,对于数据量比较大,对维表数据变化不是特别敏感的场景,可以使用 HBase 存储。

命名规范:DIM 层的表命名使用英文小写字母,单词之间用下划线分开,总长度不能超过 30 个字符,并且应遵循下述规则:dim_{业务/pub}_{维度定义}[_{自定义命名标签}]:

  • {业务/pub}:参考业务命名
  • {维度定义}:参考维度命名
  • {自定义表命名标签缩写}:实体名称可以根据数据仓库转换整合后做一定的业务抽象的名称,该名称应该准确表述实体所代表的业务含义
  • 样例:dim_trip_dri_base

4) DWM 汇总层建设

在建设顺风车实时数仓的汇总层的时候,跟顺风车离线数仓有很多一样的地方,但其具体技术实现会存在很大不同。

第一:对于一些共性指标的加工,比如 pv,uv,订单业务过程指标等,我们会在汇总层进行统一的运算,确保关于指标的口径是统一在一个固定的模型中完成。对于一些个性指标,从指标复用性的角度出发,确定唯一的时间字段,同时该字段尽可能与其他指标在时间维度上完成拉齐,例如行中异常订单数需要与交易域指标在事件时间上做到拉齐。

第二:在顺风车汇总层建设中,需要进行多维的主题汇总,因为实时数仓本身是面向主题的,可能每个主题会关心的维度都不一样,所以需要在不同的主题下,按照这个主题关心的维度对数据进行汇总,最后来算业务方需要的汇总指标。在具体操作中,对于 pv 类指标使用 Stream SQL 实现 1 分钟汇总指标作为最小汇总单位指标,在此基础上进行时间维度上的指标累加;对于 uv 类指标直接使用 druid 数据库作为指标汇总容器,根据业务方对汇总指标的及时性和准确性的要求,实现相应的精确去重和非精确去重。

第三:汇总层建设过程中,还会涉及到衍生维度的加工。在顺风车券相关的汇总指标加工中我们使用 Hbase 的版本机制来构建一个衍生维度的拉链表,通过事件流和 Hbase 维表关联的方式得到实时数据当时的准确维度

命名规范:DWM 层的表命名使用英文小写字母,单词之间用下划线分开,总长度不能超过 40 个字符,并且应遵循下述规则:realtime_dwm_{业务/pub}_{数据域缩写}_{数据主粒度缩写}_[{自定义表命名标签缩写}]_{统计时间周期范围缩写}:

  • {业务/pub}:参考业务命名
  • {数据域缩写}:参考数据域划分部分
  • {数据主粒度缩写}:指数据主要粒度或数据域的缩写,也是联合主键中的主要维度
  • {自定义表命名标签缩写}:实体名称可以根据数据仓库转换整合后做一定的业务抽象的名称,该名称应该准确表述实体所代表的业务含义
  • {统计时间周期范围缩写}:1d:天增量;td:天累计(全量);1h:小时增量;th:小时累计(全量);1min:分钟增量;tmin:分钟累计(全量)
  • 样例:realtime_dwm_trip_trd_pas_bus_accum_1min

(5)APP 应用层

该层主要的工作是把实时汇总数据写入应用系统的数据库中,包括用于大屏显示和实时 OLAP 的 Druid 数据库(该数据库除了写入应用数据,也可以写入明细数据完成汇总指标的计算)中,用于实时数据接口服务的 Hbase 数据库,用于实时数据产品的 mysql 或者 redis 数据库中。

命名规范:基于实时数仓的特殊性不做硬性要求。

2. 快手实时数仓场景化案例

1) 目标及难点

① 目标

首先由于是做数仓,因此希望所有的实时指标都有离线指标去对应,要求实时指标和离线指标整体的数据差异在 1% 以内,这是最低标准。

其次是数据延迟,其 SLA 标准是活动期间所有核心报表场景的数据延迟不能超过 5 分钟,这 5 分钟包括作业挂掉之后和恢复时间,如果超过则意味着 SLA 不达标。

最后是稳定性,针对一些场景,比如作业重启后,我们的曲线是正常的,不会因为作业重启导致指标产出一些明显的异常。

②难点

第一个难点是数据量大。每天整体的入口流量数据量级大概在万亿级。在活动如春晚的场景,QPS 峰值能达到亿 / 秒。

第二个难点是组件依赖比较复杂。可能这条链路里有的依赖于 Kafka,有的依赖 Flink,还有一些依赖 KV 存储、RPC 接口、OLAP 引擎等,我们需要思考在这条链路里如何分布,才能让这些组件都能正常工作。

第三个难点是链路复杂。目前我们有 200+ 核心业务作业,50+ 核心数据源,整体作业超过 1000。

2) 实时数仓 - 分层模型

基于上面三个难点,来看一下数仓架构:

如上所示:

最下层有三个不同的数据源,分别是客户端日志、服务端日志以及 Binlog 日志;在公共基础层分为两个不同的层次,一个是 DWD 层,做明细数据,另一个是 DWS 层,做公共聚合数据,DIM 是我们常说的维度。我们有一个基于离线数仓的主题预分层,这个主题预分层可能包括流量、用户、设备、视频的生产消费、风控、社交等。DWD 层的核心工作是标准化的清洗;DWS 层是把维度的数据和 DWD 层进行关联,关联之后生成一些通用粒度的聚合层次。再往上是应用层,包括一些大盘的数据,多维分析的模型以及业务专题数据;最上面是场景。整体过程可以分为三步:

第一步是做业务数据化,相当于把业务的数据接进来;第二步是数据资产化,意思是对数据做很多的清洗,然后形成一些规则有序的数据;第三步是数据业务化,可以理解数据在实时数据层面可以反哺业务,为业务数据价值建设提供一些赋能。

3) 实时数仓 - 保障措施

基于上面的分层模型,来看一下整体的保障措施:

保障层面分为三个不同的部分,分别是质量保障,时效保障以及稳定保障。

我们先看蓝色部分的质量保障。针对质量保障,可以看到在数据源阶段,做了如数据源的乱序监控,这是我们基于自己的 SDK 的采集做的,以及数据源和离线的一致性校准。研发阶段的计算过程有三个阶段,分别是研发阶段、上线阶段和服务阶段。研发阶段可能会提供一个标准化的模型,基于这个模型会有一些 Benchmark,并且做离线的比对验证,保证质量是一致的;上线阶段更多的是服务监控和指标监控;在服务阶段,如果出现一些异常情况,先做 Flink 状态拉起,如果出现了一些不符合预期的场景,我们会做离线的整体数据修复。

第二个是时效性保障。针对数据源,我们把数据源的延迟情况也纳入监控。在研发阶段其实还有两个事情:首先是压测,常规的任务会拿最近 7 天或者最近 14 天的峰值流量去看它是否存在任务延迟的情况;通过压测之后,会有一些任务上线和重启性能评估,相当于按照 CP 恢复之后,重启的性能是什么样子。

最后一个是稳定保障。这在大型活动中会做得比较多,比如切换演练和分级保障。我们会基于之前的压测结果做限流,目的是保障作业在超过极限的情况下,仍然是稳定的,不会出现很多的不稳定或者 CP 失败的情况。之后我们会有两种不同的标准,一种是冷备双机房,另外一种是热备双机房。冷备双机房是:当一个单机房挂掉,我们会从另一个机房去拉起;热备双机房:相当于同样一份逻辑在两个机房各部署一次。以上就是我们整体的保障措施。

4)快手场景问题及解决方案

① PV/UV 标准化

  •  场景

第一个问题是 PV/UV 标准化,这里有三个截图:

第一张图是春晚活动的预热场景,相当于是一种玩法,第二和第三张图是春晚当天的发红包活动和直播间截图。

在活动进行过程中,我们发现 60~70% 的需求是计算页面里的信息,如:

这个页面来了多少人,或者有多少人点击进入这个页面;

活动一共来了多少人;

页面里的某一个挂件,获得了多少点击、产生了多少曝光。

  • 方案

抽象一下这个场景就是下面这种 SQL:

简单来说,就是从一张表做筛选条件,然后按照维度层面做聚合,接着产生一些 Count 或者 Sum 操作。

基于这种场景,我们最开始的解决方案如上图右边所示。

我们用到了 Flink SQL 的 Early Fire 机制,从 Source 数据源取数据,之后做了 DID 的分桶。比如最开始紫色的部分按这个做分桶,先做分桶的原因是防止某一个 DID 存在热点的问题。分桶之后会有一个叫做 Local Window Agg 的东西,相当于数据分完桶之后把相同类型的数据相加。Local Window Agg 之后再按照维度进行 Global Window Agg 的合桶,合桶的概念相当于按照维度计算出最终的结果。Early Fire 机制相当于在 Local Window Agg 开一个天级的窗口,然后每分钟去对外输出一次。

这个过程中我们遇到了一些问题,如上图左下角所示。

在代码正常运行的情况下是没有问题的,但如果整体数据存在延迟或者追溯历史数据的情况,比如一分钟 Early Fire 一次,因为追溯历史的时候数据量会比较大,所以可能导致 14:00 追溯历史,直接读到了 14:02 的数据,而 14:01 的那个点就被丢掉了,丢掉了以后会发生什么?

在这种场景下,图中上方的曲线为 Early Fire 回溯历史数据的结果。横坐标是分钟,纵坐标是截止到当前时刻的页面 UV,我们发现有些点是横着的,意味着没有数据结果,然后一个陡增,然后又横着的,接着又一个陡增,而这个曲线的预期结果其实是图中下方那种平滑的曲线。

为了解决这个问题,我们用到了 Cumulate Window 的解决方案,这个解决方案在 Flink 1.13 版本里也有涉及,其原理是一样的。

数据开一个大的天级窗口,大窗口下又开了一个小的分钟级窗口,数据按数据本身的 Row Time 落到分钟级窗口。

Watermark 推进过了窗口的 event_time,它会进行一次下发的触发,通过这种方式可以解决回溯的问题,数据本身落在真实的窗口, Watermark 推进,在窗口结束后触发。此外,这种方式在一定程度上能够解决乱序的问题。比如它的乱序数据本身是一个不丢弃的状态,会记录到最新的累计数据。最后是语义一致性,它会基于事件时间,在乱序不严重的情况下,和离线计算出来的结果一致性是相当高的。以上是 PV/UV 一个标准化的解决方案。

② DAU 计算

  • 背景介绍

下面介绍一下 DAU 计算:

我们对于整个大盘的活跃设备、新增设备和回流设备有比较多的监控。

活跃设备指的是当天来过的设备;新增设备指的是当天来过且历史没有来过的设备;回流设备指的是当天来过且 N 天内没有来过的设备。但是我们计算过程之中可能需要 5~8 个这样不同的 Topic 去计算这几个指标。

我们看一下离线过程中,逻辑应该怎么算。

首先我们先算活跃设备,把这些合并到一起,然后做一个维度下的天级别去重,接着再去关联维度表,这个维度表包括设备的首末次时间,就是截止到昨天设备首次访问和末次访问的时间。

得到这个信息之后,我们就可以进行逻辑计算,然后我们会发现新增和回流的设备其实是活跃设备里打的一个子标签。新增设备就是做了一个逻辑处理,回流设备是做了 30 天的逻辑处理,基于这样的解决方案,我们能否简单地写一个 SQL 去解决这个问题?

其实我们最开始是这么做的,但遇到了一些问题:

第一个问题是:数据源是 6~8 个,而且我们大盘的口径经常会做微调,如果是单作业的话,每次微调的过程之中都要改,单作业的稳定性会非常差;第二个问题是:数据量是万亿级,这会导致两个情况,首先是这个量级的单作业稳定性非常差,其次是实时关联维表的时候用的 KV 存储,任何一个这样的 RPC 服务接口,都不可能在万亿级数据量的场景下保证服务稳定性;第三个问题是:我们对于时延要求比较高,要求时延小于一分钟。整个链路要避免批处理,如果出现了一些任务性能的单点问题,我们还要保证高性能和可扩容。

  • 技术方案

针对以上问题,介绍一下我们是怎么做的:

如上图的例子,第一步是对 A B C 这三个数据源,先按照维度和 DID 做分钟级别去重,分别去重之后得到三个分钟级别去重的数据源,接着把它们 Union 到一起,然后再进行同样的逻辑操作。

这相当于我们数据源的入口从万亿变到了百亿的级别,分钟级别去重之后再进行一个天级别的去重,产生的数据源就可以从百亿变成了几十亿的级别。

在几十亿级别数据量的情况下,我们再去关联数据服务化,这就是一种比较可行的状态,相当于去关联用户画像的 RPC 接口,得到 RPC 接口之后,最终写入到了目标 Topic。这个目标 Topic 会导入到 OLAP 引擎,供给多个不同的服务,包括移动版服务,大屏服务,指标看板服务等。

这个方案有三个方面的优势,分别是稳定性、时效性和准确性。

首先是稳定性。松耦合可以简单理解为当数据源 A 的逻辑和数据源 B 的逻辑需要修改时,可以单独修改。第二是任务可扩容,因为我们把所有逻辑拆分得非常细粒度,当一些地方出现了如流量问题,不会影响后面的部分,所以它扩容比较简单,除此之外还有服务化后置和状态可控。其次是时效性,我们做到毫秒延迟,并且维度丰富,整体上有 20+ 的维度做多维聚合。最后是准确性,我们支持数据验证、实时监控、模型出口统一等。此时我们遇到了另外一个问题 - 乱序。对于上方三个不同的作业,每一个作业重启至少会有两分钟左右的延迟,延迟会导致下游的数据源 Union 到一起就会有乱序。

  • 延迟计算方案

遇到上面这种有乱序的情况下,我们要怎么处理?

我们总共有三种处理方案:

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 變數、流程式控制制和游標 變數 在MySQL資料庫的存儲過程和函數中,可以使用變數來存儲查詢或計算的中間結果數據,或者輸出最終的結果的數據 系統變數 變數由系統定義,屬於伺服器層面 系統變數的分類 每一個MySQL客戶機成功連接伺服器後,都會產生與之對應的會話(建立一次連接相當於一次會話)。MySQL服 ...
  • MySQL 索引(入門): 一、介紹 1.什麼是索引? 一般的應用系統,讀寫比例在10:1左右,而且插入操作和一般的更新操作很少出現性能問題,在生產環境中,我們遇到最多的,也是最容易出問題的,還是一些複雜的查詢操作,因此對查詢語句的優化顯然是重中之重。說起加速查詢,就不得不提到索引了。 2.為什麼要 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 使用爬蟲等獲取實時數據+Flume+Kafka+Spark Streaming+mysql+Echarts實現數據動態實時採集、分析、展示 主要工作流程如下所示: 其中爬蟲獲取實時數據,並把數據實時傳輸到Linux本地文件夾中。 使用Flume實時監控該文件夾,如果發現文件內容變動則進行處理,將數據 ...
  • 存儲過程與函數 類似與Java的方法和C語言的函數 存儲過程概述 含義 一組經過預先編譯的SQL語句的封裝 執行過程:存儲過程預先存儲在MySQL伺服器上,客戶端發出命令後,伺服器可以把預先存儲好的SQL語句全部執行 好處 簡化操作,提高了SQL語句的通用性,減少開發程式員的壓力 減少操作中的失誤, ...
  • 作者:Álvaro Hernández 當技術決策人考慮在 Kubernetes 上部署資料庫時,面臨的第一個問題就是:“Kubernetes 有應對有狀態服務的能力嗎?”多年來的答案都是“不建議”,而且理由充分。畢竟,Kubernetes 最初的設計便是用於處理無狀態服務的容器編排。如今,有狀態服 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 視圖 常見的資料庫對象 視圖概述 為什麼使用視圖 可以幫助我們使用表中的部分數據,對其修改可以改變原來表中的值 可以簡化查詢 控制數據的訪問(許可權) 視圖的理解 視圖是一種虛擬表,本身不具有數據的,占用極少的記憶體 視圖建立在已有表的基礎上,我們可以視圖所依據的表叫做基表 視圖的創建和刪除只會影響視圖 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...