ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Hadoop的租车网站数据分析系统设计与实现

基于Hadoop的租车网站数据分析系统设计与实现 毕业设计拿到这个题目的时候我第一反应是大数据组件搭建会很麻烦。但真正做完回头看“基于Hadoop的租车网站的数据分析系统”其实是性价比很高的题目——它把Hadoop、数据分析、Web开发、可视化四块内容串在一起既能体现技术深度又能讲清楚业务价值。这篇文章把我完整的实现过程、技术选型的考量和踩坑记录整理出来给正在做类似选题的同学一个可以直接参考的路线。这套方案适合两类人一类是计算机、大数据方向做毕业设计想用Hadoop生态但不确定从哪入手的同学另一类是有一定大数据理论基础、想用一个完整项目把HDFS、Hive、数据分析、可视化串起来练手的自学者。前期只要会Linux基本操作和SQL剩下基本都是按步骤堆出来的。1. 项目整体思路与方案设计1.1 为什么是Hadoop这个题目真正考察的是什么很多同学看到“基于Hadoop”就有心理压力觉得一定要分布式集群、几十台服务器才叫大数据。其实毕设题目里出现Hadoop考察的核心是“大数据处理思路”不是“机器数量”。租车网站这个业务场景本身就适合数据分析因为订单数据天然具备多维分析的价值用户、时间、地点、车型、价格、时长随便组合都能产出有说服力的结论。Hadoop在题目里的作用是提供数据存储和计算底座。HDFS解决海量订单日志的分布式存储问题Hive基于MapReduce或Tez解决结构化数据的批处理分析问题。哪怕你的数据量只有几十万条用这套链路跑一遍也完全符合“基于Hadoop的数据分析系统”的定位——重点在于架构完整、链路清晰而不是服务器足够多。我当时的定位很明确做一个“五脏俱全”的小型数据平台。前端是模拟租车网站业务产生的订单数据中间走Hadoop存储和Hive分析最后用Web页面做可视化展示。这样既回避了纯算法类毕设的高难度又比单纯的管理系统多出了大数据处理这条技术主线。1.2 系统架构与数据链路设计这个项目的架构不用搞得太复杂我按五层来设计数据源层、采集层、存储层、计算层、应用层。数据源层是租车业务数据包括用户表、车辆表、门店表、订单表以及用户访问日志。这些数据可以用Python脚本模拟生成也可以在生产环境通过埋点采集毕设阶段用模拟数据完全够用。采集层我的做法是用Flume监控日志文件目录新产生的订单日志自动上传到HDFS如果你不想引入Flume直接使用hdfs dfs -put手动上传也可以效果一样只是少了实时采集的演示点。存储层就是HDFS原始数据落地后按天分目录存放。计算层是Hive先建库建表再做ETL清洗最后按需求写HQL统计指标。应用层是可视化部分我选择了最稳妥的组合Hive分析结果导出到MySQL后端SpringBoot写接口前端用ECharts画图表。1.3 技术选型的关键取舍在做技术选型的时候我给自己定了一个原则核心链路用熟不用生扩展链路量力而行。以下几项是我最终确定的选择Hadoop版本用3.3.xJDK用1.8这两个版本搭配最稳网上资料也最多。计算引擎用Hive原生引擎没有强行上Spark。Spark是加分项但会明显增加部署和调优成本毕设答辩时也容易被追问数据倾斜等细节。元数据存储用MySQL因为Hive默认的Derby只能支持单会话实验时开多个窗口就会报错换成MySQL才能正常多窗口操作。Zookeeper只做了解没有整合到主链路。单节点伪分布式模式不需要Zookeeper只有配置NameNode HA或者HBase时才必须用。如果时间充裕可以在论文里写“可扩展集成Zookeeper实现高可用”但不要在主链路里加否则只会增加出错概率。这里想多说一句毕设不是越复杂越好而是“能在答辩现场稳定跑通”最好。一个简化但能完整演示的数据分析链路远比一个功能堆砌但经常起不来的系统更拿分。2. 环境搭建Hadoop集群从零到能跑2.1 模式选择单机、伪分布式、完全分布式Hadoop部署有三种模式选择哪种直接决定你后面几周的体验。单机模式Local Mode下所有进程跑在同一个JVM里HDFS和YARN都不启动只能做本地调试跑不了真实的分布式演示。完全分布式模式需要至少3台机器或虚拟机每台机器都要配置SSH免密和相同用户对硬件资源和部署时间要求较高。伪分布式Pseudo-Distributed Mode是我最终选择的方案——在一台机器上同时跑NameNode、DataNode、ResourceManager、NodeManager每个进程都是一个独立Java进程分布式效果和完全分布式一致但部署复杂度低很多。如果你有16G以上内存的电脑伪分布式跑起来很流畅如果只有8G内存建议关闭几个无关应用再跑。我身边有同学直接用3台虚拟机做了完全分布式结果光环境配置就折腾了两周最后阶段反而被模拟业务数据和分析SQL压缩了时间非常不划算。2.2 伪分布式部署实操我把核心步骤写在这里很多细节是我踩过坑之后确认的。第一步安装JDK 1.8并配置JAVA_HOME环境变量。Hadoop 3.x虽然也能跑JDK 11但很多教程和第三方组件还是基于1.8统一用1.8最省心。export JAVA_HOME/usr/local/jdk1.8 export PATH$PATH:$JAVA_HOME/bin第二步下载Hadoop 3.3.x安装包并解压到/usr/local/hadoop。注意这里不要解压到带中文或空格的路径否则后面各种诡异报错。wget https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz tar -zxvf hadoop-3.3.6.tar.gz -C /usr/local/ mv /usr/local/hadoop-3.3.6 /usr/local/hadoop第三步修改环境变量。export HADOOP_HOME/usr/local/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin第四步修改核心配置文件。这几个文件都在$HADOOP_HOME/etc/hadoop/目录下。core-site.xml配置NameNode地址和临时目录。hadoop.tmp.dir一定要单独指定默认值在系统临时目录下重启后数据容易丢失。configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/home/hadoop/data/hadoop_tmp/value /property /configurationhdfs-site.xml配置副本数。伪分布式只有一个DataNode副本数必须设为1否则会一直报副本不足。configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name valuefile:///home/hadoop/data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///home/hadoop/data/datanode/value /property /configurationyarn-site.xml配置NodeManager的辅助服务这里不配的话MapReduce任务会直接报错。configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configurationmapred-site.xml默认不存在需要从模板复制一份。联网下载资源慢的把任务调度方式指到YARN上。cp mapred-site.xml.template mapred-site.xmlconfiguration property namemapreduce.framework.name/name valueyarn/value /property /configuration第五步配置SSH免密登录。Hadoop启动脚本会通过SSH连接本机不配置会反复提示输入密码。ssh-keygen -t rsa -P -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys第六步格式化NameNode并启动。注意格式化只允许执行一次重复格式化会导致NameNode和DataNode的clusterID不一致DataNode一直起不来。hdfs namenode -format start-dfs.sh start-yarn.sh启动完成后输入jps能看到NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager几个进程就说明启动成功。Web界面访问http://localhost:9870可以查看HDFS状态访问http://localhost:8088可以查看YARN任务状态。2.3 Hive与MySQL元数据配置Hadoop跑通之后我接着部署Hive元数据。前面说过Hive自带Derby数据库不支持多会话所以要把元数据放到MySQL里。先在MySQL里创建Hive元数据库CREATE DATABASE hive_meta DEFAULT CHARACTER SET utf8mb4; CREATE USER hive% IDENTIFIED BY hive123; GRANT ALL PRIVILEGES ON hive_meta.* TO hive%; FLUSH PRIVILEGES;然后修改hive-site.xml中JDBC相关配置。注意MySQL 8.x驱动要匹配对应的URL写法时区参数不能省略否则连接直接报错。property namejavax.jdo.option.ConnectionURL/name valuejdbc:mysql://localhost:3306/hive_meta?useSSLfalseamp;serverTimezoneAsia/Shanghai/value /property property namejavax.jdo.option.ConnectionDriverName/name valuecom.mysql.cj.jdbc.Driver/value /property property namejavax.jdo.option.ConnectionUserName/name valuehive/value /property property namejavax.jdo.option.ConnectionPassword/name valuehive123/value /property初始化元数据库schematool -dbType mysql -initSchema执行成功后输入hive进入命令行创建一张测试表验证一下。到这里整个数据分析的基础环境就算搭完了。2.4 要不要引入Zookeeper很多教程会把Hadoop、Zookeeper放在一起部署但其实要分场景。Zookeeper在Hadoop生态里主要服务两个场景一是NameNode高可用HA二是HBase、Kafka这类分布式组件的协调服务。我们的毕设如果只在单节点上跑伪分布式Hadoop没有HA需求也不涉及HBase和Kafka直接跳过Zookeeper完全没问题。当然如果论文想体现高可用设计可以把Zookeeper整合步骤作为“扩展实现”章节写进论文配置两个NameNode做HA。但我的建议是时间紧就别做做了就要保证答辩时能启动且稳定运行——高可用集群的故障切换一旦在演示现场出问题非常尴尬。3. 数据模型与数仓构建3.1 租车业务的数据域划分在动手写SQL之前我花了一整天梳理租车业务的数据域。这个环节千万别省直接决定了后面分析指标能不能自圆其说。租车网站的核心业务链路是用户注册 - 浏览车辆 - 下单 - 取车 - 使用车辆 - 还车 - 支付 - 可能再次下单。围绕这条链路我划分了四个主题域用户域用户ID、注册时间、性别、年龄、是否为会员。车辆域车辆ID、车型、品牌、车牌号、座位数、每公里价格。门店域门店ID、门店名称、所在城市、具体地址。订单域订单ID、用户ID、车辆ID、取车门店ID、还车门店ID、取车时间、还车时间、订单金额、订单状态。订单域是核心其他三个域都是围绕订单做维度补充的。这种主题域的划分方式到后面写数仓分层的时候就非常自然了。3.2 模拟数据生成与上传HDFS租车网站的真实业务数据不可能白白给你所以用Python的Faker库生成模拟数据是最现实的方案。我设计了几张核心表用户表1000条车辆表500条门店表50条订单表5万条分布在最近180天里。数据量不能太少太少了体现不出数据分析的价值也不能太大太大了伪分布式跑Hive会很吃力。5万条在伪分布式下跑HQL单条SQL基本在几秒到几十秒内完成演示效果刚刚好。生成订单数据的关键是时间分布要模拟真实情况工作日订单少周末订单多早晚高峰取车多。我写了简单的加权随机逻辑让周一到周四的订单量系数为0.8周五到周日为1.3这样最后画出来的趋势图有起伏感比完全均匀的数据有意义得多。from datetime import datetime, timedelta import random import csv def random_order_time(): base datetime.now() - timedelta(daysrandom.randint(0, 180)) hour_w random.choices([8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20], weights[1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1])[0] take_time base.replace(hourhour_w, minuterandom.randint(0, 59)) return take_time数据生成完之后在HDFS上创建租车数仓目录分主题存放数据文件hdfs dfs -mkdir -p /user/hive/warehouse/rcs.db/ods_order/data hdfs dfs -put order.csv /user/hive/warehouse/rcs.db/ods_order/data/如果你愿意多花一点时间把Flume接进来可以在Flume的source端配置一个spooldir监控本地数据文件目录sink端指向HDFS对应目录。这样每生成一个新数据文件Flume会自动上传演示效果更接近真实采集环境。官方文档里Flume 1.9版本提供的source类型很成熟配起来半小时内能完成agent.sources spooldirSource agent.channels memoryChannel agent.sinks hdfsSink agent.sources.spooldirSource.type spooldir agent.sources.spooldirSource.spoolDir /home/hadoop/data/rcs_logs agent.sinks.hdfsSink.type hdfs agent.sinks.hdfsSink.hdfs.path /user/hive/warehouse/rcs.db/ods_order/data/%Y%m%d agent.sinks.hdfsSink.hdfs.fileType DataStream3.3 数仓分层设计与Hive建表数仓分层不是花架子它解决的是“分析口径从哪来”的问题。原始订单表里有脏数据不可能每次分析都重写清洗逻辑所以我把数仓分成四层ODS层存放原始数据表结构和业务系统保持一致。DWD层做清洗和标准化过滤无效订单统一时间格式补充维度字段。DWS层按时间、主题做轻度汇总比如每天的订单量、销售额、活跃用户数。ADS层面向具体应用的数据结果表直接给可视化系统使用。Hive建表需要注意字段类型和分隔符的匹配。我生成数据时用逗号分隔建表时指定ROW FORMAT DELIMITED FIELDS TERMINATED BY ,。同时按日期做分区这样后面查询时可以只扫描指定分区的数据。CREATE TABLE rcs.ods_order_info ( order_id BIGINT, user_id BIGINT, car_id BIGINT, shop_id INT, take_time STRING, return_time STRING, amount DECIMAL(10,2), status TINYINT ) PARTITIONED BY (dt STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE;DWD层建表时我会把车辆信息、门店信息直接退化到订单明细表里比如车型、品牌、城市。这个操作术语叫“维度退化”好处是后续分析时不需要反复关联多张表SQL写起来简单跑起来也快。4. 数据分析核心实现4.1 指标体系先想清楚“分析什么”数据分析最怕的状态是“数据全有了但不知道要算什么”。我一开始也犯了这个毛病拿着Hive乱查一通后来静下心把分析指标按业务场景梳理了一遍才找到方向。围绕租车网站我设计了四组核心指标订单趋势类每日订单量、每日GMV、每周末订单占比用来判断业务整体走势。用户行为类新老用户订单占比、人均订单量、复购用户数用来判断用户粘性。车辆运营类车型订单排名、单辆车月均出租次数、车辆平均使用时长用来判断库存结构是否合理。门店区域类城市订单量排名、热门门店Top10、区域订单热度分布用来判断扩张方向。这些指标要回答的问题是哪款车最受欢迎哪个门店订单最多用户更喜欢长租还是短租周末和工作日的用车需求差异有多大带着这些问题去写SQL分析才算真正落地。4.2 HQL实战常用分析SQL拆解挑几个有代表性的HQL写出来这些可以直接套用到你的数据表上。每日订单趋势是最基础也最直观的分析用于可视化大屏的折线图SELECT dt AS order_date, COUNT(*) AS order_cnt, SUM(amount) AS gmv FROM rcs.dwd_order_detail WHERE dt 2024-01-01 GROUP BY dt ORDER BY dt;热门车型排名用于柱状图SELECT car_type, COUNT(*) AS order_cnt, ROUND(AVG(amount), 2) AS avg_amount FROM rcs.dwd_order_detail GROUP BY car_type ORDER BY order_cnt DESC LIMIT 10;用户复购分析用于判断用户粘性SELECT user_id, COUNT(*) AS order_cnt FROM rcs.dwd_order_detail WHERE dt 2024-06-01 GROUP BY user_id HAVING COUNT(*) 2 ORDER BY order_cnt DESC LIMIT 20;取还车热门区域用于地图热力图SELECT take_city, take_shop_name, COUNT(*) AS order_cnt FROM rcs.dwd_order_detail GROUP BY take_city, take_shop_name ORDER BY order_cnt DESC LIMIT 10;这里提醒一个Hive的坑HAVING子句在Hive里可以用但性能不如子查询过滤数据量大时建议先用子查询生成临时表再用WHERE过滤。另外LIMIT后的数字不要写太大伪分布式下出结果较慢展示时也容易显得杂乱。4.3 从Hive到MySQL结果数据下沉Hive的分析结果保存在HDFS上但Web可视化系统无法直接访问HDFS需要把结果表导出到MySQL。这一步有两种常见做法第一种是直接使用Sqoop导出。Sqoop是专门做Hadoop和关系型数据库数据迁移的工具sqoop export \ --connect jdbc:mysql://localhost:3306/rcs_analysis?useSSLfalse\serverTimezoneAsia/Shanghai \ --username root --password root123 \ --table ads_order_trend \ --export-dir /user/hive/warehouse/rcs.db/ads_order_trend \ --input-fields-terminated-by \001第二种是建一张MySQL目标表然后用Hive执行INSERT OVERWRITE DIRECTORY将结果导出为CSV再通过Python脚本或mysql命令导入到MySQL。我实际用的是第二种因为Sqoop在版本匹配上偶尔会出问题而直接用SQL的INSERT OVERWRITE方案更直观出错也好排查。hive -e INSERT OVERWRITE LOCAL DIRECTORY /home/hadoop/export/ads_order_trend ROW FORMAT DELIMITED FIELDS TERMINATED BY , SELECT dt, order_cnt, gmv FROM rcs.ads_order_trend;导出后用Python脚本批量写入MySQL整个过程非常可控。5. 可视化大屏与系统集成5.1 可视化方案横向对比数据算出来只是半成品要用图表把结论讲清楚可视化这一环必不可少。我调研过三种方案SupersetAirbnb开源的可视化平台基于Python可以直接连接Hive或MySQL拖拽生成图表。优点是省去写前端代码缺点是想做自定义驾驶舱布局比较费劲。ECharts 自研前端手动写HTML、JavaScript页面调用后端接口。优点是完全可控、展示效果专业缺点是需要写一定量的Web代码。FineBI等商业工具演示效果好但需要申请license且论文里写起来偏“商业软件使用”技术含量不高。我最终选了“SpringBoot ECharts MySQL”的组合。理由很现实毕设不仅要展示图表还要展示“前后端交互”的开发能力自研方案对论文的“系统设计与实现”章节更有话说。5.2 大屏页面设计与数据接口可视化大屏不用做成几十个图表堆砌的复杂界面我把核心页面设计成一个驾驶舱布局顶部四个关键指标卡片累计订单量、总GMV、活跃用户数、车辆利用率。中间主区域是订单趋势折线图展示近30天数据变化。左下是热门车型Top10柱状图。右下是门店订单量Top10条形图。如果做了城市维度统计还可以注册高德地图或使用ECharts地图组件做一个区域热力图体现地理特征。后端接口设计很简单就是查MySQL里的ADS表RestController RequestMapping(/api/analysis) public class AnalysisController { Resource private AdsOrderTrendMapper trendMapper; GetMapping(/orderTrend) public ResultListOrderTrendVO orderTrend() { ListOrderTrendVO list trendMapper.selectRecent30Days(); return Result.success(list); } }前端ECharts请求数据后配置折线图的xAxis和series即可渲染。需要注意MySQL中时间字段的类型要转换成字符串输出避免JSON序列化出现时区问题。我当时就在LocalDateTime序列化上栽了跟头后来统一在SQL里用DATE_FORMAT(dt, %Y-%m-%d)转成字符串前端就稳定不变了。5.3 地图热力图等复杂图表的实现细节如果想在驾驶舱里放一张“租车热门城市热力图”ECharts加载中国地图之前必须先注册GeoJSON。具体做法是下载各省市GeoJSON数据放到前端静态目录然后fetch(./china.json) .then(res res.json()) .then(geoJson { echarts.registerMap(china, geoJson); myChart.setOption({ series: [{ type: map, map: china, data: cityData }] }); });热力图数据来自ads_city_order_stats表字段就是城市名和订单量。这个图表在答辩现场很加分因为视觉冲击力强而且能直观表达“数据分析”在空间维度上的价值。6. 常见问题排查与答辩宝典6.1 高频错误与解决方案速查做这个项目过程中我整理了以下出现频率最高的报错和解决方案如果你也遇到可以直接按表排查。报错现象根本原因解决方案NameNode进入safemodeHDFS启动后自动进入安全模式保护数据hdfs dfsadmin -safemode leave或等待自动退出后重试DataNode进程启动后很快消失多次格式化导致clusterID不一致清空dfs.name.dir和dfs.data.dir目录重新格式化再启动Hive启动报NoClassDefFoundError: org/apache/hadoop/cryptoHadoop与Hive的commons-crypto版本不一致将$HADOOP_HOME/share/hadoop/common/lib/commons-crypto-1.0.0.jar复制到$HIVE_HOME/libHive无法连接MySQL元数据库JDBC驱动缺失或URL参数不完整使用MySQL 8.x驱动URL加useSSLfalseserverTimezoneAsia/ShanghaiMapReduce任务卡住不动YARN集群资源分配不足检查yarn-site.xml调大yarn.nodemanager.resource.memory-mb启动Hive后退出提示“Table not found”没有先执行对应的建表语句按ODS、DWD、DWS、ADS顺序逐层执行建表脚本其中NoClassDefFoundError这类Hadoop和Hive版本冲突问题的排查思路是报错信息里有一个crypto关键字说明是加密库加载失败。先用find / -name commons-crypto*.jar定位所有同名Jar包再对比版本号高版本覆盖低版本问题基本能解决。6.2 伪分布式起不来的排错思路环境启动失败是新手最容易崩溃的环节。我总结了一套固定排错顺序遇到问题先按顺序检查能省一半时间。第一步输入jps确认有哪些进程。如果连NameNode都没有说明启动了但没有正常注册优先看$HADOOP_HOME/logs/hadoop-hadoop-namenode-*.log日志。第二步检查端口占用。Hadoop 3.x的NameNode Web端口是9870ResourceManager是8088。如果端口被占用用netstat -tlnp | grep 9870查出哪一个进程占用了端口杀掉或换端口。第三步确认hosts配置。/etc/hosts里不要把主机名映射到127.0.1.1否则节点间通信会异常。改成127.0.0.1 localhost最稳妥。第四步检查环境变量是否生效。有的同学改了~/.bashrc后没有source导致hadoop version能执行但启动脚本找不到某些路径这种低级错误排查到最后才发现非常浪费时间。6.3 答辩时老师最常问的几个问题毕设答辩到最后老师大概率不会让你现场演示所有功能而是围绕技术方案和实现细节提问。我整理了我被问到和同学被问到的高频问题提前准备会从容很多。老师问“为什么用Hadoop而不用Spark”怎么答可以说租车数据分析属于离线批处理场景分析频率是每天或每周Hive基于Hadoop生态和HDFS天然集成开发成本低Spark更适合需要秒级响应的实时计算对部署环境和资源要求更高作为毕业设计的主链路会分散精力。这里再补一句“系统采用分层的离线数仓设计未来可扩展Spark计算引擎”既承认了Spark的价值又守住了自己的技术边界。老师问“数据量只有几万条用Hadoop是不是杀鸡用牛刀”怎么答重点应放在架构的可扩展性上当前是功能验证阶段所以采用模拟数据HDFS的分布式存储和Hive的分布式计算决定了当数据量增长到T级时不需要重构代码只需要横向扩容节点。再结合HDFS的副本存放机制讲一下数据安全设计这个回答就很完整了。老师问“数仓为什么要分层”怎么答核心是两个词解耦与复用。ODS层保留原始数据DWD层清洗过滤DWS层统一汇总。每一层各司其职避免了业务SQL直接读取原始表导致的分析口径混乱。简单说分层就是为了让每一层的职责清晰、让指标口径统一、让下游系统不再重复清洗数据。6.4 学有余力的扩展方向如果你的时间比较充裕做完主链路后可以从这几个方向选一个扩展。一是把计算引擎从Hive换成Spark SQL用DataFrame API重写分析任务代码量不大但论文里可以多写一章二是引入调度工具Azkaban或DolphinScheduler把数据采集、ETL、指标计算做成定时任务体现自动化运维能力三是把Flume日志采集换成Kafka消息队列模拟实时数据接入可以让系统架构更完整。但请记住扩展方向是为了锦上添花不是必经之路主链路稳定跑通永远排在第一位。我自己的体会是这类Hadoop数据分析项目的关键点不在“会用什么工具”而在于能不能讲清楚“数据从哪来、到哪里去、每一步做了什么、为什么这么做”。把这套逻辑讲明白哪怕只用了最简单的伪分布式也会是合格的毕业设计。最后再分享一个实用小技巧我在正式答辩前写了一个一键启动脚本把start-all.sh、schematool初始化和Hive预执行语句按顺序组合起来演示的时候一条命令拉起整个集群既省时间又避免了手动操作出错。这个小细节在现场演示时特别加分建议你也提前准备一个。
返回列表