在线型业务/大数据场景/AI时代的技术栈

在线型业务的技术栈

  •  首先当然是硬件,在线业务型的场景下,计算资源基本是CPU为主;存储资源则各种类型都有,主要是IO吞吐、时延、安全性等各种考虑;网络资源公网、内网类型,时延、吞吐考虑等。
  • 在硬件之上(软件定义计算/存储/网络资源),基本都会使用类似K8S,或商用VMWare之类,来更方便的使用硬件资源,
    • 这层软件的核心一方面是抽象硬件资源方便上层根据需求来使用硬件资源,以及同时根据需求来匹配找到合适的资源,例如最简单的排他规则等等;
    • 另一方面则是充分的提升硬件资源的使用率,例如虚拟化技术、容器化技术的引入等
  • 再往上,通常就是根据业务系统的架构、建设需求做的各种中间件的选型,这些中间件最重要的是为了降低业务系统的门槛,把一些通用的技术问题解决掉,例如
    • 数据库解决OLTP类型的数据读写
    • Dubbo之类的服务框架解决跨系统间的同步通信
    • RocketMQ之类的消息中间件解决跨系统间的异步通信等。
  • 这些中间件之上,通常就是业务系统本身了,这个就完全要根据业务需求来做相应的架构设计,并且通常都会需要跟随业务的发展来不断的迭代架构(从单体 --> 分布式 --> 异地多活,推荐 郭东白《架构思维:从程序员到CTO》

大数据场景的技术栈

  • 硬件
  • 软件定义计算/存储/网络资源(Yarn)Yarn和K8S是两种不同的集群管理和调度系统,它们在管理资源和调度任务方面有着不同的设计目标和应用场景。,的区别如下:
    • YARN 的设计重点是对大数据处理作业(如批处理、交互式处理和流处理)的优化。它有一个中心的资源管理器(ResourceManager)管理着分布在集群的所有计算资源,以及多个节点管理器(NodeManager),运行在集群的每个节点上。YARN 不具备容器原生支持,它通常管理的是进程级的应用程序
    • Kubernetes 是一个开源的容器编排系统,用于自动部署、扩展和管理容器化应用程序。
      它具有强大的容器支持和原生云环境的集成,非常适合微服务架构和持续集成/持续部署(CI/CD)。
      Kubernetes 中没有“集群”一说,而是通过集群来管理运行各种容器化应用程序的资源,没有绑定特定的数据处理框架或技术栈。
      它包含一个主机(Master)组件,负责全局的调度和管理,以及多个工作节点(Worker Node),运行容器化应用程序。
      Kubernetes 通过 Pods 来管理容器,Pod 是 Kubernetes 应用部署的最小单元,可以包含一个或多个容器。

    • 应用生态系统:YARN 主要针对的是大数据生态系统(特别是 Hadoop 相关的框架),而 Kubernetes 设计用于广泛的容器化应用程序和服务。

    • 资源和任务管理:YARN 管理的是 Hadoop 集群资源,强调在这些资源上运行不同的数据处理作业;Kubernetes 管理的是容器级别的资源,它允许容器在分布式环境中灵活运行。

    • 架构和抽象级别:YARN 是以进程为单位进行资源管理,侧重于大数据任务,而 Kubernetes 是以容器为单位,侧重于应用服务的部署和管理。

    • 使用场景:YARN 常常用在大数据分析场景(Hadoop生态),比如运行 Spark、Hive 作业;Kubernetes 则广泛用于微服务架构的应用管理和云原生应用。

  • 计算引擎
    • 离线型(批处理,有边界数据集):Hadoop、Spark
      • Hadoop 的 MapReduce是一种编程模型,用于在 HDFS 上对数据进行批处理计算;更适合于容忍较长时间的批量数据处理任务。
      • Hadoop 的 MapReduce 技术在设计上面向磁盘,适用于延迟不敏感的用例
      • 补充Hadoop生态:
        • HDFS(分布式文件系统,用于存储大量数据)
        • MapReduce(编程模型和处理框架,用于在分布式环境中批量处理数据),
        • YARN(资源管理和任务调度)
        • Hive(SQL 类查询)数据仓库基础架构,提供了一个SQL-like interface(HiveQL)进行数据汇总、查询和分析
          • Hive 是一个构建在 Hadoop 上的数据仓库框架,用于提供数据摘要、查询以及分析。Hive 允许用户用类似 SQL 的语言进行数据查询,这种语言被称为 HiveQL(Hive Query Language)。通过将 HiveQL 语句转换成 MapReduce、Tez 或 Spark 作业,Hive 使得 SQL 开发人员可以不必了解 Java 或底层的数据处理技术就能查询大规模数据集。
          • OLAP数据库和Hive区别:OLAP数据库(如Doris/StarRocks/阿里的adb、holegres)和Hive都被用于数据分析和决策支持(OLAP场景),但它们在设计、功能和最佳使用场景方面存在差别
            • OLAP数据库:被设计来执行快速的数据分析和复杂的查询操作(如优化了聚合操作例如求和、计数、平均值等),它通常用于多维数据分析(如数据立方体分析) (提供实时到近实时的查询性能,如对存储的数据执行快速、复杂的分析查询,Doris比Hbase 可能更适合
            • Hive虽然可以用来进行数据仓库任务,Hive更多是用于处理大数据集的批量数据分析和数据挖掘任务。与OLAP数据库相比它的查询性能可能不够快,特别是在交互式查询的上下文中(但是在大规模批量数据处理有优势)。
        • HBase(NoSQL 数据库)
          • Bigtable不是一个产品,而是Google公司在一篇论文中描述的一个分布式存储系统概念,用于管理结构化数据的可扩展性;HBase被设计成为Bigtable的开源等价物
          • Hbase开源的非关系型分布式数据库,它构建在Hadoop之上,特别是利用了HDFS作为其底层存储
          • 它的数据模型列族导向的,这意味着它特别适合于访问数据的特定列,对于稀疏数据表格也非常高效。
          • 通常用作在线事务性数据库(OLTP场景/系统)和作为实时查询的、大型数据集的存储和处理平台。(如 处理高速、随机的读写访问
        • OpenTSDB(Open time series data base) 是一个开源的、可扩展的时间序列数据库,它基于Hadoop的HBase构建。时间序列数据库主要用于存储和查询随时间变化的数据点,这类数据通常包括服务器监控指标(如CPU使用率、内存使用情况)、传感器数据等
        • Zookeeper(集中服务,为分布式应用提供一致性和协调)
        • Kafka(分布式流处理平台,常用于建立实时数据管道和流式应用程序等)
        • Apache Cassandra是一个分布式NoSQL数据库管理系统(用于存储结构化数据并提供查询功能),旨在处理跨多个商品服务器的大量数据,提供高可用性和无单点故障。
        • Apache Flume是一种高效、可靠的服务,用于收集、聚合和移动大量的日志数据(专注于日志数据的收集与传输)。它具有简单的配置方式,能够灵活地从各种来源采集日志,并将其传输至指定的目标。

        • Spark(作为MapReduce的替代,提供高速的数据处理和带有机器学习库的API):

          Spark 的初衷是解决MapReduce在迭代计算和交互式查询等方面的局限性。MapReduce每次执行任务都需要读写HDFS(Hadoop分布式文件系统),这导致了较高的I/O开耗时。而Spark通过引入内存计算模型,能够在内存中缓存中间结果,大大提高了数据处理速度,尤其是在需要多次操作同一份数据集的情况下。

          此外,Spark不仅仅局限于批处理作业,它还支持流处理(Spark Streaming 是 Spark 中的一个组件,专门用于实时数据流处理)、图计算、机器学习等多种工作负载,形成了一个统一的数据处理平台。这种多功能性使得用户可以在同一个平台上完成不同类型的数据分析任务,而无需切换不同的工具或框架,从而简化了开发流程并提高了效率。

        • Storm(实时大数据处理框架,跟flink是竞品)
    • 实时型(流计算,无边界数据集):Flink、Storm
      • 设计为内存计算,具备更低的延迟和更高的吞吐量,适用于实时数据流处理。
      • 以数据流为中心,提供了灵活的窗口操作和时间管理功能,它能够处理有界(批处理)和无界(流处理)的数据集,实现了真正的流批一体化。
  • 数据库/存储(Hbase、OLAP数据库 (如Doris/StarRocks/阿里的adb、holegres))
    • Hbase前面有介绍
      • 底层 用 HDFS作为存储
      • 场景再强调一下:通常用作在线事务型数据库(OLTP场景/系统)和作为实时查询的、大型数据集的存储和处理平台。(如 处理高速、随机的读写访问)
      • HBase虽然被设计为一个非关系型数据库,它也被广泛应用于需要快速随机访问 大量数据的场景中,包括某些类型的OLTP应用
        尽管HBase不直接支持SQL或提供传统的关系型数据库特性如复杂的事务管理,但它通过一些机制来满足特定类型的OLTP需求:

        强一致性读写:对于单行的操作可以提供类似于ACID事务的支持。
        版本控制:允许对同一单元格的数据进行多版本存储,这对于历史数据分析很有用。
        Region分割:自动将表分成多个region以便于并行处理和负载均衡。

        因此,当说HBase“用作在线事务型数据库”时,更多是指它在大规模数据集上的实时读写能力以及其在特定应用场景下的表现,而不是说它完全替代了传统的RDBMS所有功能。例如,在社交网络、即时消息服务等领域,HBase因其高效的数据检索能力和良好的扩展性而成为一种受欢迎的选择。

    • OLAP数据库:
      • 底层不一定是 HDFS 存储(如 Doris 主要以本地文件系统(如 ext4、xfs)存储其数据,也支持导入各种数据源 如 HDFS)
      • 场景再强调一下:提供实时到近实时的查询性能,如对存储的数据执行快速、复杂的分析查询,Doris比Hbase 可能更适合
      • 几种常见的OLAP数据库
        • Doris/StarRocks:Doris(之前也称为Apache Doris 或 Palo)和StarRocks实际上同源于一个项目。它们都是高性能、实时分析型、MPP(Massively Parallel Processing)架构的列式数据仓库系统;
          • Doris是Baidu开源的
          • StarRocks是由Doris衍生而来的商业化产品,提供更多的企业级特性和优化,以及更高性能的查询处理能力
        • 阿里的adb、hologres
  • 工作台(批处理-maxcompute/流处理-flink /OLAP数据库-hologres等):大数据的场景比较特殊的一个地方是通常需要面向数据分析师等角色使用,这个需要一个工作平台,像阿里云的dataworks之类的。

AnalyticDB和Hologress关系(都是实时数仓/OLAP数据库):

ADB是阿里云数据库事业部团队提供的云原生数据仓库AnalyticDB MySQL版(放弃了对事务的支持),简称ADB(历史上也叫ADS)

Hologres是阿里云计算平台事业部出品,来自Holographic全息的+Postgress(PostgreSQL,MySQL 是一个纯粹的关系数据库。而另一方面,PostgreSQL 是一个对象关系数据库。这意味着在 PostgreSQL 中,您可以将数据存储为具有属性的对象)。

一款是AnalyticDB for MySQL,一款是Hologres。ADB是阿里云数据库事业部团队提供的云原生数据仓库AnalyticDB MySQL版,是阿里巴巴自主研发的海量数据实时高并发在线分析云计算服务。
Hologres是阿里云计算平台事业部提供的一款全面兼容PostgreSQL协议并与大数据生态无缝打通的实时交互式分析产品。

从实际业务场景出发,两者的主要区别有以下几点:

1)与MaxCompute的打通性

Hologres:与MaxCompute打通,可以直接通过外部表读取MaxCompute数据进行查询分析,无需存储就能查询。

ADB:能加速查询MaxCompute,提供复杂交互式分析、实时混合数据仓库等多种场景。

2)成本方面

从我们每年ADB和Hologres的的单价上对比,Hologres成本相比ADB略微低。

3)灵活度

