在LBS的应用中,一个基本的需求是查找附近的用户,现在有两种做法:

1. 使用mysql的空间数据库,具体做法参考:http://blog.sina.com.cn/s/blog_a48af8c001018q1p.html 。

2.  使用geohash编码,这个是本文需要讨论的。

geohash编码,可以把球面上的经纬度转换成一个值,简单点来说就是把二维坐标转换成一维坐标。查找附近的时候,非常方便,用SQL中,LIKE ‘w23yr3%’可查询附近的所有地点。

geohash的详细介绍,可参考 http://www.wubiao.info/372

在以前的产品中,一个需求是查找用户附近的商铺,发现用mysql LIKE ‘w23yr3%’这种方式检索geohash性能上的瓶颈很大,检索130万行的数据,平均花费了8秒,这是响应速度是无法忍受的。

后来经过不断优化,确定了如下使用coreseek+redis+mysql解决方案,一下子就把响应速度减少到平均1 秒,这个方案的如下:

1. 用每个商铺的坐标值计算geohash,把geohash作为key,商铺的作为value,放到redis的set集中。

$this->cache->redis->select(1);//不能使用0,因为这里有大量的数据,需要独立
$this->cache->redis->set('place:geohash:'.$geohash,$place_id);

2. 根据用户的坐标,在redis中查找附近的商铺id

<?php

    /**
* 获取附近的地标公共处理方法
* @param $lat
* @param $lng
* @param $n geohash值的长度,一般来说,当n=6,是获取当前附近1千米范围内的用户
*/
function getLocalPlace($lat, $lng, $n)
{ $lat = (float) $lat;
$lng = (float) $lng;
$nowGeohash = $this->geohash->encode($lng, $lat);
$likeGeohash = substr($nowGeohash, 0, $n);
$placeIds = array(); $this->_loadDriver('cache', array('adapter' => 'redis')); //不能使用0,因为这里有大量的数据,需要独立
$this->cache->redis->select(1); //*表示模糊匹配,例如有key werewfs,werewfw,那么使用“werewf*”,则能同时匹配werewfs,werewfw
$geohashKeys = $this->cache->redis->keys('place:geohash:' . $likeGeohash . '*');
$hashlen = strlen($nowGeohash);
if ($geohashKeys)
{
$searchKeys = array(); //对坐标进行排序
foreach ($geohashKeys as $k => $v) {
$v = ltrim($v, 'place:geohash:');
for ($i = $n; $i < $hashlen; $i++) {
$compare_hash = substr($nowGeohash, 0, $i);
$cur_hash = substr($v, 0, $i);
if ($compare_hash != $cur_hash)
{
$nofst = str_pad(($i - 1) . $k, 6, '0');
$searchKeys[$nofst] = 'place:geohash:' . $v;
break 1;
}
}
}
if ($searchKeys)
{
krsort($searchKeys); //mget表示返回所有特殊keys的values
$placeIds = $this->cache->redis->mget($searchKeys); }
} return $placeIds;
}

3. 如果需要查找关键字或商铺的类型,则用把2中$placeIds 作为filter调戏 ,在coreseek中继续查找。

app后端系列文章总目录

如果您觉得这系列的文章对你有所帮助,欢迎打赏。

支付宝账号:190678908@qq.com 收款人:曾健生

[文章作者]曾健生

[作者邮箱]h6k65@126.com

[作者QQ]190678908

[新浪微博] @newjueqi

[博客]http://blog.csdn.net/newjueqi

http://blog.sina.com.cn/h6k65

版权声明:本文为博主原创文章,未经博主允许不得转载。

