https://matt.sh/redis-geo

http://antirez.com/latest/0

http://invece.org/

https://github.com/davidmoten/geo/blob/master/src/main/java/com/github/davidmoten/geo/GeoHash.java

http://www.movable-type.co.uk/scripts/latlong-db.html

http://www.basistech.com/wp-content/uploads/2014/06/oss-2011-smiley-geospatial-search.pdf

https://github.com/mattsta/geohash-int/commits/matt

https://dzone.com/articles/designing-spacial-index#footnote-6-ref

http://www.ibm.com/developerworks/library/j-spatial/

https://en.wikipedia.org/wiki/Angular_diameter

https://en.wikipedia.org/wiki/Angular_displacement

http://gis.stackexchange.com/questions/18330/would-it-be-possible-to-use-geohash-for-proximity-searches/92331

https://github.com/yinqiwen/ardb/blob/d42503/src/geo/geohash_helper.cpp

https://github.com/yinqiwen/ardb/wiki/Spatial-Index

https://github.com/yinqiwen/geohash-int

https://en.wikipedia.org/wiki/Geohash

http://gis.stackexchange.com/questions/115766/fastest-strategy-for-proximity-searches-in-sql-server-2012

https://en.wikipedia.org/wiki/Z-order_curve

https://en.wikipedia.org/wiki/Geohash

https://matt.sh/redis-architecture-diagram

https://matt.sh/redis-geo#_origin-story

https://github.com/antirez/redis/blob/356a6304ec77783e7fdaf00668a09dc293b810a0/src/geo.c

http://cristian.regolo.cc/2015/07/07/introducing-the-geo-api-in-redis.html

http://redisplanet.com/redis/under-the-hood-of-redis-hash-part-2-and-list/

http://redisplanet.com/redis/under-the-hood-of-redis-hash-part-1/

http://www.basistech.com/wp-content/uploads/2014/06/oss-2011-smiley-geospatial-search.pdf

geohash算法原理及实现方式

GeoHash核心原理解析

https://dzone.com/articles/designing-spacial-index

http://iamzhongyong.iteye.com/blog/1399333

http://tech.idv2.com/2011/06/17/location-search/

http://blog.sina.com.cn/s/blog_62ba0fdd0100tul4.html

https://github.com/kungfoo/geohash-java

http://101.96.10.62/geomesa.github.io/assets/outreach/SpatioTemporalIndexing_IEEEcopyright.pdf

https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html

https://docs.mongodb.com/manual/core/geospatial-indexes/

https://en.wikipedia.org/wiki/Spatial_database#Spatial_index

https://en.wikipedia.org/wiki/Geographic_coordinate_system

https://en.wikipedia.org/wiki/Haversine_formula

http://geohash.org/site/tips.html

https://www.researchgate.net/publication/259633148_Review_of_Spatial_Indexing_Techniques_for_Large_Urban_Data_Management

http://101.96.10.63/www.comp.nus.edu.sg/~ooibc/spatialsurvey.pdf

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.140.7080&rep=rep1&type=pdf

http://101.96.10.61/people.cs.vt.edu/~asandu/Public/Qual2005/Q2005_skjellum.pdf

http://gis.stackexchange.com/questions/115766/fastest-strategy-for-proximity-searches-in-sql-server-2012

http://gis.stackexchange.com/questions/108557/advantages-of-r-trees-in-comparison-to-geohashes?rq=1

http://www.movable-type.co.uk/scripts/latlong.html

https://en.wikipedia.org/wiki/Great-circle_distance

https://en.wikipedia.org/wiki/Haversine_formula

https://en.wikipedia.org/wiki/Angular_displacement

http://www.mathsisfun.com/algebra/trig-inverse-sin-cos-tan.html

http://math.rice.edu/~pcmi/sphere/drg_txt.html

http://stackoverflow.com/questions/18324524/what-are-some-efficient-geohash-bounding-box-coverage-algorithms

https://en.wikipedia.org/wiki/Image_resolution

======================================================================

Absolutely you can. And it can be quite fast. (EDIT: The intensive computation bits can ALSO be distributed)