均能满足OLAP场景,Hologres兼容兼容PostgreSQL生态,ADB坚兼容MySQL协议,均能满足实时和离线批量的数据导入和分析。

4)性能
对于需要处理大量随机查询的场景,AnalyticDB 是一个更好的选择。而对于需要处理大规模的数据集的场景,Hologres 是一个更好的选择。

Apache Flink 

3.1 数据源定义(订阅外部数据源的topic)

在 Apache Flink 的 SQL API 中,CREATE TABLE 语句用于定义表的结构,包括其元数据列。Flink SQL 允许用户在表定义中包括一系列的列属性,这些属性不仅仅限于传统的数据列,还包括一些特殊的元数据列,用以提供额外的信息,如时间戳、水印等,对于处理时间敏感的流数据尤为重要。

以下是一个简化的 CREATE TABLE 语句示例,展示了如何在 Flink SQL 中定义包含元数据列的表:

 1 CREATE TABLE my_table (
 2    -- 数据列
 3    id INT,
 4    name STRING,
 5  
 6    -- 元数据列
 7    event_time TIMESTAMP(3) METADATA FROM 'timestamp', -- 对应源数据的时间戳字段
 8    watermark FOR event_time AS event_time - INTERVAL '5' SECOND -- 设置水印,以支持事件时间的窗口操作
 9  
10    -- 表的连接器、格式化器、以及其它配置信息
11  ) WITH (
12    'connector' = 'kafka', -- 使用 Kafka 连接器
13    'topic' = 'my_topic',
14    'format' = 'json', -- 数据格式为 JSON
15    -- 更多的 Kafka 连接器设置...
16  );

 

