geohash介绍

⾃Redis 3.2开始,Redis基于geohash和有序集合提供了地理位置相关功能。Redis Geo模块包含了以下6个命令:
▶GEOADD: 将给定的位置对象(纬度、经度、名字)添加到指定的key;
▶GEOPOS: 从key⾥⾯返回所有给定位置对象的位置(经度和纬度);
▶GEODIST: 返回两个给定位置之间的距离;
▶GEOHASH: 返回⼀个或多个位置对象的Geohash表⽰;
▶GEORADIUS: 以给定的经纬度为中⼼,返回⽬标集合中与中⼼的距离不超过给定最⼤距离的所有位置对象;
▶GEORADIUSBYMEMBER: 以给定的位置对象为中⼼,返回与其距离不超过给定最⼤距离的所有位置对象。
其中,组合使⽤GEOADD和GEORADIUS可实现“附近的⼈”中“增”和“查”的基本功能。要实现微信中“附近的⼈”功能,可直接使⽤GEORADIUSBYMEMBER命令。其中“给定的位置对象”即为⽤⼾本⼈,搜索的对象为其他⽤⼾。不过本质
上,GEORADIUSBYMEMBER = GEOPOS + GEORADIUS,即先查找⽤⼾位置再通过该位置搜索附近满⾜位置相互距离条件的其他⽤⼾对象。
以下会从源码⻆度⼊⼿对GEOADD和GEORADIUS命令进⾏分析,剖析其算法原理

Redis geo操作中只包含了“增”和“查”的操作,并没有专⻔的“删除”命令。主要是因为Redis内部使⽤有序集合(zset)保存位置对象,可⽤zrem进⾏删除。
在Redis源码geo.c的⽂件注释中,只说明了该⽂件为GEOADD、GEORADIUSGEORADIUSBYMEMBER的实现⽂件(其实在也实现了另三个命令)。从侧⾯看出其他三个命令为辅助命令。

GEOADD

使⽤⽅式
GEOADD key longitude latitude member [longitude latitude member …]
将给定的位置对象(纬度、经度、名字)添加到指定的key。
其中,key为集合名称,member为该经纬度所对应的对象。在实际运⽤中,当所需存储的对象数量过多时,可通过设置多
key(如⼀个省⼀个key)的⽅式对对象集合变相做sharding,避免单集合数量过多。
成功插⼊后的返回值:
(integer) N
其中N为成功插⼊的个数。

通过源码分析可以看出Redis内部使⽤有序集合(zset)保存位置对象,有序集合中每个元素都是⼀个带位置的对象,元素的score值为其经纬度对应的52位的geohash值。
double类型精度为52位;
geohash是以base32的⽅式编码,52bits最⾼可存储10位geohash值,对应地理区域⼤⼩为0.60.6⽶的格⼦。换句话说经Redis geo转换过的位置理论上会有约0.31.414=0.424⽶的误差。(?)

简单总结下GEOADD命令都⼲了啥:
1、参数提取和校验;
2、将⼊参经纬度转换为52位的geohash值(score);
3、调⽤ZADD命令将member及其对应的score存⼊集合key中。

GEORADIUS

使⽤⽅式

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count] [STORE key] [STORedisT key]

以给定的经纬度为中⼼,返回⽬标集合中与中⼼的距离不超过给定最⼤距离的所有位置对象。
范围单位:m | km | ft | mi --> ⽶ | 千⽶ | 英尺 | 英⾥
额外外参数:

  • WITHDIST:在返回位置对象的同时,将位置对象与中⼼之间的距离也⼀并返回。距离的单位和⽤⼾给定的范围单位保持⼀致。
  • WITHCOORD:将位置对象的经度和维度也⼀并返回。
  • WITHHASH:以 52 位有符号整数的形式,返回位置对象经过原始 geohash 编码的有序集合分值。这个选项主要⽤于底层应⽤
    或者调试,实际中的作⽤并不⼤。
  • ASC|DESC:从近到远返回位置对象元素 | 从远到近返回位置对象元素。
  • COUNT count:选取前N个匹配位置对象元素。(不设置则返回所有元素) - STORE key:将返回结果的地理位置信息保存到
    指定key。
  • STORedisT key:将返回结果离中⼼点的距离保存到指定key。

