读入数据,冲洗数据,进行交换和输出,这是MapReduce的一个数据库,比如168的,或者是更小的,可以读入到一个Map的过程,通过排序进入Reduce的阶段,这个过程中间的过程我们不用去管它,但是我们可以写自定义的代码,你排序的规则是什么,我们一般这种Key可能是一个值。但是如果你现在记录一个位置,记录一个值的话,你想要把一堆进行排序,比如先排横坐标,再排纵坐标,这种排序需要自己写相应的自定义排序的算法。这个也并不复杂,也就是一个接口实现各相应的功能就够了。这是一个Reduce过程,会生成一份结果,比如我们做栅格处理的时候,有好几个栅格数据,最后需要加加减减,做成这种计算,最后生成一份结果,我们就只能要一个Reduce。或者是你有两个Reduce更好,中间会把排序的数据传到不同的Reduce的节点上去。当然,时间会降低,因为Reduce实际上回洗过程是非常耗时的过程,如果数据量很大的情况下,你的输出又很大的情况下,其实Reduce非常耗时,这也是我们的一个经验,那就看你自己的选择了,或者是一个根本就没有Reduce的过程也可以,你如果一次性把它读出来,处理了,写出去,存在一个文件里面也可以。这是一个基本的示例,这么一个过程,我们选的是两份文件。比如我们假设一行文件被加入到一个Map的过程,当它读出来的时候是How有1个,Browe有1个,Does有1个,如果说How有2个了,可以经过经过排序,把Key相同的放在一起。这种数据流程看起来非常简单,但是你开动脑筋就会发现,其实可以做很多事情,这是一个经典的例子,算一个文档里面哪些字符有多少个是最经典的一个例子。
这是我自己做的一个实验,Hadoop这个东西也不是万能的,至少你不能把那个数据直接放上去读。做的实验就是用MR来做自动构面计算的实验,还有就是用GIS做检索的实验。第一个很简单,一堆点构成一个拓扑网络,可以通过左转或者是右转的方式,从任何一个点出发,按照那种算法的要求,你可以构成一个面起来。它的好处就是说,不管你选哪一个点触发,其实与其他的点没有什么关系的。如果你写一个程序,你的那个程序上同时运行10个这样的程序也是可以的,也就是它可以切分这个任务。如果你有1万个点,你只有一台机器,那么你就是1万个点,如果你有这样一个机制,就是说你有5台机器,每个机器上分两千个点,5个节点同时来做,所用的时间肯定比1万个点到一台机器上做的要好得多。这个过程就是,我用了两个MapReduce的过程,第一个是把它做拓扑网络,把这个数据读进去可能大家比较担心,不是原生的这种,还是文本文件式的,记录一下你这个点的POI是多少,是用Java编写的,因此可以直接调用Java的API,或者是AO的Java的API,是一点问题没有的,可以继续调用我们基础数据库的信息,把和它相关联的找出来,然后自己去记录一下在输出的地方记录一下我要哪些点,和哪些边相连,就构成一个拓扑网络了。我把上面的一堆结果重新读取出来,选取一个点开始,所不同的就是,我可能有一万个点,现在分到四五台机器上,现在每个点做面,做的也不是一个面,最终还是从我这个点出发,我们可能循环多少个点,最终形成一个面,记录的是这个东西。最终它的结果我们可能把它再记录一下,再通过其他的一些,把这几个点找到,把这个面构成起来。因此,具体的处理逻辑还是需要我们自己来实现的,这个是非常简单的一个例子。
每天几百万条的POI需要保存到数据库中,我觉得这个东西很现实。你做电子商务的,阿里巴巴或者是京东,每天不止几百万条,每天的交易量有几千万条,如果把几千万条的地址地名变成地址,你怎么去存?你把它用点的形式去存吗?是搞不定的。你无时无刻都在写数据库,你写是一回事,还面临着去读它的问题。还有一个问题就是说,我们现在基站更多的时候到了上亿条。我看到一个说法,关系数据库的表,大概在1亿条的时候就跑不动了,效率非常低。遇到的问题就是没有一种空间数据库能够满足这种要求或者是需要。
我们解决一下检索很慢的问题,使用什么样的数据库来存储这些数据?这些数据库是空间形式吗?比如说你把它还存储一个点,如果是通过这样的点来描述,怎么样做这种查询呢?比如说哪怕是你的ArcGIS或者是超图,从其中一个点找特定的点,耗的时间是很长的。我们还有没有其他的更加好的、更有效的空间检索方式?我们通过Geohash的方式方式存储这些点,把一个空间分成4份,比如说左上角是00,右下角是11,最大范围分成4块,比如说这个往下继续分,01继续加上00、11,可以无限的分下去。我们可以注意一下,实际上是对半分,哪怕是整个地球的范围,分布到多少次,就可以把你这个格子缩小到一个足够小的程度,完全能够标注POI点的程度。如果我们把地球上的一个点精度也这样分,因为我们用的是WGIS84,因为你使用的是84这个坐标,从180到180,-90到90的范围,划分到这种范围就分,横向上你去把它写成这些0101的值,纵向上也把它做这些值。然后把它们横向上的,就是说奇位数为横坐标,偶位数纵坐标,最终就能够得到一个比较短的值。大家感兴趣的话可以自己到网上去查一下这种方式。这是5位编码,也就是画了10次网格之后的结果。这个表示了一个范围,其实它的范围很大,里面更大的,从6位其实范围已经很小了。如果你到8位的时候,实际上9个格子就已经可以描述一栋房子了。我们自己做过一个计算,9位的时候,格子的长度和宽度是不一样,不是一个正方形的格子,是一个长方形的格子。到第9位的时候,每个格子的长度和宽度大概就是0.3米左右,也就是说,精度是绝对足够的,就是用点来描述地球上的位置也是空的。现在只不过是用递进的方式,把这个位置划到一个小的方框里面来。下面检索的问题就解决了,其实检索的问题很好解决。我们可以看到,如果对于8位的数字来讲,其实前7位的值都是一样的,就是第8位不一样。如果我们用这种方式去存储数据,将来你检索的时候怎么来检索?就是判断它的前面有几位相同。比如说我这里有一个点,我检索一下大概是200米,周围有哪些其他的POI点的存在,我先把自己的点大概编到一个7位就足够了。然后我就去在整个数据库里面找一项和我前面6位相同的这些格网有哪些,也就是找它周围的这么8个,或者甚至找更大范围相同的都可以,可以把这些格网找出来。当然一个问题就是说,不可能精确到200米,因为格网的宽度不是很固定的。比如我们到了第9级的0.3米,到了第8级的时候可能有13米多,更大一点的,可能有40多米,1千多米,范围不是一个固定的。但是,通过这种方式,足够让你在一个海量的数据库里面检索区域内相对较少的点出来,然后你再去判断它的距离,判断两个经纬度之间的距离,如果超过了200米,那你就不要了,如果小于200米就包含它。我们通过这种方式,把一个空间判断的问题转换成了一种匹配的,相对来讲较为简单的这么一种问题。就是说既能够解决海量POI数据的存储,又能解决它的检索,要不然你几百万、上千万的点存到里面去,是很难再查出来的,或者查出来的速度满足不了。当然最后查出来的速度取决于你有多少台机器,也不用说非常快,也不用说你现在输入命令进去以后,至少可能是40秒或者是1分钟左右。至少我自己在测那些速度的时候,基本上都是1分钟。如果做事后的分析,做技术查询也是足够的。
MapReduce和Hadoop与我们GIS没有太直接的关系,就是一个框架。你怎么去使用它完全取决于你自己的创造力、想法和思路。它适用的范围是我前面讲到的三个数据的存储、计算分析,解决海量地址的查询,或者是其他一切可以划分为多个问题来解决的这些技术问题。其中技术处理方面的问题都可以,我看到不少的论文都是这样来解决的,不会直接拿Hadoop来当做一个普通的数据链,去存储数据和切图,不会那样做,还是一个可并行计算的工具。