在这个例子中,除了常规的数据列 id 和 name 外,

第7行解释:还定义了一个名为 event_time 的元数据列,该列用来从数据源(如 Kafka 消息的某个字段)中提取时间戳信息。

  • 1. event_time TIMESTAMP(3):这定义了一个名为 event_time 的列,其数据类型是带有3位小数秒精度的时间戳(TIMESTAMP)。这意味着它可以精确到毫秒。
  • 2. METADATA FROM 'timestamp':这一部分说明了 event_time 列的实际值是从消息元数据中获取的,而不是直接包含在消息体内的数据字段里。这里的 'timestamp' 是指Kafka消息的一个特殊属性头信息键名,通常用于存储事件发生的确切时间。Flink会从每条记录的消息元数据中提取这个键对应的值作为 event_time 的值。

 

第8行解释:此外,还利用 event_time 列设置了水印策略(watermark),这对于时间窗口操作至关重要,因为它允许系统处理乱序事件,并为事件时间提供一定的延迟容忍度。

  • 1. watermark FOR event_time:这表示我们正在为 event_time 列设置一个水印(Watermark)。水印是流处理系统用来处理乱序事件的一种机制,它允许系统确定某个时间点之后不会再有更早的数据到达。
  • 2. AS event_time - INTERVAL '5' SECOND:这部分定义了如何生成水印。具体来说,每个事件的水印值等于该事件的 event_time 减去5秒。这意味着系统假设所有迟到的数据最多晚于它们的真实事件时间5秒钟。一旦处理到了某个特定时间点的水印,任何比这个水印时间还要早的数据都将被视为不再可能到达,并且可以安全地进行窗口计算等操作而不必等待更多延迟数据。

 