由于 STORE 和 STORedisT 两个选项的存在,GEORADIUS 和 GEORADIUSBYMEMBER 命令在技术上会被标记为写⼊命令,从⽽只会查询(写⼊)主实例,QPS过⾼时容易造成主实例读写压⼒过⼤。为解决这个问题,在 Redis 3.2.10 和 Redis 4.0.0 中,分别新增了 GEORADIUS_RO 和 GEORADIUSBYMEMBER_RO两个只读命令。
不过,在实际开发中笔者发现 在java package Redis.clients.jedis.params.geo 的 GeoRadiusParam 参数类中并不包含STORE 和 STORedisT 两个参数选项,在调⽤georadius时是否真的只查询了主实例,还是进⾏了只读封装。
成功查询后的返回值:
不带WITH限定,返回⼀个member list,如:
[“member1”,“member2”,“member3”]
带WITH限定,member list中每个member也是⼀个嵌套list,如:
[
[“member1”, distance1, [longitude1, latitude1]]
[“member2”, distance2, [longitude2, latitude2]]
]

⼩结
抛开众多可选参数不谈,简单总结下GEORADIUS命令是怎么利⽤geohash获取⽬标位置对象的:
1、参数提取和校验;
2、利⽤中⼼点和输⼊半径计算待查区域范围。这个范围参数包括满⾜条件的最⾼的geohash⽹格等级(精度) 以及 对应的能够覆盖⽬标区域的九宫格位置;(后续会有详细说明)
3、对九宫格进⾏遍历,根据每个geohash⽹格的范围框选出位置对象。进⼀步找出与中⼼点距离⼩于输⼊半径的对象,进⾏返回。
直接描述不太好理解,我们通过如下两张图在对算法进⾏简单的演⽰:

令左图的中⼼为搜索中⼼,绿⾊圆形区域为⽬标区域,所有点为待搜索的位置对象,红⾊点则为满⾜条件的位置对象。
在实际搜索时,⾸先会根据搜索半径计算geohash⽹格等级(即右图中⽹格⼤⼩等级),并确定九宫格位置(即红⾊九宫格位置信息);再依次查找计算九宫格中的点(蓝点和红点)与中⼼点的距离,最终筛选出距离范围内的点(红点)。

如何通过geohash⽹格的范围框选出元素对象?效率如何?
⾸先在每个geohash⽹格中的geohash值都是连续的,有固定范围。所以只要找出有序集合中,处在该范围的位置对象即可。以下是有序集合的跳表数据结构:

其拥有类似⼆叉查找树的查询效率,操作平均时间复杂性为O(log(N))。
且最底层的所有元素都以链表的形式按序排列。
所以在查询时,只要找到集合中处在⽬标geohash⽹格中的第⼀个值,后续依次对⽐即可,不⽤多次查找。九宫格不能⼀起查,要⼀个个遍历的原因也在于九宫格各⽹格对应的geohash值不具有连续性。只有连续了,查询效率才会⾼,不然要多做许多距离运算。

