下面,对近期的工作进行个总结。
最开始是实现了geohash+快速选择算法。geohash是使用32位字符串进行编码,编码长度可以进行控制。查询时,找到当前格子周围的8个格子,对这9个格子中的所有点进行快速选择算法,选择符合调节的K个节点。
此方法对随机生产的千万级别的数据能保证查询效率,但是实际情况中节点是不均匀分布,有些格子节点比较多。因此考虑到实际情况,该算法是不行的。
接下来实现了geohash+KD树的方法。对于每个格子,建一棵kd树,将当前格子和周围8个格子中的节点加入到kd树中。查询时,找到节点所在格子,对这个格子对应的KD树进行查找即可。
此方法对查找部分进行了优化,速度会比上面的方法效率高。但是存在两个问题,一是内存消耗大;二是考虑到实际情况,格子大小该如何控制。其实次方法对实际数据进行测试后,取一个最优的经验值还是可以用的,只是可扩展性比较差。
最后实现了自适应格子算法+字典树。每存入一个节点,就要一层一层的更新格子中节点的数量。查询时,一层一层的找,找到格子大小合适为止,然后再找到当前大小的格子的周围8个格子,对这9个格子中的数据进行查找最近的K个节点即可。找周围8个格子的方法与上面geohash的实现方法一样,字典树是用来存储和更新格子中节点的数量的(此处还有个可以优化的地方,可以在字典树中再存储8个指针指向周围8个格子的邻居节点,这8个指针是当此格子第一次被查找到时才进行赋值的。以后再查找到此格子时就可以直接找到此格子周围的邻居节点,就不用再调用函数进行查找了)
此方法自动进行格子的分裂和合并,即使数据分布不均匀也不会影响效率。
至于纯真ip数据库,网上找到一份代码可以直接将数据库中的数据保存到一个本地文档中,然后可以使用libcurl库像百度地图api发请求将ip转换为经纬度。(ps:保存到本地中的ip数量是十万级别的,每个ip下面还会有很多子ip地址,可是子ip地址怎么获取呢?难道要随机生成?)
反正最后实现的方法是可以应用到实际情况中去的,这个测试工作感觉没什么意义。
后面的工作重点是将代码好好整理,结合局部网络瘫痪情况,将上层应用接口好好整整。