请注意,实际的元数据列和配置参数可能会根据你使用的具体连接器(如 Kafka、JDBC 等)和数据格式(如 JSON、Avro 等)有所不同。因此,了解具体连接器和格式化器的文档是非常重要的。

最后,WITH 子句中的属性用于指定表的物理数据存储相关的配置,如数据来源是 Kafka 时的主题(topic)、数据格式(format)等信息。这部分配置确保了 Flink 能够正确地读写外部系统的数据。

3.2 结果写入外部系统的topic

在 Apache Flink 中,使用 CREATE TABLE 语句写入外部系统是通过定义一个动态表连接到外部存储或消息系统来实现的。这个表可以连接到各种外部系统,比如 Kafka、Elasticsearch、JDBC 数据库等。通过定义这样的表,Flink 可以从这些外部系统读取数据作为输入流,也可以将数据输出到这些系统。

下面是一个简单示例,展示如何使用 CREATE TABLE 语句在 Flink SQL 中定义一个表来写入一个外部系统(假设是 Kafka):

写入 Kafka 示例

 1 CREATE TABLE kafka_output_table (
 2   id INT,
 3   name STRING,
 4   event_time TIMESTAMP(3),
 5   WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND
 6 ) WITH (
 7   'connector' = 'kafka', -- 使用 Kafka 连接器
 8   'topic' = 'output_topic', -- Kafka 主题名称
 9   'properties.bootstrap.servers' = 'localhost:9092', -- Kafka 集群地址
10   'format' = 'json', -- 数据格式
11   'sink.parallelism' = '1' -- 设置 sink 的并行度
12 );

 

在这个示例中,我们定义了一个名为 kafka_output_table 的表,它指定了要写入 Kafka 主题 output_topic 的数据结构。通过 WITH 子句提供连接器配置、Kafka 服务器的地址、以及数据的格式化方式。

写入操作

定义了输出表之后,你可以使用 INSERT INTO 语句将数据写入这个表(即写入外部系统):

1 INSERT INTO kafka_output_table
2 SELECT 
3   id, 
4   name, 
5   event_time 
6 FROM 
7   input_table; -- 假设已经定义了一个名为 input_table 的输入表

 

这个 INSERT INTO 语句会将 input_table 表中的数据写入到 kafka_output_table进而写入到配置的 Kafka 主题中

注意事项

  • 确保你选择的连接器(比如 Kafka、Elasticsearch)和你希望使用的数据格式(比如 JSON、Avro)已经在 Flink 中支持。
  • 外部系统的配置如 Kafka 主题、JDBC 的数据库连接细节是在 WITH 子句中指定的,这些配置会根据连接的系统和使用场景而有所不同。
  • 请参考 Flink 官方文档以了解更多与具体连接器相关的配置选项和示例。

Apache Flink 的强大之处在于它提供了统一的批处理和流处理模型,使得处理时间驱动的数据流与传统的批量数据处理得以无缝集成,从而可以灵活地满足各种复杂数据处理场景的需求。

 

3.3 水印和滚动窗口

Apache Flink 中的水印(Watermarks)是一种机制,用于处理事件时间(Event Time)中的乱序事件,以及在流数据处理中为窗口操作提供正确的时间语义。水印允许 Flink 对事件数据进行时间标记,以确定何时可以认为某个时间点的所有数据都已到达,从而可以对这些数据进行处理或聚合操作。

下面是一个使用水印的简单示例,假设我们有一个流式数据源,它不断地发送带有时间戳的事件数据,我们想要按照事件时间处理这些数据,并且使用基于时间的窗口进行一些聚合操作,比如计算每5分钟内的事件数量。

在定义表时引入水印:

 1 CREATE TABLE events (
 2   id INT,
 3   eventName STRING,
 4   eventTime TIMESTAMP(3), -- 事件时间字段
 5   WATERMARK FOR eventTime AS eventTime - INTERVAL '5' SECONDS -- 定义水印策略
 6 ) WITH (
 7   'connector' = 'kafka', -- 示例使用 Kafka 连接器
 8   'topic' = 'event_topic',
 9   'properties.bootstrap.servers' = 'localhost:9092',
10   'scan.startup.mode' = 'earliest-offset',
11   'format' = 'json',
12   ...
13 );

