GeoHash——滴滴打车如何找出方圆一千米内的乘客?

简介: GeoHash——滴滴打车如何找出方圆一千米内的乘客?

背景

不知道大家是否思考过一个问题,在一些场景下(如大家在使用高德地图打车的时候,邻近的司机是如何知道你在他的附近并将你的打车通知推送给他去接单的?)是如何实现的?

一般来讲,大家也许会想到,首先肯定需要知道每位乘客的经纬度(lng,lat),也即是二维坐标(当然这是在绝对理想的情况,不考虑上下坡度)。

而在知道了经纬度之后,一个暴力简单且容易想到的思路就是将经纬度这个二元组都存放在一个数组当中,然后当我们需要拿到离我们规定范围内的用户(如获取当前位置方圆百米内正在打车的乘客),我们就可以去遍历维护的那个数组,以此去判断数组中的经纬度与自己所在经纬度的距离,然后判断是否在范围内。

显然这种方法一定是能够达到目的的,但是值得注意的点是,维护的数据量一般来讲是海量的,因此如果每次都需要遍历所有数据去进行计算,那这计算量以及存储量目前是无法满足的。那如何在此基础上去优化性能呢??那么这个内容就是本篇文章主要想探讨的问题......


GeoHash基本原理介绍

首先我想先介绍一下GeoHash这种算法基本原理,再讨论如何进行应用。

对于每一个坐标都有它的经纬度(lng,lat),而GeoHash的原理就是将经纬度先通过一个二分的思路拿到一个二进制数组的字符串,然后再通过base32编码去进行压缩存储。

举一个例子,比如经纬度为(116.3111126,40.085003),对其进行二分步骤如下:


   **bit** | **left**      | **mid**       | **right**     |
| ------- | ------------- | ------------- | ------------- |
| 1       | -180          | 0             | 180           |
| 1       | 0             | 90            | 180           |
| 0       | 90            | 135           | 180           |
| 1       | 90            | 112.5         | 135           |
| 0       | 112.5         | 123.75        | 135           |
| 0       | 112.5         | 118.125       | 123.75        |
| 1       | 112.5         | 115.3125      | 118.125       |
| 0       | 115.3125      | 116.71875     | 118.125       |
| 1       | 115.3125      | 116.015625    | 116.71875     |
| 0       | 116.015625    | 116.3671875   | 116.71875     |
| 1       | 116.015625    | 116.19140625  | 116.3671875   |
| 1       | 116.19140625  | 116.279296875 | 116.3671875   |
| 0       | 116.279296875 | 116.323242188 | 116.3671875   |
| 1       | 116.279296875 | 116.301269532 | 116.323242188 |
| 0       | 116.301269532 | 116.31225586  | 116.323242188 |