There are several ways, but one way that I've been working with is in using an ordered list of integer-based geohashes, and finding all the nearest neighbour geohash ranges for a specific geohash resolution (the resolution approximates your distance criteria), and then querying those geohash ranges to get a list of nearby points. I use redis and nodejs (ie. javascript) for this. Redis is super fast and can retrieve ordered ranges very quickly, but it can't do a lot of the indexing query manipulation stuff that SQL databases can do.

The method is outlined here: https://github.com/yinqiwen/ardb/blob/master/doc/spatial-index.md

But the gist of it is (to paraphrase the link):

  1. You store all your geohashed points in the best resolution you want (max usually 64bit integer if that's accessible, or in the case of javascript, 52bits) in an ordered set (ie. zset in redis). Most geohash libraries these days have geohash integer functions built in, and you'll need to use these instead of the more common base32 geohashes.
  2. Based on the radius you want to search within, you need to then find a bit depth/resolution that will match your search area and this must be less than or equal to your stored geohash bit depth. The linked site has a table that correlates the bit depth of a geohash to its bounding box area in meters.
  3. Then you rehash your original coordinate at this lower resolution.
  4. At that lower resolution also find the 8 neighbour (n, ne, e, se, s, sw, w, nw) geohash areas. The reason why you have to do the neighbour method, is because two coordinates nearly right beside each other could have completely different geohashes, so you need to do some averaging of the area covered by the search.
  5. Once you get all the neighbour geohashes at this lower resolution, add to the list your coordinate's geohash from step 3.
  6. Then you need to build a range of geohash values to search within which cover these 9 areas. The values from step 5 are your lower range limit, and if you add 1 to each of them, you'll get your upper range limit. So you should have an array of 9 ranges, each with a lower limit and and upper geohash limit (18 geohashes in total). These geohashes are still in that lower resolution from step 2.
  7. Then you convert all 18 of these geohashes to whatever bit depth/resolution you have stored all your geohashes in your database in. Generally you do this by bitshifting it to the desired bit depth.
  8. Now you can do a range query for points within these 9 ranges and you'll get all points approximately within the distance of your original point. There will be no overlap so you don't need to do any intersections, just pure range queries, very fast. (ie. in redis: ZRANGEBYSCORE zsetname lowerLimit upperLimit, over the 9 ranges produced in this step)

You can further optimize (speed wise) this by:

  1. Taking those 9 ranges from step 6 and finding where they lead into each other. Usually you can reduce 9 separate ranges into about 4 or 5 depending on where your coordinate is. This can reduce your query time by half.
  2. Once you have your final ranges, you should hold them for reuse. The calculation of these ranges can take most of the processing time, so if your original coordinate doesn't change much but you need to make the same distance query over again, you should keep that ready instead of calculating it everytime.
  3. If you're using redis, try to combine the queries into a MULTI/EXEC so it pipelines them for a bit better performance.
  4. The BEST part: You can distribute steps 2-7 on clients instead of having that computation done all in one place. This greatly reduces CPU load in situations where millions of requests would be coming in.

You can further improve accuracy by using a circle distance/haversine type function on the returned results if you care much about precision.

Here's a similar technique using ordinary base32 geohashes and a SQL query instead of redis: https://github.com/davetroy/geohash-js

I don't mean to plug my own thing, but I've written a module for nodejs&redis that makes this really easy to implement. Have a look at the code if you'd like: https://github.com/arjunmehta/node-geo-proximity

Redis GEO ,GEOHASH,Spatial_index的更多相关文章

  1. 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法

    "为什么这个功能用不了?" 程序员:"清一下缓存" 上篇洞悉系列文章给大家详细介绍了MySQL的存储内幕:洞悉MySQL底层架构:游走在缓冲与磁盘之间.既然聊过 ...

  2. 常见的Redis面试"刁难"问题,值得一读

    Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog.G ...

  3. Redis的Python实践,以及四中常用应用场景详解——学习董伟明老师的《Python Web开发实践》

    首先,简单介绍:Redis是一个基于内存的键值对存储系统,常用作数据库.缓存和消息代理. 支持:字符串,字典,列表,集合,有序集合,位图(bitmaps),地理位置,HyperLogLog等多种数据结 ...

  4. 分布式缓存技术redis学习系列(五)——redis实战(redis与spring整合,分布式锁实现)

    本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...

  5. 项目分布式部署那些事(1):ONS消息队列、基于Redis的Session共享,开源共享

    因业务发展需要现在的系统不足以支撑现在的用户量,于是我们在一周之前着手项目的性能优化与分布式部署的相关动作. 概况 现在的系统是基于RabbitHub(一套开源的开发时框架)和Rabbit.WeiXi ...

  6. redis虚拟机模拟集群,节点,增加多端口命令

    Redis启动多端口,运行多实例 使用redis在同一台机器上,启用多个端口,实现多个实例,完成集群的模拟实现. 启动多实例 redis默认启动端口为6379,我们可以使用 --port 来指定多个端 ...

  7. redis 五种数据结构详解(string,list,set,zset,hash)

    redis 五种数据结构详解(string,list,set,zset,hash) Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存 ...

  8. python_way ,day11 线程,怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)

    python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...

  9. Redis入门(优势,环境,字符串,哈希,列表)

    Redis从它的许多竞争继承来的三个主要特点: Redis数据库完全在内存中,使用磁盘仅用于持久性. 相比许多键值数据存储,Redis拥有一套较为丰富的数据类型. Redis可以将数据复制到任意数量的 ...