在这个示例中,WATERMARK FOR eventTime AS eventTime - INTERVAL '5' SECONDS 表示水印被定义为 事件时间戳 减去5秒。意味着在观察到某个事件时间戳后系统会等待5秒,以接收可能延迟到达的数据。这样,即使数据到达的顺序有所乱序,系统也能够基于事件的时间戳正确地处理它们。

接下来,我们可以定义一个窗口查询,来计算每5分钟内的事件数量

1 SELECT
2   TUMBLE_START(eventTime, INTERVAL '5' MINUTE) as windowStart,
3   COUNT(*) as eventCount
4 FROM events
5 GROUP BY TUMBLE(eventTime, INTERVAL '5' MINUTE);

在上述查询中,TUMBLE 是一个内置的窗口函数,用于基于时间对事件进行分组。这里它被配置为创建长度为5分钟的滚动窗口。窗口的开始时间通过 TUMBLE_START 函数获得,同时我们对每个窗口内的事件数进行计数。

利用水印,即使事件以乱序的方式到达,Flink也能保证窗口操作的正确性,因为它会根据水印和事件时间来触发窗口的计算,确保所有被认为属于该窗口的事件都已被处理。

总结,Flink中使用水印可以优雅地处理乱序事件流,保证时间窗口操作的准确性,非常适用于实时数据分析和流处理的场景。

 

3.4 水印和滑动窗口

在 Apache Flink 中,滑动窗口(Sliding Window)是一种时间窗口,它以固定的时间间隔(滑动间隔)在数据流上滑动,并为每个窗口期间内的数据执行聚合操作。与滚动窗口(Tumbling Window)相比,滑动窗口允许窗口之间有重叠,因此它非常适用于需要频灭聚合和分析的场景。

以下是结合使用水印(Watermarks)和滑动窗口的一个简单例子。在这个例子中,我们将计算过去10分钟内,每隔1分钟的事件数量,这意味着我们的窗口大小是10分钟滑动间隔是1分钟。同时,我们使用水印来处理可能出现的乱序事件,确保窗口的正确触发。

首先,定义一个带有时间戳和水印的数据源表:跟3.3一样,

数据源定义中,我们设置了水印策略。在这个策略中,水印设置为事件时间戳减去五秒,这意味着系统或许等待最多五秒获取晚于事件时间戳的数据。

 

然后,执行一个窗口聚合查询:

1 SELECT 
2   window_start, 
3   window_end, 
4   COUNT(*) AS event_count
5 FROM TABLE(
6   TUMBLE(TABLE event_stream, DESCRIPTOR(event_timestamp), INTERVAL '10' MINUTES // 窗口大小 , INTERVAL '1' MINUTES // 滑动间隔)
7 )
8 GROUP BY window_start, window_end;

 

在这个查询中:

  • 使用了 TUMBLE 函数的一个变体,它接收一个额外的参数来指定滑动间隔。这里,窗口的长度(INTERVAL '10' MINUTES)是10分钟,滑动间隔(第四个参数INTERVAL '1' MINUTES)是1分钟。
  • 我们按事件时间戳进行分组,并为每个窗口计算事件数量。
  • window_start 和 window_end 表示窗口的起始和结束时间

请注意,Flink SQL 中的滑动窗口聚合查询语法可能会根据版本有所不同。确认在你的 Flink 环境中使用正确的语法非常重要。

水印机制以及滑动窗口的应用,允许我们在保证窗口计算准确性的同时,灵活地处理乱序事件和延迟数据,这对实时数据处理尤为重要。

3.3 水印和滑动窗口(例子还不错)

【背景和例子】
假设我们正在处理一个实时的网页点击流数据,用户的点击事件包含时间戳和用户ID。我们的目标是计算每5分钟内,每个用户的点击次数。水印的时间戳定义为事件时间戳的最大值 - 1s。假设滑动窗口  大小为5 分钟,每次滑动步长为1分钟,即窗口1:[2023-10-08 10:00 , 2023-10-08 10:05)、窗口2:[2023-10-08 10:01 , 2023-10-08 10:06)

例如,某个用户的事件可能因网络延迟而晚于其他事件到达。以下是时间戳和用户ID的几个事件示例:

事件ID       时间戳                    用户ID
---------------------------------
1              2023-10-08 10:01     A
2             2023-10-08 10:03     B
3             2023-10-08 10:04     A
4             2023-10-08 10:05     B
5             2023-10-08 10:06     C
6             2023-10-08 10:02     A

【问题】请根据上述背景和例子,详细说明下每个事件到达时:水印、滑动窗口、点击次数的计算和更新情况,乱序情况下flink如何处理。

 

一、水印的定义及作用

 

水印在这个场景中定义为事件时间戳的最大值减去 1 秒。其作用是衡量事件时间的进度,帮助 Flink 确定在某个时间点之前的事件是否都已到达,以便触发窗口的计算。

 

二、滑动窗口的定义及特点

 

滑动窗口大小为 5 分钟,每次滑动步长为 1 分钟。这意味着窗口会随着时间的推移不断向前滑动,对不同时间段内的数据进行处理。在这个问题中,有多个滑动窗口,如窗口 1 为 [2023 - 10 - 08 10:00, 2023 - 10 - 08 10:05),窗口 2 为 [2023 - 10 - 08 10:01, 2023 - 10 - 08 10:06) 等。

 

三、每个事件到达时的计算和更新情况

 

  1. 事件 1:时间戳为 2023 - 10 - 08 10:01,用户 ID 为 A
    • 水印计算:此时只有这一个事件,最大时间戳为 2023 - 10 - 08 10:01,所以水印时间戳为 2023 - 10 - 08 10:00。
    • 窗口计算:
      • 窗口 1:事件 1 属于该窗口。为用户 A 在窗口 1 中创建一个计数器,并将其点击次数加 1。此时窗口 1 中用户 A 的点击次数为 1。
      • 窗口 2:事件 1 也在窗口 2 的时间范围内,但目前窗口 2 的计算暂未开始。记录用户 A 在窗口 2 中有一次潜在点击(暂不增加计数器)。
  2. 事件 2:时间戳为 2023 - 10 - 08 10:03,用户 ID 为 B
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:03,水印时间戳更新为 2023 - 10 - 08 10:02。
    • 窗口计算:
      • 窗口 1:事件 2 属于该窗口。为用户 B 在窗口 1 中创建一个计数器,并将其点击次数加 1。此时窗口 1 中用户 B 的点击次数为 1,用户 A 的点击次数仍为 1。
      • 窗口 2:事件 2 也在窗口 2 内,但窗口 2 未开始计算。记录用户 B 在窗口 2 中有一次潜在点击(暂不增加计数器)。
  3. 事件 3:时间戳为 2023 - 10 - 08 10:04,用户 ID 为 A
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:04,水印时间戳更新为 2023 - 10 - 08 10:03。
    • 窗口计算:
      • 窗口 1:事件 3 属于该窗口。用户 A 在窗口 1 中的点击次数再加 1。此时窗口 1 中用户 A 的点击次数为 2,用户 B 的点击次数为 1。
      • 窗口 2:事件 3 在窗口 2 内,但窗口 2 未开始计算。记录用户 A 在窗口 2 中有一次潜在点击(暂不增加计数器)。
  4. 事件 4:时间戳为 2023 - 10 - 08 10:05,用户 ID 为 B
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:05,水印时间戳更新为 2023 - 10 - 08 10:04。
    • 窗口计算:
      • 窗口 1:该窗口即将关闭,不再接收新事件。此时窗口 1 中用户 A 的点击次数为 2,用户 B 的点击次数为 1。
      • 窗口 2:事件 4 在窗口 2 的时间范围内,但此时窗口 2 未开始计算。记录用户 B 在窗口 2 中有一次潜在点击(暂不增加计数器)。
  5. 事件 5:时间戳为 2023 - 10 - 08 10:06,用户 ID 为 C
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:06,水印时间戳更新为 2023 - 10 - 08 10:05。
    • 窗口计算:
      • 由于最新产生的水印(2023 - 10 - 08 10:05)等于窗口 2 的结束时间(2023 - 10 - 08 10:06 的前一秒),根据假设(最新产生的水印大于或等于某个窗口的结束时间时,触发该窗口的计算;随着事件的不断到来,水印时间不断更新。当水印时间戳达到或超过 2023 - 10 - 08 10:06(窗口 2 的结束时间)时,Flink 会触发窗口 2 的计算。),触发窗口 2 的计算
      • 检查之前记录的潜在点击
        • 用户 A 在窗口 2 中有两次点击(来自事件 1 和事件 3),所以用户 A 的点击次数加 2,现在为 2。
        • 用户 B 在窗口 2 中有两次点击(来自事件 2 和事件 4),所以用户 B 的点击次数加 2,现在为 2。
        • 用户 C 的点击次数为 1(新事件)。
  6. 事件 6:时间戳为 2023 - 10 - 08 10:02,用户 ID 为 A
    • 水印计算:最大时间戳仍为 2023 - 10 - 08 10:06(因为事件 6 是迟到事件,最大时间戳未被更新),水印时间戳保持为 2023 - 10 - 08 10:05。
    • 窗口计算:
      • 窗口 1:已关闭,不再考虑
      • 窗口 2:事件 6 属于该窗口。用户 A 在窗口 2 中的点击次数再加 1。此时窗口 2 中用户 A 的点击次数为 3,用户 B 的点击次数为 2,用户 C 的点击次数为 1。

 

四、乱序情况下 Flink 的处理方式

 

在这个场景中,如果事件以乱序的方式到达,Flink 依靠水印机制来处理。当一个迟到的事件到达时,如事件 6,Flink 会根据当前的水印时间来判断该事件是否属于已经处理过的窗口。如果迟到事件的时间戳小于当前水印时间,就像事件 6 的时间戳 2023 - 10 - 08 10:02 小于水印时间 2023 - 10 - 08 10:05,Flink 会将其标记为迟到事件。

 

对于迟到事件,Flink 可以有不同的处理策略。一种常见的策略是将迟到事件放入侧输出流,以便后续分析或处理。另一种策略是更新已经计算过的窗口结果,但这可能会带来额外的计算开销和复杂性。具体的处理方式取决于应用的需求和性能考虑。

 

综上所述,通过水印机制和滑动窗口的结合,以及明确的触发条件假设,Flink 能够在处理实时网页点击流数据时,有效地应对乱序事件,确保每 5 分钟内每个用户的点击次数计算的准确性。同时,随着窗口的不断滑动,能够持续地对不同时间段的数据进行处理。
 

3.4 水印和滚窗口(例子还不错)

 同上述例子,改为滚动窗口,如窗口 1 为 [2023 - 10 - 08 10:00, 2023 - 10 - 08 10:05),窗口 2 为 [2023 - 10 - 08 10:06, 2023 - 10 - 08 10:10) 等)