```纬度步骤:

bit | left | mid | right |
| ------- | --------- | ------------- | ------------- |
| 1 | -90 | 0 | 90 |
| 0 | 0 | 45 | 90 |
| 1 | 0 | 22.5 | 45 |
| 1 | 22.5 | 33.75 | 45 |
| 1 | 33.75 | 39.375 | 45 |
| 0 | 39.375 | 42.1876 | 45 |
| 0 | 39.375 | 40.78125 | 42.1876 |
| 1 | 39.375 | 40.078125 | 40.78125 |
| 0 | 40.078125 | 40.4296875 | 40.78125 |
| 0 | 40.078125 | 40.25390625 | 40.4296875 |
| 0 | 40.078125 | 40.166015625 | 40.25390625 |
| 0 | 40.078125 | 40.1220703125 | 40.166015625 |
| 0 | 40.078125 | 40.1000976563 | 40.1220703125 |
| 0 | 40.078125 | 40.0891113282 | 40.1000976563 |
| 1 | 40.078125 | 40.0836181641 | 40.0891113282 |

其思路就是不断二分,如果原本值大于mid那本bit位就是1,以此往下递归,最终,我们递归二分得到纬度方向上的二进制字符串为 101110010000001,长度为 15 位

那此时就拿到了30bit位的字符串,然后就开始进行拼接

结合经度字符串 110100101011010和纬度字符串 101110010000001,我们遵循先经度后纬度的顺序,逐一交错排列,最终得到的一维字符串为 11100 11101 00100 11000 10100 01001.

然后再进行Base32编码,主要步骤就是首先会维护一个0-9A-Za-z中32个字符的数组,如:['a','b','1','2','3','4','5','6','7','A'...],然后再将这30位的字符串每五个一组(正好覆盖0-31的索引)去索引到指定字符以此拿到30/5=6位的base32编码去进行存储。

ps:注意并不一定是必要将经纬度都二分得到15位长度,多少位都可以,只是精度越高结果也就越精确,但是算力就越大,只需在此做出权衡即可


GeoHash如何应用到这个问题当中?

上面讲到了可以通过GeoHash将经纬度转换成bit位的字符串,那么怎么进行应用呢,其实答案很明显,其实如果经纬度越接近,他们的前缀匹配位数也就越长,比如

image.png
通过这个思路我们就比较容易得到我们想要的范围内的乘客了。

遗留问题

但是其实仅仅如此是不够的,因为一个base32其实是覆盖了一片区域的,它并不是说仅仅代表一个精确的ip地址,那这其实就衍生出了一些问题,就比如

image.png
,用geohash那结果显然是AB更近,但是实际上A与B的距离比AE、AC、AD都远。这其实是一个边缘性的问题........后续我会更新如何去避免这种问题的出现

相关文章
|
SQL 存储 关系型数据库
对线面试官 - 如何理解MySQL的索引覆盖和索引下推
索引下推是MySQL 5.6引入的优化,允许部分WHERE条件在索引中处理,减少回表次数。例如,对于索引(zipcode, lastname, firstname),查询`WHERE zipcode='95054' AND lastname LIKE '%etrunia%'`时,索引下推先过滤zipcode,然后在索引中应用lastname条件,降低回表需求。索引下推可在EXPLAIN的`Using index condition`中看到。
1972 0
对线面试官 - 如何理解MySQL的索引覆盖和索引下推
|
2月前
|
人工智能 自然语言处理 监控
阿里云百炼大模型平台全指南:定位、模型、场景与计费详解
2026年,阿里云百炼(Model Studio)已从单一模型服务平台,升级为集模型调用、微调、智能体开发、知识库构建、应用部署于一体的全链路MaaS(Model as a Service)平台。它聚合了150+款优质大模型,提供零代码/低代码与高代码双模式开发能力,搭配灵活的计费体系,成为个人开发者、中小企业与大型企业落地AI应用的首选平台。本文将从平台定位、模型矩阵、核心能力、落地场景、计费方案与选型建议等维度,全面解读2026年阿里云百炼大模型平台。
865 0
|
9月前
|
人工智能 自然语言处理 API
AI战略丨阿里云百炼,让企业应用大模型更简单
企业级的大模型开发,是一个复杂的过程,阿里云百炼平台以更经济高效的模型推理服务和更智能灵活的模型定制能力,让更多的企业以更低的门槛、更好的效果使用大模型产品赋能业务。
AI战略丨阿里云百炼,让企业应用大模型更简单
|
人工智能 Rust 自然语言处理
37.1K star!AI模型全能工具箱,这个开源项目让智能体开发更简单!
"Awesome MCP Servers 是当前最全面的模型上下文协议服务器集合,为AI开发者提供开箱即用的工具链支持。通过标准化协议实现AI模型与各类资源的无缝对接,堪称智能体开发的瑞士军刀!"
751 7
|
7月前
|
XML JSON 定位技术
地理编码-逆地理编码-经纬度解析-逆经纬度解析API接口的运用
本文详解地理编码(地址→坐标)与逆地理编码(坐标→地址)技术,覆盖实时定位、车辆追踪、地图搜索与导航等应用场景;对比高德(GCJ02)与百度(BD09)地图API的参数、返回结构及坐标系差异,助力开发者快速集成位置服务。
1339 1
|
人工智能 自然语言处理 安全
新浪微博AIGC业务应用探索-AIGC应用平台助力业务提效实践
本次分享围绕AIGC技术在新浪微博的应用展开,涵盖四个部分。首先分析AIGC为微博带来的机遇与挑战,特别是在内容安全和模型幻觉等问题上的应对策略;其次介绍通过工程架构快速实现AIGC技术落地的方法,包括统一部署模型和服务编排;接着展示AIGC在微博的具体应用场景,如评论互动、视频总结和智能客服等;最后展望未来,探讨大模型的发展趋势及其在多模态和特定业务场景中的应用前景。
|
存储 定位技术 数据库
探索GeoHash:滴滴打车定位技术揭秘
【10月更文挑战第28天】
1860 5
|
存储 关系型数据库 MySQL
什么是覆盖索引?
本章主要讲解了索引覆盖和回表的相关知识
526 0
|
SQL 关系型数据库 MySQL
详解MySQL覆盖索引、索引下推
1.覆盖索引 1.1.概述 覆盖索引,是为了避免“回表查询”,从而降低查询耗时的一种使用索引的方法,所以要聊覆盖索引首先我们要知道什么是"回表查询,“回表查询”是因为MySQL的索引结构决定的,是因为非聚集索引要找聚集索引拿数据而出现的现象,所以我们又要先了解MySQL中的聚集索引和非聚集索引。 文章的脉络就是先聊聚集索引、非聚集索引是怎么带来了“回表查询”的问题,然后怎么用用覆盖索引解决这个问题。
2694 0
|
Java Maven Spring
创建一个spring boot的3种方式
创建一个spring boot的3种方式
563 6

热门文章

最新文章