大数据系统部署中的技术架构选型种类比较多,多种技术架构或者方案在实际部署中都是组合应用;根据系统的复杂程度不同,也会做适当的增加和裁剪,正所谓没有最好的架构,只有最适合的架构。
但是初学时,面对这么多技术架构,确实会让人一脸懵,要理解这些框架最好的方式,是看它们在一个真实项目中如何协同作战。下面,通过一个模拟的 "智慧电商实时运营平台" 项目,完整走一遍从项目需求、架构设计到技术选型的全过程。
这个平台的目标是整合电商网站的所有数据,为运营、市场和供应链团队提供实时 和离线两种决策支持。
🏗️ 第一步:梳理业务需求与数据流向
任何架构设计都始于业务需求。我们先梳理出平台需要处理的核心数据流:
- 用户行为数据(实时 + 离线) :用户在App/网页上的点击、浏览、加购等行为,需实时 分析以用于个性化推荐,同时也要离线存储用于长期用户画像分析。
- 业务订单数据(实时 + 离线) :订单的创建、支付、发货等状态变更,需实时 同步到数据平台,用于大屏展示和实时风控;同时也需离线存储用于财务对账和销售分析。
- 历史数据与外部数据(离线):过去几年的销售历史、供应链数据、天气数据等,用于离线的销售预测和库存优化。
🗺️ 第二步:设计整体架构蓝图
基于上述需求,我们采用经典的Lambda架构。它将数据处理分为三条清晰的路径:
- 实时处理链路 (Speed Layer):追求低延迟,处理秒级或毫秒级数据。
- 离线处理链路 (Batch Layer):追求准确性和全面性,处理T+1或小时级数据。
- 服务层 (Serving Layer):统一对外提供查询服务。
下面是这个平台的完整架构图及各层职责:
#mermaid-svg-RG5f6p9ltyEecVSt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RG5f6p9ltyEecVSt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RG5f6p9ltyEecVSt .error-icon{fill:#552222;}#mermaid-svg-RG5f6p9ltyEecVSt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RG5f6p9ltyEecVSt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RG5f6p9ltyEecVSt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RG5f6p9ltyEecVSt .marker.cross{stroke:#333333;}#mermaid-svg-RG5f6p9ltyEecVSt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RG5f6p9ltyEecVSt p{margin:0;}#mermaid-svg-RG5f6p9ltyEecVSt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RG5f6p9ltyEecVSt .cluster-label text{fill:#333;}#mermaid-svg-RG5f6p9ltyEecVSt .cluster-label span{color:#333;}#mermaid-svg-RG5f6p9ltyEecVSt .cluster-label span p{background-color:transparent;}#mermaid-svg-RG5f6p9ltyEecVSt .label text,#mermaid-svg-RG5f6p9ltyEecVSt span{fill:#333;color:#333;}#mermaid-svg-RG5f6p9ltyEecVSt .node rect,#mermaid-svg-RG5f6p9ltyEecVSt .node circle,#mermaid-svg-RG5f6p9ltyEecVSt .node ellipse,#mermaid-svg-RG5f6p9ltyEecVSt .node polygon,#mermaid-svg-RG5f6p9ltyEecVSt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RG5f6p9ltyEecVSt .rough-node .label text,#mermaid-svg-RG5f6p9ltyEecVSt .node .label text,#mermaid-svg-RG5f6p9ltyEecVSt .image-shape .label,#mermaid-svg-RG5f6p9ltyEecVSt .icon-shape .label{text-anchor:middle;}#mermaid-svg-RG5f6p9ltyEecVSt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RG5f6p9ltyEecVSt .rough-node .label,#mermaid-svg-RG5f6p9ltyEecVSt .node .label,#mermaid-svg-RG5f6p9ltyEecVSt .image-shape .label,#mermaid-svg-RG5f6p9ltyEecVSt .icon-shape .label{text-align:center;}#mermaid-svg-RG5f6p9ltyEecVSt .node.clickable{cursor:pointer;}#mermaid-svg-RG5f6p9ltyEecVSt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RG5f6p9ltyEecVSt .arrowheadPath{fill:#333333;}#mermaid-svg-RG5f6p9ltyEecVSt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RG5f6p9ltyEecVSt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RG5f6p9ltyEecVSt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RG5f6p9ltyEecVSt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RG5f6p9ltyEecVSt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RG5f6p9ltyEecVSt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RG5f6p9ltyEecVSt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RG5f6p9ltyEecVSt .cluster text{fill:#333;}#mermaid-svg-RG5f6p9ltyEecVSt .cluster span{color:#333;}#mermaid-svg-RG5f6p9ltyEecVSt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RG5f6p9ltyEecVSt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RG5f6p9ltyEecVSt rect.text{fill:none;stroke-width:0;}#mermaid-svg-RG5f6p9ltyEecVSt .icon-shape,#mermaid-svg-RG5f6p9ltyEecVSt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RG5f6p9ltyEecVSt .icon-shape p,#mermaid-svg-RG5f6p9ltyEecVSt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RG5f6p9ltyEecVSt .icon-shape .label rect,#mermaid-svg-RG5f6p9ltyEecVSt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RG5f6p9ltyEecVSt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RG5f6p9ltyEecVSt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RG5f6p9ltyEecVSt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用层
数据服务与查询层
计算与处理层
数据存储层
数据采集与传输层
数据源层
Web/App日志
业务数据库
(MySQL/PostgreSQL)
外部数据
(天气/供应链)
Flume / Filebeat
Debezium / Canal CDC
Sqoop / DataX
Kafka 消息队列
HDFS
数据湖
HBase
实时服务
Flink
实时计算
Spark
离线计算
ClickHouse / Druid
实时OLAP
Hive / Spark SQL
离线数仓
实时大屏
& 推荐
BI报表
& 数据科学
🧩 第三步:为每一层选择"最佳拍档"
现在,我们来为架构图中的每一层填充具体的技术组件:
1. 数据采集与传输层:Kafka 是绝对核心
这一层负责将数据从源头高效、可靠地接入系统。
- 日志采集 :使用 Flume 或 Filebeat 从Web服务器采集用户行为日志,并发送到Kafka。
- 数据库变更捕获 :使用 Debezium 或 Canal 监控MySQL的业务订单表,将数据变更实时转为消息发送到Kafka。
- 历史/批量数据导入 :使用 Sqoop 或 DataX 将历史订单、外部数据一次性导入到HDFS。
- 数据总线 :Apache Kafka 是整个实时数据流入的中枢。所有实时数据先进入Kafka,进行削峰填谷,再被下游的Flink和HDFS消费。
2. 数据存储层:HDFS 与 HBase 的"冷热"分工
这一层负责持久化存储所有数据。
- "冷"数据湖 :HDFS 存储所有原始、不可变的数据。无论是Kafka过来的实时数据(落地归档),还是Sqoop导入的历史数据,最终都会以文件形式存入HDFS,作为数据仓库的基石。
- "热"数据服务 :HBase 是一个基于HDFS的NoSQL数据库。它用来存储Flink实时计算后需要低延迟(毫秒级)随机读写的结果,比如"用户当前的最新购物车信息"。
3. 计算与处理层:Flink 与 Spark 的"实时"与"离线"协同
这一层是数据处理的大脑。
- 实时计算引擎 :Apache Flink 消费Kafka中的实时数据流,进行实时清洗、聚合、关联等计算。例如,计算过去5分钟各个商品的实时点击量,用于热门榜单。
- 离线计算引擎 :Apache Spark 读取HDFS中的海量历史数据,进行复杂的离线ETL 和批量分析。例如,每日凌晨运行任务,计算昨天的全国各区域销售报表。
4. 数据服务与查询层:ClickHouse 与 Hive 的"快"与"全"
这一层为上层应用提供数据查询服务。
- 实时OLAP引擎 :ClickHouse 是一款极快的列式数据库。Flink将实时计算结果写入ClickHouse,供实时大屏和即席查询使用。
- 离线数据仓库 :Hive 将HDFS上的结构化数据映射成"表",提供SQL查询能力。数据分析师可以用Hive SQL对海量历史数据进行复杂的离线分析,生成BI报表。
5. 辅助协调层:ZooKeeper 是集群的"管理员"
最后,我们还需要一个"管理员"来协调这一切。
- 分布式协调服务 :ZooKeeper 负责管理Kafka、HBase、HDFS等集群的元数据、选主和配置同步。它本身不处理业务数据,但保证了整个分布式系统的稳定运行。
💡 第四步:组件间的关系与数据同步
从这个架构图中,可以清晰地看到我们之前讨论的框架是如何各司其职、紧密协作的:
- Kafka 是实时数据管道,连接了数据源和Flink。
- Flink 是实时计算引擎,消费Kafka数据,产出结果。
- HDFS 是离线数据底座,存储所有历史数据,供Spark进行批处理。
- Spark 是离线计算引擎,读取HDFS数据,产出报表。
- HBase / ClickHouse / Hive 是数据服务层,为不同的应用场景(实时/离线)提供查询服务。
- ZooKeeper 是集群协调者,默默地在背后保证所有组件正常工作。
🛠️ 第五步:部署考量
- 集群规划 :这是一个典型的完全分布式高可用集群。通常,我们会准备多台物理机或云服务器,将HDFS NameNode、YARN ResourceManager、ZooKeeper等核心组件部署为高可用模式(即至少两个节点),避免单点故障。
- 资源分配:根据各组件的资源消耗特点进行规划。例如,DataNode(HDFS)需要大容量磁盘,而Flink/TaskManager(计算节点)则需要更多的内存和CPU。
✂️ 第六步:根据项目规模"按需裁剪"
上面的架构是一个较为完整的企业级方案。在实际项目中,可以根据自身的数据量、实时性要求和团队规模进行裁剪:
场景一:小型创业公司,数据量<100TB,实时性要求不高
- 裁剪方案:大刀阔斧地简化。
- 技术栈 :可以放弃复杂的Hadoop生态,直接使用Apache Doris 或ClickHouse这样的"全能型"数据库。它们既能存储,也能进行实时和离线分析,极大地降低了架构和运维的复杂度。
场景二:中型互联网公司,数据量数百TB,有实时和离线需求
- 裁剪方案 :采用Kappa架构(轻量级Lambda)。
- 技术栈 :可以只用 Kafka + Flink 这一套实时技术栈。所有数据(包括历史数据)都作为流来处理,Flink可以同时做实时计算和"有限流"的离线批处理,省去了维护Spark和Hive的成本。
场景三:大型企业,数据量PB级,有复杂的离线数仓和实时风控需求
- 裁剪方案 :采用我们上面设计的完整 Lambda架构。
- 技术栈 :Flume + Kafka + Debezium + Flink + Spark + HDFS + Hive + ClickHouse + ZooKeeper。这是最成熟、最稳定的方案,能应对最复杂的业务场景。
💎 总结
通过这个"智慧电商"项目,应该能清晰地看到:
- 没有"万能钥匙":每个框架都有其最擅长的领域,它们通常组合使用,各司其职。
- 架构服务于业务:Lambda、Kappa等架构模式提供了不同的解题思路。
- 按需裁剪是常态:从几十TB到EB级数据,技术选型和架构的复杂度天差地别。关键是理解每个组件的核心能力,然后根据业务需求进行合理的组合与取舍。