我们主要讨论使用 Apache Spark、Apache Kafka 和 ClickHouse 的实时数据处理架构。
什么是实时数据处理架构?
实时数据处理架构涉及实时/近实时处理数据。它在数据生成后立即处理数据并提供见解。
比方说,我们正在获取有关用户如何使用我们的 Web 应用程序的事件(数据)。为了简单起见,我们会收集用户单击内容、将鼠标悬停在内容上等时的事件。使用这些收集的事件,我们希望为单个用户提供定制的体验。为了提供定制体验,我们希望在收集的事件生成后立即对其进行处理。处理延迟会影响用户体验。理想情况下,每当用户与我们的网络应用程序交互时,我们都会立即处理收集到的数据并提供定制体验。
如果您不了解任何一个术语(Apache Spark | Apache Kafka | ClickHouse | Amazon S3),我建议您从下面的链接中学习该教程。
Apache Spark : Apache Spark 是一个分布式计算框架。为了简单起见,通俗地说,假设我们有一个非常大的数据集,我们想要对其进行一些操作(比如,我们想要计算特定单词的出现次数)。为了执行此操作,我们有一组机器。我们决定将数据集分割成子集,并将子集分布到机器上来执行我们的操作。我们这样认为,我们可以有效地利用可用的机器。但跨机器维护子集很复杂。如果有一个框架可以处理跨机器的数据集分割,并处理一致性和容错性,该怎么办?是的,Apache Spark 提供了这样一个框架。
Apache Kafka:Apache Kafka 是一个消息流组件。它提供了一个高吞吐量、低延迟的平台来传输数据。
Clickhouse: ClickHouse 是一个开源的面向列的 DBMS。使用基于 SQL 的查询生成分析报告非常有用。此外,ClickHouse 还配备了 Kafka 引擎,我们可以使用它从 Kafka 主题中读取/写入数据。
Amazon S3: Amazon S3 是一种对象存储服务,是 AWS 生态系统的一部分。它提供了高度可用且可扩展的存储服务。
先决条件:
要实现此架构,我们必须安装 Apache Spark、Apache Kafka 和 ClickHouse。
实时数据处理架构:
在此架构中,ClickHouse 被视为单一事实来源。其他服务/组件将数据存储到 ClickHouse 中。
- 每当应用程序向 ClickHouse 表中插入一条记录时,插入的记录将由 ClickHouse Kafka Engine 推送到 Kafka 中。(请参阅架构图中的步骤 A)。
- Apache Spark 使用 Kafka-Spark 连接器从 Kafka 传输实时数据。利用这个数据流,Spark可以进行实时处理。(参考步骤B)
- 处理完成后,会将结果存储到S3存储桶中。(参考步骤C)
该架构的实现涉及五个步骤:
- Kafka-Apache Spark 连接器设置。
- Apache Spark-Amazon S3 连接器设置。
- 配置 ClickHouse-Kafka。
- 收听 Apache Spark 中的 Kafka 主题。
- 将结果存储到 Amazon S3 中。
Kafka-Apache Spark 连接器设置:
要监听 Kafka 主题,我们需要以下 jar。这些 jar 将为 Apache Spark 提供监听 Kafka 主题的接口。
此外,Apache Spark 能够监听多个 Kafka 主题。
- Spark-sql-kafka-0–10_2.12–3.1.2.jar
- Spark-token-provider-kafka-0–10_2.12–3.1.2.jar
- kafka-clients-3.0.0.jar
- commons-pool2–2.11.1.jar
将这些 jar 复制到 $SPARK_HOME/jars/ 文件夹中。
wget https://repo1.maven.org/maven2/org/apache/spark/spark-sql-kafka-0-10_2.12/3.1.2/spark-sql-kafka-0-10_2.12-3.1.2 .jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/org/apache/spark/spark-token-provider-kafka-0-10_2.12/3.1.2/spark-token-provider-kafka-0-10_2.12 -3.1.2.jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/3.0.0/kafka-clients-3.0.0.jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/org/apache/commons/commons-pool2/2.11.1/commons-pool2-2.11.1.jar -o $SPARK_HOME/jars/
提示:默认情况下,Apache Spark 作业从 $SPARK_HOME/jars/ 文件夹加载 jar。您不必将 jar 复制到此文件夹中。相反,您可以在使用 —conf 参数提交 Spark 作业时加载这些 jar。请参阅此处以了解更多相关信息。
Apache Spark-Amazon S3 Bucket Connector:
要将数据写入 Amazon S3 存储桶,我们需要以下 jar。这些 jar 提供了一个接口,用于将数据从 Apache Spark 写入 Amazon S3 存储桶。
- aws -java-sdk-core-1.11.762.jar
- aws -java-sdk-1.11.762.jar
- aws -java-sdk-dynamodb-1.11.762.jar
- aws -java-sdk-s3–1.11.762.jar
- hadoop -aws-3.1.2.jar
将这些 jar 复制到 $SPARK_HOME/jars/ 文件夹中。
wget https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-core/1.11.762/aws-java-sdk-core-1.11.762.jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk/1.11.762/aws-java-sdk-1.11.762.jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-dynamodb/1.11.762/aws-java-sdk-dynamodb-1.11.762.jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-s3/1.11.762/aws-java-sdk-s3-1.11.762.jar -o $SPARK_HOME/jars/
wget https://repo1.maven.org/maven2/org/apache/hadoop/hadoop-aws/3.1.2/hadoop-aws-3.1.2.jar -o $SPARK_HOME/jars/
提示:默认情况下,Apache Spark 作业从 $SPARK_HOME/jars/ 文件夹加载 jar。您不必将 jar 复制到此文件夹中。相反,您可以在使用 —conf 参数提交 Spark 作业时加载这些 jar。请参阅此处以了解更多相关信息。
配置 ClickHouse — Kafka:
借助 ClickHouse — Kafka 引擎,我们可以将 ClickHouse 表中的记录推送到 Kafka,反之亦然。
在我们的演示中,比如说,我们的要求是,每当我们在API表中插入SERVICE_ID = 1 的记录时,插入的记录都必须推送到 Kafka 中。
- ClickHouse 源表— 创建源表API。每当我们向该表中插入一条记录时,ClickHouse Kafka 引擎就会将数据推送到 Kafka。
CREATE TABLE API (
api_id Int32 Codec(DoubleDelta, LZ4),
time DateTime Codec(DoubleDelta, LZ4),
time_taken DateTime Codec(DoubleDelta, LZ4),
Service_id Int32
) Engine = MergeTree
PARTITION BY toYYYYMM(time)
ORDER BY ( api_id , time);
- Kafka 主题 ( kafka_topic_1 ) — 创建一个目标 Kafka 主题,其中 Kafka 引擎推送满足条件 SERVICE_ID = 1 的 ClickHouse 记录。
kafka-topics \
--bootstrap-server kafka:9092 \
--topic kafka_topic_1 \
--create --partitions 6 \
--replication-factor 2
- 使用创建的Kafka主题对应的Kafka表引擎创建ClickHouse表(kafka_queue) 。
CREATE TABLE kafka_queue (
api_id Int32,
time_taken Int32
)
ENGINE = Kafka
SETTINGS kafka_broker_list = 'kafka:9092 ',
kafka_topic_list = 'kafka_topic_1 ',
kafka_format = 'CSV',
kafka_max_block_size = 1 048576;
- 创建一个物化视图 ( kafka_queue_mv) — 它将 service_id = 1 的行从API表传输到kafka_queue表。
CREATE MATERIALIZED VIEW kafka_queue_mv TO kafka_queue_mv AS
SELECT api_id, time_taken FROM API
WHERE service_id = 1
最后,我们需要运行一个Kafka消费者来测试。
kafka-console-consumer.sh --bootstrap-server kafka:9092 -- topic kafka_topic_1
每当您向 service_id = 1 的 API 表插入一条记录时,该记录就会被推送到 kafka_topic_1 。
从 Apache Spark 监听 Kafka 主题:
要从 Apache Spark 作业读取 Kafka 流,我们需要以下信息。
- Kafka 服务器域名/IP 地址。
- Kafka 服务器运行的端口。
- 要听的 Kafka 主题。
Apache Spark 能够从多个 Kafka 实例监听多个 Kafka 主题。为了演示,下面的代码片段从 kafka:9092 实例监听主题 kafka-topic-1 。
dataframe = Spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "kafka:9092")
.option("consumer", "kafka-topic-1")
.load()
加载后,下一步是计算 API 所花费的时间百分比。
dataframe
.withColumn(“percentage_time”,percent_rank().over(windowSpec))
.show()
下一步是,我们需要将流写入 Amazon S3 存储桶。
注意: Apache Spark 能够将流写入许多数据层,包括 HDFS、Cassandra 等。
将结果存储到 Amazon S3 存储桶中
要将 Apache Spark 中的数据存储到 Amazon S3 存储桶,我们需要 S3 存储桶访问 ID 和密钥。Apache Spark 使用此访问 ID 和密钥向 AWS 进行身份验证。
我们有两个选项来设置 Access Id 和 Secret Key:
将访问 ID 和密钥存储为环境变量 — 不是首选方式。原因是,我们提交的任何 Spark 作业都可以访问 access_id 和 Secret_key,因为它被设置为环境变量。
export AWS_SECRET_ACCESS_KEY=XXXXX
export AWS_ACCESS_KEY_ID=XXXXX
在 SparkContext 中设置 Access Id 和 Secret Key — 另一种选择是,我们可以在 Spark Context 对象中设置 Access Id 和 Secret Key。
Spark.sparkContext._jsc.hadoopConfiguration()
.set(“fs.s3a.access.key”, xxxxxxx )
Spark.sparkContext._jsc.hadoopConfiguration()
.set(“fs.s3a.secret.key”, xxxxxxxxxxxxxxxxxxx )
在上面的代码片段中,我们设置 fs.s3a.access.key 和 fs.s3a.secret.key 参数。
一旦我们设置了访问密钥和秘密密钥,下一步就是编写将数据实际存储到 S3 存储桶中的代码。将 Spark 数据帧写入 S3 存储桶类似于写入 HDFS 或本地文件系统。