Redis 是怎么实现 “附近的人” 的?
操作命令
- GEOADD: 将给定的位置对象(纬度、经度、名字)添加到指定的key;
- GEOPOS: 从key里面返回所有给定位置对象的位置(经度和纬度);
- GEODIST: 返回两个给定位置之间的距离;
- GEOHASH: 返回一个或多个位置对象的Geohash表示;
- GEORADIUS: 以给定的经纬度为中心,返回目标集合中与中心的距离不超过给定最大距离的所有位置对象;
- GEORADIUSBYMEMBER: 以给定的位置对象为中心,返回与其距离不超过给定最大距离的所有位置对象。
以下会从源码角度入手对GEOADD和GEORADIUS命令进行分析,剖析其算法原理。
Redis geo操作中只包含了“增”和“查”的操作,并没有专门的“删除”命令。主要是因为Redis内部使用有序集合(zset)保存位置对象,可用zrem进行删除。
在Redis源码geo.c的文件注释中,只说明了该文件为GEOADD、GEORADIUS和GEORADIUSBYMEMBER的实现文件(其实在也实现了另三个命令)。从侧面看出其他三个命令为辅助命令。
GEOADD
使用方式
源码分析
double类型精度为52位;
geohash是以base32的方式编码,52bits最高可存储10位geohash值,对应地理区域大小为0.6*0.6米的格子。换句话说经Redis geo转换过的位置理论上会有约0.3*1.414=0.424米的误差。
算法小结
1、参数提取和校验;
2、将入参经纬度转换为52位的geohash值(score);
3、调用ZADD命令将member及其对应的score存入集合key中。
GEORADIUS
使用方式
由于 STORE 和 STORedisT 两个选项的存在,GEORADIUS 和 GEORADIUSBYMEMBER 命令在技术上会被标记为写入命令,从而只会查询(写入)主实例,QPS过高时容易造成主实例读写压力过大。为解决这个问题,在 Redis 3.2.10 和 Redis 4.0.0 中,分别新增了 GEORADIUS_RO 和 GEORADIUSBYMEMBER_RO两个只读命令。
不过,在实际开发中笔者发现 在java packageRedis.clients.jedis.params.geo的 GeoRadiusParam 参数类中并不包含 STORE 和 STORedisT 两个参数选项,在调用georadius时是否真的只查询了主实例,还是进行了只读封装。感兴趣的朋友可以自己研究下。
源码分析
此段源码较长,看不下去的可直接看中文注释,或直接跳到小结部分
geohashGetAreasByRadiusWGS84和membersOfAllNeighbors两个函数。- 计算中心点范围:
- 对中心点及其周围8个geohash网格区域进行查找:
算法小结
算法分析
来源:饿了么物流团队
https://juejin.im/post/5da40462f265da5baf410a11
点击「阅读原文」和栈长学更多~
Redis 是怎么实现 “附近的人” 的?的更多相关文章
- 使用 Redis 如何实现查询附近的人?「视频版」——面试突击 003 期
面试问题 Redis 如何实现查询附近的人? 涉及知识点 Redis 中如何操作位置信息? GEO 底层是如何实现的? 如何在程序实现查询附近的人? 在实际使用中需要注意哪些问题? 视频答案 视频地址 ...
- Redis(6)——GeoHash查找附近的人
像微信 "附近的人",美团 "附近的餐厅",支付宝共享单车 "附近的车" 是怎么设计实现的呢? 一.使用数据库实现查找附近的人 我们都知道, ...
- Redis 到底是怎么实现“附近的人”这个功能的?
前言:针对“附近的人”这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现.而Redis另辟蹊径,结合其有序队列zset以及geohash编码,实现了空 ...
- Redis 实现美团的外卖派单系统“附近的人”筛选实战原理分析
针对“附近的人”这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现.而Redis另辟蹊径,结合其有序队列zset以及geohash编码,实现了空间搜索 ...
- Redis 到底是怎么实现“附近的人”这个功能的呢?
作者简介 万汨,饿了么资深开发工程师.iOS,Go,Java均有涉猎.目前主攻大数据开发.喜欢骑行.爬山. 前言:针对“附近的人”这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoD ...
- Redis的人门以及使用
1.Redis的安装 1.1centos下安装Redis 1.1.1 安装gcc 1.1.2 安装过程 图一 图三 2.Redis的启动 2.1 前端模式启动(不推荐) 截图 2.2 后端模式(推荐 ...
- 网站缓存技术总结( ehcache、memcache、redis对比)
网站技术高速发展的今天,缓存技术已经成为大型网站的一个关键技术,缓存设计好坏直接关系的一个网站访问的速度,以及购置服务器的数量,甚至影响到用户的体验. 网站缓存按照存放的地点不同,可以分为客户端缓存. ...
- Linux下redis的安装
第一部分:安装redis 希望将redis安装到此目录 /usr/local/redis 希望将安装包下载到此目录 /usr/local/src 那么安装过程指令如下: $ mkdir /usr/lo ...
- ehcache memcache redis 三大缓存
最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特意归纳下各个缓存的优缺点,仅供参考! Ehcache 在Java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS ...
随机推荐
- linux如何查看ip地址
使用命令: ifconfig -a 例如:
- 7.13 T2 Shit 题(shit)
[题目描述] 某一天,小
- JavaScript设计模式—代理模式
代理模式介绍 使用者无权访问目标对象,中间加代理,通过代理做授权和控制 代理(proxy)是一个对象,它可以用来控制对另外一个对象的访问: 代理对象和本体对象实现了同样的接口,并且会把任何方法调用传递 ...
- Zookeeper系列(十)zookeeper的服务端启动详述
作者:leesf 掌控之中,才会成功:掌控之外,注定失败.出处:http://www.cnblogs.com/leesf456/p/6105276.html尊重原创,大家功能学习进步: 一.前 ...
- python并发——信号量
信号量通常用于保护数量有限的资源,例如数据库服务器.在资源数量固定的任何情况下,都应该使用有界信号量.在生成任何工作线程前,应该在主线程中初始化信号量. 工作线程生成后,当需要连接服务器时,这些线程将 ...
- javax.el.PropertyNotFoundException: Property 'id' not found on type java.lang.String 可长点心吧
在网上搜了好多帖子都说<c:forEach items="${list }" var="stu">标签list没有加${}: 可我的问题不是这个,而 ...
- 常用css模板
段落超出显示省略号(可单行多行) .p-content{ overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-b ...
- box-sizing Bootstrap
https://getbootstrap.com/docs/4.0/getting-started/introduction/#box-sizing Box-sizing For more strai ...
- 前端知识点回顾之重点篇——JavaScript异步机制
JavaScript异步机制 来源:https://www.cnblogs.com/zhaodongyu/p/3922961.html JavaScript是单线程异步执行的,单线程意味着代码在任务队 ...
- acl设置问题
在学习nfs服务配置的时候用到了acl规则(服务配置文件权限设置可写,但是由于客户端映射,不能写入,所以要设置系统权限),但是遇到了一个小小的问题:一.当使用-x选项取消规则的时候,再次查看权限后面仍 ...