一、mongo基本概念
请参考我之前的一篇文章:mongo基本概念 和使用,也可通过官方文档或者别的博客进行了解。
二、数据背景和业务诉求
(看到这里,笔者认为您是对mongo已经有所了解了)
2.1 目标数据
鉴于公司数据安全要求,这里不对数据具体内容做描述。源数据通过一个中转集群拷贝至我们的生产环境hadoop集群中,业务数据分为几块大的领域,但是每个领域的数据结构基本相同。主要是三个事实表(这里用r1,r2,r3代称)和若干个维度表。维表数据量大概在几万条左右,每天以overwrite方式刷新对应hive表。三个事实表按照顺序:r1=>r2=>r3,依次是前者一对多后者。r1可以通过主键r1id与r2、r3进行join,r2可以通过主键r2id与r3进行join,所以r3中包含r1id和r2id。三个事实表按照每天增量的方式从源端集成,以日分区入库Hive分区表。每天增量数据依次为:r1-400万、r2-3000万、r3-3亿,基本每层十倍的比例。截至我着手开发时,历史数据有6个月的数据,要处理的一块领域的历史数据大概为500亿。
2.2 业务需求
源端数据集成至hadoop平台中,不同的业务部门需要获取自己业务领域的数据进行数据聚合处理、明细查询,以及时对对应业务产品做质量分析、性能校正等方面用途。
数据跨天的集成性质,当天集成的都是昨天生成的数据,这本身就是离线数据处理,所有一些聚合运算可以放Hive中处理好后,落地一个结果表。再通过协作工具sqoop或者相应jdbc程序export至RDBMS或者NOSQL数据库提供查询服务。
除了聚合结果,有时候业务场景是需要查询明细数据的。如果直接用Hive以jdbc方式提供查询,将无法达到实时查询的需求。对此,在结合源数据的关系模型和mongodb的适用场景后,我们选型Mongo,利用mongo支持的层级文档特性构建一个RDMBS概念中的宽表。
三、需求目标
3.1 快速完成海量历史数据的入库初始化和后期日增长数据的增加
3.2 实现海量嵌套数据快速检索查询,根据业务需要返回需要的数据
四、入库实践
笔者在着手做这个mongo入库的时候,与Mongo也是初遇。当时,既不懂mongo的架构原理,也不清楚基本的操作。所以,本文主要是以时间轴线,来阐述下个人的踩坑经历。直到现在,我对Mongo也只是达到一知半解的地步,各位看官发现不对的地方请及时指正。
废话不多说,进入实践正题。
pit 1: 现在有源数据,如何将数据写入Mongo?
在啥都不会的情况下,不要慌(虽然当时比梅西还慌得一批),先花点时间大概了解下架构原理、基本操作和对应api。
mongodb的基本概念和操作可参考mongo基本概念 和使用或者官方文档。建议自己装个单机版的,然后按照官方文档敲一遍crud,基本就算入门了。
从hive往mongo写数据,不要着急操作,还要进一步分析。要入库的数据主要是三个事实表(本文只讨论这三个表),这三个表都是每天增量的方式进行集成。通过数据发现,r1层与r2层或者r2层与r3层都是错位的,比如当前日期为2018-07-01,r1层(r1表)在这天的某些数据所对应的子项r2层数据并不一定也在当天分区,可能会滞后到明天、后天甚至更多天,r3的情况同理。在这种情况下,数据入mongo就不能提前先整合成层级文档一次写入了。所以需要按照层级顺序依次写入1,2,3层数据,不过这也有个大问题,具体后文再论述。
明确写入顺序,再研究具体操作,笔者是先在mongo shell中实现功能,再转化成对应api进行批量操作的。
在公司的大兄弟们可以直接用公司的机器进行操作,在校或者没环境的同学可以点击这里,参考文档搭建个单机进行操作。
mongo shell(或者第三方客户端软件):
写入第一层数据,提前看了操作文档后非常简单,直接用insert操作命令。
db.embedded_collection.insertMany(
[
{_id:NumberLong(123),
"r1_field1":"r1_value1_1",
"r1_field2":"r1_value2_1",
"r1_field3":"r1_value3_1",
"r1_field4":"r1_value4_1",
"r1_field5":"r1_value5_1"
},
{"_id":NumberLong(456),
"r1_field1":"r1_value1_2",
"r1_field2":"r1_value2_2",
"r1_field3":"r1_value3_2",
"r1_field4":"r1_value4_2",
"r1_field5":"r1_value5_2"
},
{"_id":Number