一、水印的定义及作用

 

水印在这个场景中定义为事件时间戳的最大值减去 1 秒。其作用是衡量事件时间的进度,帮助 Flink 确定在某个时间点之前的事件是否都已到达,以便触发窗口的计算。

 

二、滚动窗口的特点

 

滚动窗口是固定大小且不重叠的窗口。在这个问题中,窗口大小为 5 分钟,如窗口 1 为 [2023 - 10 - 08 10:00, 2023 - 10 - 08 10:05),窗口 2 为 [2023 - 10 - 08 10:06, 2023 - 10 - 08 10:10) 等。

 

三、每个事件到达时的计算和更新情况

 

  1. 事件 1:时间戳为 2023 - 10 - 08 10:01,用户 ID 为 A
    • 水印计算:此时只有这一个事件,最大时间戳为 2023 - 10 - 08 10:01,所以水印时间戳为 2023 - 10 - 08 10:00。
    • 窗口计算:
      • 窗口 1:事件 1 属于该窗口。为用户 A 在窗口 1 中创建一个计数器,并将其点击次数加 1。此时窗口 1 中用户 A 的点击次数为 1。
      • 窗口 2 及其他后续窗口:由于时间未到,这些窗口暂不考虑。此时这些窗口中用户 A 的点击次数为 0。
  2. 事件 2:时间戳为 2023 - 10 - 08 10:03,用户 ID 为 B
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:03,水印时间戳更新为 2023 - 10 - 08 10:02。
    • 窗口计算:
      • 窗口 1:事件 2 属于该窗口。为用户 B 在窗口 1 中创建一个计数器,并将其点击次数加 1。此时窗口 1 中用户 B 的点击次数为 1,用户 A 的点击次数仍为 1。
      • 窗口 2 及其他后续窗口:由于时间未到,这些窗口暂不考虑。此时这些窗口中用户 B 的点击次数为 0。
  3. 事件 3:时间戳为 2023 - 10 - 08 10:04,用户 ID 为 A
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:04,水印时间戳更新为 2023 - 10 - 08 10:03。
    • 窗口计算:
      • 窗口 1:事件 3 属于该窗口。用户 A 在窗口 1 中的点击次数再加 1。此时窗口 1 中用户 A 的点击次数为 2,用户 B 的点击次数为 1。
      • 窗口 2 及其他后续窗口:由于时间未到,这些窗口暂不考虑。此时这些窗口中用户 A 的点击次数为 0。
  4. 事件 4:时间戳为 2023 - 10 - 08 10:05,用户 ID 为 B
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:05,水印时间戳更新为 2023 - 10 - 08 10:04。
    • 窗口计算:
      • 窗口 1:该窗口即将关闭,不再接收新事件。此时窗口 1 中用户 A 的点击次数为 2,用户 B 的点击次数为 1。
      • 窗口 2 及其他后续窗口:由于时间未到,这些窗口暂不考虑。此时这些窗口中用户 B 的点击次数为 0。
  5. 事件 5:时间戳为 2023 - 10 - 08 10:06,用户 ID 为 C
    • 水印计算:最大时间戳变为 2023 - 10 - 08 10:06,水印时间戳更新为 2023 - 10 - 08 10:05。
    • 窗口计算:
      • 窗口 1:已关闭,不再考虑。
      • 窗口 2:事件 5 属于该窗口。为用户 C 在窗口 2 中创建一个计数器,并将其点击次数加 1。此时窗口 2 中用户 C 的点击次数为 1。
  6. 事件 6:时间戳为 2023 - 10 - 08 10:02,用户 ID 为 A
    • 水印计算:最大时间戳仍为 2023 - 10 - 08 10:06(因为事件 6 是迟到事件,最大时间戳未被更新),水印时间戳保持为 2023 - 10 - 08 10:05。
    • 窗口计算:
      • 窗口 1:已关闭,不再考虑。
        • 若 假设可以将迟到事件放入已关闭窗口重新计算。  窗口 1:虽然已关闭,但重新纳入事件 6 进行计算。用户 A 在窗口 1 中的点击次数再加 1,现在为 3。对于乱序事件,Flink 需要额外的逻辑来处理迟到事件并将其放入已关闭的窗口重新计算。这可能会带来一些复杂性,例如需要维护已关闭窗口的状态以便重新计算,同时也可能会影响性能,因为需要对已关闭的窗口进行额外的操作。
        • 在一般情况下,对于滚动窗口,当一个事件迟到且其对应的窗口已经关闭通常不会将其放入已关闭的窗口重新计算
      • 窗口 2:事件 6 不属于该窗口,因为其时间戳小于窗口 2 的起始时间。所以窗口 2 中用户 A 的点击次数不变,仍为 0。

 