【学习笔记】Redis的geohash数据结构介绍相关推荐

  1. CCC3.0学习笔记_数字密钥数据结构

    CCC3.0学习笔记_数字密钥数据结构 系列文章目录 文章目录 系列文章目录 前言 4.1 Applet Instance Layout 4.2 Digital Key Structure 4.2.1 ...

  2. Redis学习笔记---Redis的主从复制

    Redis学习笔记-Redis的主从复制 1.Redis的高可用性 高可用性(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性. Rei ...

  3. Redis学习笔记---Redis的模式订阅与退订

    Redis学习笔记-Redis的模式订阅与退订 1.发布订阅简介 发布订阅是一种通信的模式,Redis提供了发布订阅功能,可以用于消息的传输 Redis的发布订阅机制包括三个部分,publisher( ...

  4. Redis学习笔记~Redis在windows环境下的安装

    Redis是一个key-value的存储系统,它最大的特点就是可以将数据序列化到文件中. redis存储在服务器的内存或者文件中,它不是session,不是cookies,它只是个更安全,更稳定,更可 ...

  5. python表单提交的两种方式_Flask框架学习笔记之表单基础介绍与表单提交方式

    本文实例讲述了Flask框架学习笔记之表单基础介绍与表单提交方式.分享给大家供大家参考,具体如下: 表单介绍 表单是HTML页面中负责数据采集功能的部件.由表单标签,表单域和表单按钮组成.通过表单,将 ...

  6. Linux学习笔记 文件服务Vsftp详细介绍

    Linux学习笔记 文件服务Vsftp详细介绍 知识点: 1.FTP使用TCP连接和TCP端口 2.在进行通信时,FTP需要建立两个TCP连接: 一个用于控制信息,TCP端口号缺省为21 一个用于数据 ...

  7. Oracle中job_type,【学习笔记】Oracle DBMS_SCHEDULER详细介绍与使用案例

    天萃荷净 分享一篇关于Oracle DBMS_SCHEDULER详细介绍与使用案例 1.通过DBMS_SCHEDULER.CREATE_JOB直接创建job SQL> create table ...

  8. Unity DOTS 学习笔记1 - ECS 0.50介绍和安装

    Unity DOTS 学习笔记1 - ECS 0.50介绍和安装 为什么学习这个技术 ECS的全称为Entity Component System,是最早由暴雪在GDC2017上提出的一个新的游戏设计 ...

  9. 嵌入式学习笔记——基于Cortex-M的单片机介绍

    基于Cortex-M的单片机介绍 前言 1生产厂商及其产品线 1.1ARM单片机的产品线 1.2命名规则 作业1 2习单片机的资料准备 2.1STM32开发所需手册 2.1.1芯片的数据手册 芯片基本 ...

最新文章

  1. 王茂霖:数据挖掘提分三板斧!
  2. php的类图怎么生成_PHP设计模式之简单工厂模式
  3. 帆软日期控件变灰_数据分析插件FineReport中日期控件如何校验JS
  4. 视图切换—多模板文档视图结构的应用
  5. RocketMQ如何保证消息不丢失? 如何快速处理积压消息?
  6. CentOS 7 巨大变动之 systemd 取代 SysV的Init
  7. switchhosts 文件下载
  8. Eclipse ADT 进行android应用签名打包详解
  9. Visio软件方案UML选择
  10. 两种方式,实现 SpringBoot 中数据库密码加密
  11. html5音效,HTML5之Audio(六)—— 3D音效
  12. 神奇的css之 -webkit-background-clip: text; 五彩斑斓的文字效果
  13. C语言编程实现Euclid GCD算法 作业
  14. tomcat 配置文件 conf/server.xml 中的 appBase和docBase
  15. python抓取数据包_python抓数据包
  16. STM32之BKP原理
  17. Google内部流传的反多样性文章(10页完整版中文翻译)
  18. 美元霸权·《看懂世界格局的第一本书·2》
  19. 网店刷单后自己线下发货还是找礼品代发?空包还是信封件怎么选才正确?
  20. 谷歌手机pixel4 夜景_您应该购买Google Pixel 4a的5个理由

热门文章

  1. 工程勘察设计管理条例释义电子书_全国有多少注册勘察设计工程师?官方数据告诉你...
  2. 字符串从右截取_跟运维组学Python基础day04(字符串str的索引和切片)
  3. python右对齐输出如果结果超过30个字符_Python3 输出字符串左对齐、右对齐、居中对齐...
  4. html二级选择题,2017计算机二级考试试题web习题及答案
  5. go mongodb排序查询_「赵强老师」MongoDB中的索引(下)
  6. 二十六、爬取拉钩网Python职位的数据
  7. 二十六、深入Node.js中的文件系统fs模块
  8. 六十八、SpringBoot连接MongoDB操作
  9. pytorch 入门Tensor(一)
  10. Myeclipse中快速插入HttpServlet子类中doGet和doPost方法