背景

在review同事代码时,看到了一个很长的SQL,功能是用户找到附近的100个店铺。我忍不住提出了一种更优雅更快捷的方式:利用redis 的一种在Redis3.2版本中推出高级数据类型GEO(不要再说Redis只有5种数据结构了),特别是数据量比较大时,效率高于MySQL很多。

mysql查看用户(还在用MySQL计算用户距离吗) 第1张

mysql 计算经纬度

简介

Redis的GEO可以将用户给定的地理位置(经度和纬度)信息储存起来,并对这些信息进行操作。GEO相关命令只有6个:

mysql查看用户(还在用MySQL计算用户距离吗) 第2张

改进思路

  1. 将店铺信息存储在Redis中
  2. 利用Redis的GEORADIUS 查出附近的10个店铺

springboot redis实战

引入jar包

mysql查看用户(还在用MySQL计算用户距离吗) 第3张

利用StringRedisTemplate API

mysql查看用户(还在用MySQL计算用户距离吗) 第4张

mysql查看用户(还在用MySQL计算用户距离吗) 第5张

测试结果

redis计算

mysql查看用户(还在用MySQL计算用户距离吗) 第6张

MySQL计算

mysql查看用户(还在用MySQL计算用户距离吗) 第7张

结论: 可见2个的结果一致。

也说原理

我们知道经度范围(-180,180),纬度范围(-90,90)。

以纬度为例,用二分法将纬度(-90,90)分成两个区间,(-90,0)和(0,90),如果目标纬度落在左边区间则记为0,否则记为1;再将目标纬度所在的那个区间再通过二分法分成两个相等的区间,如果目标纬度落在左边区间则记为0,否则记为1,以此类推,可以得到一个二进制数。同理经度也以此可以推导出一个二进制数。

假如得到的经纬度二进制数如下

经度:110101100101001110111100011010 纬度:101011000101010000110101100101

然后通过偶数位放经度,奇数位放纬度将经纬度合并,从0位开始数起(0是偶数位,放经度)

结果

111001100111100000110011000110101000111110110001011010011001

然后按照从左往右,每n位划分成1个组(n 越小越精确)

假如n为5,则结果

11100 11001 11100 00011 00110 00110 10100 01111 10110 00101 10100 11001

换成十进制,

28 25 28 3 6 6 20 15 22 5 20 25

然后十进制转base32字符串:4Z4CGGUPWFUZ

如果有另外一个经纬度转化后为:4Z4CGGUPWFUA,则两个字符串能匹配11位,比较相似,距离就比较近。

mysql查看用户(还在用MySQL计算用户距离吗) 第8张

演示视频

收藏(0)