Flume流Twitter数据至Hive Avro表报Block size错误求助
嘿,我来帮你拆解这个问题——你遇到的Block size invalid or too large for this implementation: -40错误,根源在于Flume输出的数据格式和Hive表预期的格式完全不匹配,咱们一步步理清楚:
为什么会出现这个错误?
你的Flume配置里,HDFS sink是把Twitter数据输出成纯文本JSON(看配置里的hdfs.writeFormat = Text和serializer=Text),但你创建的Hive表却用了Avro的SerDe和容器输入输出格式——Avro容器文件有自己特定的文件结构(包含元数据、块大小等信息),而纯文本JSON完全不符合这个结构,所以Avro解析器读取时就会读到无效的块大小值,抛出这个错误。
两种修复方案任你选
方案一:让Flume输出Avro格式(匹配现有Hive表)
修改你的Flume配置,把HDFS sink改成输出Avro容器格式,这样现有Hive的Avro表就能正确解析数据:
# 替换原Flume sink的相关配置 TwitterAgent.sinks.HDFS.type = hdfs TwitterAgent.sinks.HDFS.hdfs.path = hdfs://xxx:8000/topics/flumedata TwitterAgent.sinks.HDFS.hdfs.fileType = DataStream # 把Text格式替换为Avro格式配置 TwitterAgent.sinks.HDFS.hdfs.writeFormat = Avro TwitterAgent.sinks.HDFS.hdfs.serializer = org.apache.flume.sink.hdfs.AvroEventSerializer # 指定和Hive表一致的Avro schema TwitterAgent.sinks.HDFS.hdfs.serializer.schema = { "type" : "record", "name" : "Doc", "doc" : "adoc", "fields" : [ { "name" : "id", "type" : "string" }, { "name" : "user_friends_count", "type" : [ "int", "null" ] }, { "name" : "user_location", "type" : [ "string", "null" ] }, { "name" : "user_description", "type" : [ "string", "null" ] }, { "name" : "user_statuses_count", "type" : [ "int", "null" ] }, { "name" : "user_followers_count", "type" : [ "int", "null" ] }, { "name" : "user_name", "type" : [ "string", "null" ] }, { "name" : "user_screen_name", "type" : [ "string", "null" ] }, { "name" : "created_at", "type" : [ "string", "null" ] }, { "name" : "text", "type" : [ "string", "null" ] }, { "name" : "retweet_count", "type" : [ "long", "null" ] }, { "name" : "retweeted", "type" : [ "boolean", "null" ] }, { "name" : "in_reply_to_user_id", "type" : [ "long", "null" ] }, { "name" : "source", "type" : [ "string", "null" ] }, { "name" : "in_reply_to_status_id", "type" : [ "long", "null" ] }, { "name" : "media_url_https", "type" : [ "string", "null" ] }, { "name" : "expanded_url", "type" : [ "string", "null" ] } ] } # 其他原有配置保持不变 TwitterAgent.sinks.HDFS.hdfs.batchSize = 10000 TwitterAgent.sinks.HDFS.hdfs.rollSize = 0 TwitterAgent.sinks.HDFS.hdfs.rollCount = 100000
修改后重启Flume Agent,重新采集数据,之后Hive执行select * from twitter_tweets;就能正常获取数据了。
方案二:修改Hive表,用JSON SerDe读取现有纯文本数据
如果你不想改动Flume配置,直接读取已经存在的纯文本JSON文件,那需要把Hive表改成用JSON SerDe:
DROP TABLE IF EXISTS twitter_tweets; CREATE EXTERNAL TABLE twitter_tweets ( id string, user_friends_count int, user_location string, user_description string, user_statuses_count int, user_followers_count int, user_name string, user_screen_name string, created_at string, text string, retweet_count bigint, retweeted boolean, in_reply_to_user_id bigint, source string, in_reply_to_status_id bigint, media_url_https string, expanded_url string ) ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' STORED AS TEXTFILE LOCATION '/topics/flumedata';
注意:这里用的是HCatalog的JsonSerDe,确保你的Hive环境已经包含HCatalog依赖。如果没有,也可以使用第三方的
org.openx.data.jsonserde.JsonSerDe,需要先在Hive中安装这个SerDe包(比如通过ADD JAR命令添加对应的jar包)。
额外提醒
- 不要用
LOAD DATA INPATH命令处理外部表——外部表的意义就是直接读取指定HDFS路径的文件,LOAD DATA会把文件移动到Hive的默认表目录下,反而会导致原路径数据被清空,直接用LOCATION指定路径更合适。 - 如果已经执行过
LOAD DATA,需要检查Hive表的实际存储路径是否正确,或者重新指定LOCATION到原Flume输出路径。
内容的提问来源于stack exchange,提问作者SARANYA

