Redis GEO = 用 ZSet + GeoHash,把二维经纬度问题,降维成一维 score 的范围查询问题
核心只有三点:
二维 → 一维(降维)
GeoHash 编码
ZSet 的 score 范围查询
一、为什么 GEO 不直接存经纬度?
经纬度是 二维坐标 (lat, lon) ,而 Redis 最擅长的是一维有序数据(ZSet)。
Redis 的思路是:
把二维空间映射成一条"近似保持空间关系的一维曲线"
二、GeoHash 是怎么工作的?
第一步:对二维地图做"区间划分"
先看全球范围:
| 维度 | 范围 |
|---|---|
| 经度 | -180 ~ 180 |
| 纬度 | -85.05112878 ~ 85.05112878 |
GeoHash 的做法是:
不断 二分经度区间
再 二分纬度区间
经度、纬度交替进行
第二步:区间编码(GeoHash 编码)
二进制还不方便存,于是:
每 5 位二进制 → 1 个 Base32
Redis 内部 不是存字符串形式的 GeoHash,而是:
把 GeoHash 转成一个 64 位整数
为什么 GeoHash 能"找附近"?
关键特性:
地理位置相近的点,GeoHash 编码也大概率相近
GEORADIUS / GEOSEARCH 是怎么查附近的?
以「查 5km 内的点」为例:
根据中心点算 GeoHash
得到中心点的 GeoHash 区间。
找"周围 8 个格子"
GeoHash 会有边界问题
所以 Redis 会算:
当前格子
上下左右 + 四个角(共 9 个)
转成 score 范围查询
精确距离过滤(很重要)
GeoHash 是 近似 的
所以 Redis 最后一步会算真实球面距离:
所以结果是 精确的
三、场景建模:滴滴叫车到底在查什么?
当你在滴滴上点「叫车」时,系统核心要做三件事:
实时上报车辆位置
从当前位置附近找车
按距离排序,选最近的几辆
这三件事,Redis GEO 刚好全部覆盖