Redis GEO 52 位整数的经纬分布
在 Redis 的 GEO 实现中,经度和纬度的编码方式是 交错存储而不是分离存储的。在 52 位的 Geohash 编码中,经度(longitude)和纬度(latitude)的比特位是 交替排列的,而不是物理上分开的区块。
具体结构如下:
Geohash 编码的位排列规则
| 位位置(从最高位开始) | 0 | 1 | 2 | 3 | 4 | … | 50 | 51 |
|---|---|---|---|---|---|---|---|---|
| 对应坐标 | 经度 | 纬度 | 经度 | 纬度 | 经度 | … | 经度 | 纬度 |
- 偶数索引位(0,2,4,…,50):存储经度信息(共 26 位)
- 奇数索引位(1,3,5,…,51):存储纬度信息(共 26 位)
编码过程原理(源码解析)
Redis 的 Geohash 编码实现在 geohash.c 文件中,核心逻辑在 geohashEncode() 函数中:
// redis/src/geohash.c
void geohashEncode(...) {
// ...
for (i = 0; i < step; i++) {
double lat_offset, lng_offset;
uint64_t bits = 0;
// 交替处理经度和纬度
if (i % 2 == 0) {
// 偶数位:处理经度
lng_offset = (lng_range[0] + lng_range[1]) / 2;
if (longitude >= lng_offset) {
bits |= 1;
lng_range[0] = lng_offset;
} else {
lng_range[1] = lng_offset;
}
} else {
// 奇数位:处理纬度
lat_offset = (lat_range[0] + lat_range[1]) / 2;
if (latitude >= lat_offset) {
bits |= 1;
lat_range[0] = lat_offset;
} else {
lat_range[1] = lat_offset;
}
}
hash->bits = (hash->bits << 1) | bits;
}
}
为什么采用交错存储?
- 空间局部性保留:
- 经纬度交错排列保持了地理位置的连续性
- 相邻地理位置的 Geohash 值会有更长的公共前缀(临界特性)
- 范围查询优化:
// redis/src/geo.c
void georadiusGetAreasByShape(geoRange *r) {
// 范围查询时会自动对齐Z阶曲线
geohashBoundingBox(r->longitude, r->latitude, r->radius);
}
这种排列使得经度/纬度联合查询可以直接通过位操作实现
- 与Z阶曲线的兼容:
交错存储本质上实现了莫顿码(Morton Code),将二维坐标映射到一维曲线时能最小化空间跳跃
解码过程
当需要反向获取坐标时,Redis 会分离这些位:
// redis/src/geohash.c
int decodeGeohash(uint64_t bits, double *xy) {
double lat_range[] = {-90, 90};
double lng_range[] = {-180, 180};
// 交替处理52位
for (int i = 51; i >= 0; i--) {
uint64_t bit = (bits >> i) & 1;
if (i % 2 == 0) { // 经度位
double mid = (lng_range[0] + lng_range[1]) / 2;
if (bit) lng_range[0] = mid;
else lng_range[1] = mid;
} else { // 纬度位
double mid = (lat_range[0] + lat_range[1]) / 2;
if (bit) lat_range[0] = mid;
else lat_range[1] = mid;
}
}
xy[0] = (lng_range[0] + lng_range[1]) / 2;
xy[1] = (lat_range[0] + lat_range[1]) / 2;
}
精度说明
| 坐标轴 | 比特位数 | 理论精度 |
|---|---|---|
| 经度 | 26 bits | 约 0.0000429° (赤道约 4.78m) |
| 纬度 | 26 bits | 约 0.0000215° (约 2.39m) |
这种交错编码方式虽然增加了编解码的复杂性,但使 Redis 的 GEO 查询性能达到了 O(log N) 的优异水平,是空间与时间的完美平衡。
本文来自博客园,作者:NeoLshu,转载请注明原文链接:https://www.cnblogs.com/neolshu/p/19120489

浙公网安备 33010602011771号