四、乱序情况下 Flink 的处理方式

 

在滚动窗口的情况下,对于乱序事件的处理相对简单。如果一个事件迟到,且其时间戳不在当前正在处理的窗口范围内,那么这个事件通常会被丢弃或者放入侧输出流以便后续分析。例如事件 6,由于其时间戳小于窗口 2 的起始时间,所以不会被纳入窗口 2 的计算。

 

综上所述,在使用滚动窗口处理实时网页点击流数据时,每个窗口独立计算,不重叠的特点使得计算更加清晰明确。通过水印机制,可以确保窗口在合适的时间进行计算,同时对于乱序事件也能根据窗口的定义进行恰当的处理。

AI时代的技术栈(后面补充)

  •  硬件:CPU --> GPU
  • 软件定义计算/存储/网络资源:怎么管理好GPU卡,去调度好GPU的池子,做好GPU的虚拟化等
  • 计算引擎&数据库:Ray、Milvus等
    • Ray 是一个开源的分布式计算框架,用于构建大规模的机器学习应用程序
    • 发Ray 是一个开源的分布式计算框架,用于构建大规模的机器学习应用程序。
      • 强大的并行处理能力:Ray 提供了简单的API,能够轻松地将串行代码并行化,支持多核CPU和GPU的计算资源。
      • 任务调度和执行:Ray 可以高效调度大量的小任务,这对于现代机器学习和AI应用特别重要。
      • 动态任务图执行:Ray 能够创建一个动态任务图,它将计算任务表示为图中的节点,这些任务可以并发执行。
      • Actor模型:Ray 支持类似 Erlang 的 Actor 模型,允许用户构建并行的,有状态的任务。
      • 内存对象存储:Ray 有内置的分布式对象存储,可以在工作节点之间共享大型数据对象而无需显式复制。
      • 轻量级:Ray 被设计成轻量级的,易于安装,快速启动。
      • 由于其效率和易用性,Ray 在机器学习社区中获得了很多支持,特别是与像 RLlib (强化学习库)和 Tune(超参数调优库,可以与多种机器学习框架集成(如 TensorFlow、PyTorch))这样的库结合使用。

    • 应用如
      • 模型训练与分布式深度学习:

        Ray 可以用于加速大规模的深度学习模型训练
        分布式计算能力允许将复杂的模型和大型数据集划分到多个处理单元(GPU或CPU)进行并行训练

      • 数据预处理和流水线:

        Ray 提供了强大的数据预处理功能,可以对大型数据集进行并行和异步预处理,从而为模型训练做准备。

      •  和RLlib (强化学习库)和 Tune(超参数调优库,可以与多种机器学习框架集成(如 TensorFlow、PyTorch))这样的库结合使用
    • Milvus 是一个开源的向量数据库,用于存储、索引和管理大规模的向量集合。它特别适合处理那些需要通过向量相似性搜索来检索信息的应用,例如图像识别和深度学习。

      •  

        强大的搜索能力:Milvus 支持多种相似性搜索算法,包括最近邻搜索(K-NN)和范围搜索等。
        高效的索引策略:Milvus 使用多种索引策略来优化不同规模数据集的搜索性能,如 IVF FLAT, IVF SQ8, HNSW 等。
        水平可伸缩:Milvus 设计用来支持水平扩展,它可在多个节点之间平衡存储和计算负载。

            

参考:AI时代的技术栈 https://mp.weixin.qq.com/s/cc1IrhTSbOyoTZ96VOikZw

 
 
 
 
 
 

posted on 2024-04-03 10:27  gogoy  阅读(44)  评论(0编辑  收藏  举报

导航