app后端设计(6)-- LBS的更多相关文章

  1. app后端设计(14)--LBS的偏移问题

    刚开始做LBS的时候,有一个问题,通过手机获取的坐标,放到百度地图或高德地图上,总是会出现偏移,例如,当时是在微信的前总部"南方通讯大厦"附近获取的坐标,那是把坐标放到百度地图上却 ...

  2. app后端设计--总目录 (转)

    特此说明,我转载的!!! app后端设计(1)--api app后端设计(2)--xmpp的使用 app后端设计(3)--短信,邮件,推送服务 app后端设计(4)-- 通讯的安全性 app后端设计( ...

  3. app后端设计--总目录

    做了3年app相关的系统架构,api设计,先后在3个创业公司中工作,经历过手机网页端,android客户端,iphone客户端,现就职于app云后端平台bmob(想了解bmob点击这里).其中的乐与苦 ...

  4. app后端设计(0)--总文件夹

    原文:http://blog.csdn.net/newjueqi/article/details/19003775 做了接近两年app相关的系统架构,api设计,先后在两个创业公司中工作,经历过手机网 ...

  5. [置顶] app后端设计--总目录

    版权声明:本文为博主原创文章,未经博主允许不得转载. 做了3年app相关的系统架构,api设计,先后在3个创业公司中工作,经历过手机网页端,Android客户端,iphone客户端,现就职于app云后 ...

  6. app后端设计(0)--总目录(转)

    原文:http://blog.csdn.net/newjueqi/article/details/19003775 做了接近两年app相关的系统架构,api设计,先后在两个创业公司中工作,经历过手机网 ...

  7. app后端设计(php)

    来源:http://blog.csdn.net/column/details/mobilebackend.html?page=1 做了3年app相关的系统架构,api设计,先后在3个创业公司中工作,经 ...

  8. app后端设计(12)--图片的处理

    app上线后,不断接受用户的反馈,于是,反馈非常差的情况下,都会有app的改版. 一旦app的改版,都会有比较大的UI改动,一改动UI,那么图片的尺寸也就必须要改变. 在app后端设计(1)—api( ...

  9. app后端设计(11)-- 系统架构(2014.12.05更新)

    个人认为,在小型的创业团队中,特别是以应用产品为主,在架构后台的时候,需要集中精力解决自身业务上的问题,不是花时间解决第三方已经解决的问题,简单点来说,就是能用第三方服务就使用第三方的服务.基于这个原 ...

随机推荐

  1. Linux文件与目录管理 - ls, cp, mv

    [root@www ~]# ls [-aAdfFhilnrRSt] 目录名称 [root@www ~]# ls [--color={never,auto,always}] 目录名称 [root@www ...

  2. objective-c 2.0的字面量Literals

    obj-c 2.0增加了许多核心对象字面量的简单语法,向ruby学习吗? 直接上代码: #import <Foundation/Foundation.h> int main(void){ ...

  3. iOS监听模式系列之IOS中的几中观察监听模式

    本文介绍Objective C中实现观察者模式(也被称为广播者/监听者.发布/注册或者通知)的五种方法以及每种方法的价值所在. 该文章将包括: 1 手动广播者和监听者(Broadcaster and ...

  4. 一个简单的ruby生成器例子(用连续体Continuation实现)

    ruby中有很多经典的驱动器结构,比如枚举器和生成器等.这次简单介绍下生成器的概念.生成器是按照功能要求,一次产生一个对象,或称之为生成一个对象的方法.ruby中的连续体正好可以用来完成生成器的功能. ...

  5. Apache Kafka简介与安装(一)

    介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计. 首先让我们看几个基本的消息系统术语: Kafka将消息以topic为单位进行归纳. 将向 ...

  6. Mysql创建索引

    1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提高查询效率.特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍. 例如,有 ...

  7. 开启flume的远程调试功能

    各种组件,比如tomcat.storm.flume,我们都可以通过JMX方式开启远程调试,主要可以用来跟踪源码,了解程序内部的运行机制,其次,也有利于你修改源码. 首先,本质上是要修改flume本身启 ...

  8. Day4_迭代器

    迭代器: 是一个重复的过程,每一次重复都是基于上一次的结果而来. 可迭代对象: 凡是对象有_iter_方法(对象._iter_),该对象就是可迭代对象. 字符串,列表,元组,字典等都是可迭代对象. 可 ...

  9. subclipse下svn: E200015: authentication cancelled问题的解决

    今天要把新建的一个项目要share到一个Ubuntu下SVN服务上,总是让我不断的重复输入密码,实在是太要命了,点取消就报错如标题,Google了一下,最后在后面参考那篇帖子的启发下,到SVN配置里面 ...

  10. UML小白入门基础教程

    面向对象的问题的处理的关键是建模问题.建模可以把在复杂世界的许多重要的细节给抽象出.许多建模工具封装了UML(也就是Unified Modeling Language™,统一建模语言),这篇课程的目的 ...