MENU

利用Redis的GEO特性实现类似微信附近的人

December 25, 2019 • php阅读设置

前言

随着移动互联网的快速发展,移动互联网覆盖我们生活中的方方面面!
在日常生活中我们所使用APP的外卖、打车、附近的商家等功能又是如何实现的呢?
例如我们现在想叫一份外卖,如果根据自己的位置找寻附近的商家呢?
或者我们需要打车回家的时候,系统又是如何安排优先距离我们较近的车辆信息呢?
再或者我们想交友,那微信附近的人、陌陌、探探.....(#手动狗头)
了解这些功能如何实现的,接下来我们一探究竟!

特性简介

通过Redisgeo特性,可以将用户上报的经纬度坐标信息进行存储,并对用户坐标信息进行距离等相关运算!
geo特性由Redis3.2版本推出,若需使用Redisgeo特性,请将redis版本升级至3.2以上。

第一步 用户坐标信息上报

移动端在获取手机的GPS权限后,定时向服务器上报当前用户的经纬度。
比如说滴滴打车定时上报当前车辆的经纬度坐标信息。
服务器将车辆的经纬度通过Redis的geo特性进行存储

命令参考:GEOADD key longitude latitude member
文档地址:GEOADD命令参考文档

php存储两个车辆坐标信息代码示例:
新建一个geoadd.php 代码如下:

<?php
$redis = new \Redis();
$redis->connect('redis', 6379);
// 增加两个车辆编号为 car1、car2的坐标 到carlist集合.
$redis->geoadd('carlist', '-100.6331263694', '40.2054986348', 'car1');
$redis->geoadd('carlist', '-100.6306533726', '40.2047529787', 'car2');

我们执行一下 php geo.php 看有没有把坐标信息存入redis

执行结果

现在我们已经把两个车辆的坐标信息存入到Redis了。


第二步 根据用户当前坐标查询周围5公里范围的车辆

现在我们的用户要打车,发送了一个用户的坐标到服务器
服务器拿到了用户的坐标需要根据用户的坐标来查找周围5公里范围内的汽车。

命令参考:GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
文档地址:GEORADIUS命令参考文档

php存储两个车辆坐标信息代码示例:
新建一个georadius.php 代码如下:

<?php
$redis = new \Redis();
$redis->connect('redis', 6379);
// 根据用户的经纬度查询出周围5公里范围内的车辆信息,由近及远排序,并在返回的车辆信息中附带车辆的当前坐标及距离(km单位);
$carlist = $redis->georadius('carlist', '-100.6301598462', '40.2067989295', 5, 'km', ['WITHDIST', 'WITHCOORD', 'ASC']);
var_dump($carlist);

我们执行一下 php georadius.php 看看返回结果

➜  php georadius.php
array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(4) "car2"
    [1]=>
    string(6) "0.2315"
    [2]=>
    array(2) {
      [0]=>
      string(22) "-100.63065379858016968"
      [1]=>
      string(20) "40.20475215137940239"
    }
  }
  [1]=>
  array(3) {
    [0]=>
    string(4) "car1"
    [1]=>
    string(6) "0.2905"
    [2]=>
    array(2) {
      [0]=>
      string(22) "-100.63312679529190063"
      [1]=>
      string(20) "40.20549989412140945"
    }
  }
}

ok 车辆的信息已经按条件返回了。非常的简单且粗暴!


附言

  1. 在实际项目中我们可以根据业务场景实时上报坐标信息,例如滴滴打车、美团骑手位置等可以通过长连接协议实时上报至服务器!
  2. 根据GEORADIUS方法里面的其他参数可以灵活控制redis返回的信息,例如:坐标经纬距离单位远近排序
  3. 使用mysql相关函数也能实现,但不建议!
  4. mongoDBelasticsearch也可实现相关功能,具体请参考搜索引擎
  5. Redis Geo其他命令参考文档:Geo命令文档
Last Modified: March 12, 2020
Archives QR Code
QR Code for this page
Tipping QR Code