需求是把mongodb里的数据条目存入hdfs,用于离线统计分析。mongodump导出的文件格式为bson,每条记录前用4字节来表示该记录的长度,这是比较典型的非定长条目的文件存储格式,优点是简单。由于只能从文件开始处一路读下去才能理解整个文件,所以当给定部分文件内容时,是没法理解文件内容的,这对mapreduce的分割很不友好。mongodb官方提供的方案,是对bson文件预处理一遍,生成split文件,mapdeduce任务根据split文件进行分割。但有如下缺点:
- 初次使用时,需要生成split文件,耗时较长
- hadoop生态链如hive pig,对bson支持不够
调研了下avro格式,其文件组织方式如下:
相比于bson的文件格式,最重要变化是多了个sync marker字段,这是个边界符,意义等同于TextInputFormat里的换行符,这样就可以对文件正常进行分割了,读取时从本区间第一个sync marker后开始读,为了保证所有记录读且被读了一次,读到区间尾时,应该继续读下去,直到读完该block。avro是有范式的,bson是无范式的,倘若能把mongodb里的数据以一定范式表达出来,avro只需要在文件头储存格式信息就可以了,而bson的每条记录都必须存储字段信息,这样能节省大概百分20的空间。使用avro的成本是bson到avro的格式转换,实践下来,单cpu能达到30M/S,还是能接受的范围。