随机推荐

  1. Struts2 的ModelDriven理解

    以UserAction为例,当UserAction实现了ModelDriven接口之后,与该接口相关的默认配置的拦截器会在拦截请求之后判断该请求是将要被UserAction处理而且UserAction ...

  2. JavaScript 之 走马灯

    1.原理分析:首先截取字符串的最后一位用Last表示,再截取剩余字符串用Rest表示,拼接字符串Last + Rest, 此事字符串是不会动的,还需要一个函数setInterval(javascrip ...

  3. POJ 3156 - Interconnect (概率DP+hash)

    题意:给一个图,有些点之间已经连边,现在给每对点之间加边的概率是相同的,问使得整个图连通,加边条数的期望是多少. 此题可以用概率DP+并查集+hash来做. 用dp(i,j,k...)表示当前的每个联 ...

  4. char, signed char, and unsigned char in C++

    关于这三者的区别stackoverrflow里有一个答案是这样说的: 3.9.1 Fundamental types [basic.fundamental] 1 Objects declared as ...

  5. 搭建EJB3开发环境

    开发工具:myeclipse8.5.antjdk:1.5容器:jboss4.2.31.安装jboss:解压.配置JBOSS_HOME环境变量2.测试安装是否成功:启动%JBOSS_HOME%\bin\ ...

  6. 基于HTML5+CSS3的图片旋转、无限滚动、文字跳动特效

    本文分享几种基于HTML5+CSS3实现的一些动画特效:图片旋转.无限滚动.文字跳动;实现起来均比较容易,动手来试试! 一.图片旋转 效果图如下: 这个效果实现起来其实并不困难.代码清单如下: < ...

  7. 深入理解:Android 编译系统

    一,简介: Android Build 系统是用来编译 Android 系统,Android SDK 以及相关文档的一套框架.众所周知,Android 是一个开源的操作系统.Android 的源码中包 ...

  8. Java Proxy

    Client---->Interface A --        -- 代理类     Class AImpl 代理类是动态生成的,借助Proxy类和InvocationHandler接口进行实 ...

  9. Android系统在新进程中启动自定义服务过程(startService)的原理分析

    在编写Android应用程序时,我们一般将一些计算型的逻辑放在一个独立的进程来处理,这样主进程仍然可以流畅地响应界面事件,提高用户体验.Android系统为我们提供了一个Service类,我们可以实现 ...

  10. 创建XML文档结构

    static void CreateXML(string outputPath) { XmlDocument _xmlDoc = new XmlDocument(); string _xmlNode ...