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

- 首先当然是硬件,在线业务型的场景下,计算资源基本是CPU为主;存储资源则各种类型都有,主要是IO吞吐、时延、安全性等各种考虑;网络资源公网、内网类型,时延、吞吐考虑等。
- 在硬件之上(软件定义计算/存储/网络资源),基本都会使用类似K8S,或商用VMWare之类,来更方便的使用硬件资源,
- 这层软件的核心一方面是抽象硬件资源,方便上层根据需求来使用硬件资源,以及同时根据需求来匹配找到合适的资源,例如最简单的排他规则等等;
- 另一方面则是充分的提升硬件资源的使用率,例如虚拟化技术、容器化技术的引入等
- 再往上,通常就是根据业务系统的架构、建设需求做的各种中间件的选型,这些中间件最重要的是为了降低业务系统的门槛,把一些通用的技术问题解决掉,例如
- 数据库解决OLTP类型的数据读写
- Dubbo之类的服务框架解决跨系统间的同步通信
- RocketMQ之类的消息中间件解决跨系统间的异步通信等。
-
这些中间件之上,通常就是业务系统本身了,这个就完全要根据业务需求来做相应的架构设计,并且通常都会需要跟随业务的发展来不断的迭代架构(从单体 --> 分布式 --> 异地多活,推荐 郭东白《架构思维:从程序员到CTO》
K8S(Kubernetes)
K8s 主要用于管理和编排容器化的应用程序,这里的编排如何理解?
在Kubernetes(简称K8s)的上下文中,“编排”指的是自动化 容器化应用程序的部署、管理、扩展和联网的过程。具体来说,它包括但不限于以下功能:
- 自动部署和更新容器化应用。
- 管理容器的生命周期,包括冗余容器的替换和故障转移。
- 控制容器的可用性和伸缩性,根据负载自动增加或减少容器实例的数量。
- 定义网络规则来控制服务之间的通信。
- 存储卷挂载等。
关于你的Java微服务应用“mabe”,以及其资源基线和POD分配情况,这里有一些概念需要澄清和建议:
-
资源基线:你提到的应用资源基线为8C-16G-60GB,意味着每个POD被配置为需要8个CPU核心、16GB内存以及可能的60GB存储空间。这种资源配置相对较高,确保了应用有足够的资源运行。
-
POD数量:你总共分配了10个POD。这意味着你的应用将并行运行10个实例,每个实例都有相同的资源配置。这样的设置非常适合于需要高可用性和/或水平扩展能力的应用场景,例如处理大量并发请求的服务。
-
优化建议:
- 资源优化:确保这些资源限制是基于实际需求设定的,而不是过度分配。可以考虑使用Kubernetes的Horizontal Pod Autoscaler (HPA) 根据实际负载动态调整POD的数量,这样可以在保证性能的同时优化成本。
- 健康检查:配置合适的liveness和readiness探针,以帮助Kubernetes了解何时重启一个POD或者何时将其加入到服务中,提高应用的稳定性和可靠性。
- 服务发现与负载均衡:利用Kubernetes的服务机制来实现内部的服务发现和外部的负载均衡,简化微服务架构中的网络配置。
通过这种方式,Kubernetes可以帮助你更有效地管理和扩展你的Java微服务应用,同时确保其高可用性和资源的有效利用。
在 Kubernetes 中,POD 并不是容器,而是 Kubernetes 的最小运行和管理单元。POD 和容器的关系类似于“容器组”与“容器”的关系。以下是详细解释:
1. POD 的定义(类似于“容器组”,如一个pod=一个应用容器 + 一个边车容器(运维、监控等))
POD 是 Kubernetes 中的最小调度单元,它封装了一个或多个 共享资源 的容器。具体来说:
- POD 是一个逻辑单元:它代表一组紧密相关的容器,这些容器共享相同的资源(如网络、存储、IP 地址等)。
- POD 的核心功能:为容器提供运行环境,并协调它们的生命周期、资源共享和通信。
2. 容器的定义
容器(Container)是 Docker 等容器化技术的核心概念:
- 容器是运行时的实体:它是镜像(Image)的实例,包含应用程序及其依赖。
- 容器的隔离性:每个容器运行在独立的命名空间中,具有独立的文件系统、进程空间等。
3. POD 与容器的区别
| 特性 | POD | 容器 |
|---|---|---|
| 抽象层级 | 更高层的抽象(Kubernetes 的核心概念)。 | 更底层的实现(Docker 等容器技术的实体)。 |
| 资源共享 | POD 内的容器 共享网络、存储卷(Volume)、IP 等资源(CPU和内存是独立的,通过cgroup隔离)。 | 容器本身是独立的,除非被封装在同一个 POD 中,否则不共享资源。 |
| 生命周期管理 | Kubernetes 直接管理 POD 的生命周期。 | Kubernetes 不直接管理容器,而是通过 POD 管理容器。 |
| IP 地址 | 每个 POD 有唯一的 IP 地址。 | 容器没有独立的 IP 地址(除非显式配置)。 |
| 通信方式 | POD 内的容器通过 localhost 通信。 |
跨 POD 的容器需要通过服务(Service)或 IP 地址通信。 |
| 资源类型 | POD 内是否共享 | 说明 |
|---|---|---|
| 网络(IP、端口) | ✅ 共享 | 所有容器共享同一个 IP 和端口空间,通过 localhost 通信。 |
| 存储卷(Volume) | ✅ 共享 | 容器通过挂载相同的 Volume 实现数据共享。 |
| CPU 和内存 | ❌ 独立 | 每个容器独立配置资源请求和限制,Kubernetes 通过 cgroups 进行隔离和限制。 |
4. 为什么需要 POD?
POD 的设计解决了以下问题:
- 资源共享:
- 同一个 POD 中的容器共享网络命名空间(IP 和端口),因此可以通过
localhost直接通信。 - 共享存储卷(Volume),方便数据传递或持久化。
- 同一个 POD 中的容器共享网络命名空间(IP 和端口),因此可以通过
- 简化管理:
- Kubernetes 以 POD 为单位进行调度、扩展、健康检查等操作,无需直接管理单个容器。
- 生命周期协调:
- 通过 Pause 容器(基础设施容器)管理 POD 的状态,确保 POD 内容器的一致性。
5. 你的场景分析
你提到:
- 每个 POD 的资源基线为 8C-16G-60GB,并部署了 10 个 POD。
- 问题:POD 是否就是容器?
答案:不是。你的每个 POD 实际上是一个容器组(可能只包含一个容器),但 Kubernetes 以 POD 为单位进行管理。例如:
- 如果你的 Java 微服务每个 POD 只运行一个容器(典型场景),那么每个 POD 就是一个容器的封装。
- 如果你的 POD 内运行多个容器(例如主容器 + 辅助容器),则这些容器共享同一个 POD 的资源。
6. 举个例子
假设你有一个 Java 微服务应用,部署在 Kubernetes 中:
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: mabe-pod 5 spec: 6 containers: 7 - name: java-app 8 image: your-java-image:latest 9 resources: 10 requests: 11 memory: "15Gi" # 显式配置了资源请求和限制(7.5C-15G),Kubernetes 会确保该容器的资源需求被满足。 12 cpu: "7.5" 13 limits: 14 memory: "15Gi" 15 cpu: "7.5" 16 - name: sidecar-container # 17 image: sidecar-image:latest # 未显示配置资源请求和限制,可能导致(资源争用、OOM等风险)
边车容器sidecar作用:
- 日志收集:使用Sidecar容器收集和转发应用程序的日志。
- 监控:通过Sidecar容器进行应用的性能监控和健康检查。
- 安全性:使用Sidecar容器实现服务之间的安全通信和访问控制
在一个POD中若某个容器未显示配置资源请求和限制可能导致,Kubernetes 允许容器不配置资源请求和限制,但这种行为可能导致以下问题:
- 资源争用:
sidecar-container可能会占用大量 CPU 或内存,影响java-app的性能。 - 调度风险:如果
java-app的资源请求(如8C-16G)占用了节点的大部分资源,而sidecar-container未配置资源请求,Kubernetes 调度器可能无法正确评估节点的可用资源,导致调度决策不合理。 - OOM Killer 风险:如果
sidecar-container没有内存限制,它可能因内存不足被节点的 OOM Killer 终止
显示配置资源请求和限制:
1 containers: 2 - name: java-app 3 resources: 4 requests: 5 memory: "16Gi" 6 cpu: "8" 7 limits: 8 memory: "16Gi" 9 cpu: "8" 10 - name: sidecar-container 11 image: sidecar-image:latest 12 resources: 13 requests: # 资源请求(Requests):确保 sidecar-container 的最小资源需求被满足 14 memory: "512Mi" 15 cpu: "100m" 16 limits: # 资源限制(Limits):防止 sidecar-container 占用过多资源,影响 java-app 17 memory: "1Gi" 18 cpu: "500m"
- POD:
mttt-pod是 Kubernetes 的最小管理单元。 - 容器:
java-app和sidecar-container是两个容器,它们共享同一个 POD 的网络和存储。
7. 总结
- POD ≠ 容器:POD 是 Kubernetes 的最小运行单元,容器是 POD 中的运行实体。
- POD 的作用:封装容器、协调资源、简化管理。
- 你的场景:10 个 POD 实际上是 10 个容器组(每个可能包含一个容器),Kubernetes 通过 POD 管理这些容器的生命周期和资源分配。
如果需要进一步优化资源或理解 POD 的调度策略,可以结合 Horizontal Pod Autoscaler(HPA) 或 资源限制(Resource Limits) 进行调整。
大数据场景的技术栈

- 硬件
- 软件定义计算/存储/网络资源(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
- 设计为内存计算,具备更低的延迟和更高的吞吐量,适用于实时数据流处理。
- 以数据流为中心,提供了灵活的窗口操作和时间管理功能,它能够处理有界(批处理)和无界(流处理)的数据集,实现了真正的流批一体化。
- 离线型(批处理,有边界数据集):Hadoop、Spark
- 数据库/存储(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
- Doris/StarRocks:Doris(之前也称为Apache Doris 或 Palo)和StarRocks实际上同源于一个项目。它们都是高性能、实时分析型、MPP(Massively Parallel Processing)架构的列式数据仓库系统;
- Hbase前面有介绍
- 工作台(批处理-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 是一个更好的选择。
离线批处理(mapreduce)
2.1 基本概念和数据流转流程
2.2 例子:单词计数
数据文件存储
MapReduce 计算过程
任务提交与资源分配
Map 阶段
Reduce 阶段
2.3 不好理解的概念:容器与分区
1. 关于任务容器以及和 K8s 容器对比、任务销毁的问题
(1)Map/Reduce 任务与容器的关系
(2)Map 和 Reduce 容器的区别
(3)任务容器的销毁
2. 关于中间文件分区操作的问题
(1)分区操作的目的和规则
(2)分区后中间文件的存储形式
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如何处理。
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
浙公网安备 33010602011771号