GEOSEARCH 并不比 GEORADIUS 查询效率更高,但通过减少 RTT、支持矩形搜索、统一单位语义,显著降低端到端延迟和出错率;原生支持 FROMMEMBER 避免两次查询,BYBOX 实现原子矩形覆盖,单位强制小写且语义明确,底层仍逐点计算 Haversine 距离。

GEOSEARCH 并不比 GEORADIUS “查询效率更高”——它不加速单次球面距离计算,但通过减少 RTT、支持矩形、统一单位语义,显著降低端到端延迟和出错率。
FROMMEMBER 省掉一次 GEOPOS 查询,避免两轮 RTT
GEORADIUS 必须传 FROMLONLAT,如果想以用户 u123 为圆心查附近人,得先发 GEOPOS 拿坐标,再拼 GEORADIUS,两次网络往返。并发高时容易因坐标过期或精度丢失导致结果漂移。
而 GEOSEARCH 原生支持 FROMMEMBER u123,Redis 内部直接从 ZSet score 解码经纬度,一次命令搞定:
GEOSEARCH users:geo FROMMEMBER u123 BYRADIUS 500 m WITHDIST ASC COUNT 10
- 适用于社交匹配、骑手调度等对“实时性+一致性”敏感的场景
- 不用在应用层做
if err != nil { ... }处理 GEOPOS 失败的情况 - 避免浮点数序列化/反序列化引入的微小误差(比如
116.48321存成116.48320999999999)
BYBOX 矩形搜索不是“凑出来的”,而是原生能力
用 GEORADIUS 实现矩形区域(比如地图瓦片加载、电子围栏),只能靠 4 次圆形查询 + 应用层去重,漏边角、性能差、逻辑复杂。
GEOSEARCH 的 BYBOX 2000 1500 m 是原子操作:Redis 自动覆盖中心格及相邻 8 个 Geohash 格网,保证边界完整,且返回结果天然满足矩形约束。
- 单位必须是小写:
m、km、ft、mi;写成M或KM直接报ERR unknown unit - 宽度和高度数值含义清晰,不像半径容易被误读为“公里数”(比如传
10,GEORADIUS可能被当成 10 米,GEOSEARCH的BYRADIUS 10就真是 10 米) - 矩形内部仍走 Haversine 距离校验,不是粗略前缀匹配,精度有保障
Go 客户端里 Unit 参数彻底失效,别再传了
在 github.com/redis/go-redis/v9 中:
-
client.GeoRadius:Radius是数值,Unit必须显式传字符串(如Unit: "km"),漏传或大小写错误直接失败 -
client.GeoSearch:Radius字段单位固定为米,Unit参数已废弃;传Radius: 1000就是 1000 米,传Radius: 1就是 1 米 - 同是传
10,GeoRadius默认按米算(隐式),GeoSearch就真是 10 米——这是线上查不到结果时最常忽略的单位陷阱
底层仍是逐点算距离,别指望 Geohash 前缀加速
无论是 GEORADIUS 还是 GEOSEARCH,都对 ZSet 所有成员调用 Haversine 公式计算球面距离,不依赖 Geohash 前缀索引。所谓“Geohash 加速”必须自己实现分桶(如 geo:bucket:ws10),并手动查 9 个邻近格网再合并过滤。
这意味着:
- 万级数据下两者性能差异几乎不可测(都是毫秒级)
- 10 万点以上或 QPS > 500 时,CPU 会被距离计算吃满,此时才值得上自建 Geohash 分桶
- 动态调整半径(如滑动选择 1km/5km/10km)反而会让分桶策略更难维护
真正影响落地效果的,从来不是“Redis 算得多快”,而是你有没有踩中 FROMMEMBER、BYBOX、单位语义这三处关键设计变更。











