【Redis实战】GeoHash实现原理与基本使用

news2024/10/5 14:08:20

文章目录

  • GeoHash可以解决什么问题?
  • 基于网格划分的最近邻查询
  • GeoHash
    • 划分规则
  • GeoHash的使用方式
    • Redis GEOADD 命令
      • 语法
      • 示例
    • Redis GEORADIUS 命令
      • 语法
        • 半径单位:
        • 可选性参数:
      • 示例
    • Redis GEORADIUSBYMEMBER 命令
      • 语法
      • 示例
    • Redis GEODIST 命令
      • 语法
      • 示例

GeoHash可以解决什么问题?

现在很多APP上都有依赖基于附近搜索的需求,也就是根据一组经纬度,检索其相邻范围内的经纬度,而GeoHash就是一种可以用来解决检索相邻区域的地理空间算法。

我们不妨先从最原始的需求开始分析,也就是根据某个经纬度获取其附近一定范围内的其他目标信息,我们可以先尝试通过使用像MySQL这样的关系型数据库来实现,比如表中记录了longitude表示经度,latitude 表示纬度。

现在有个用户当前处于的经纬度分别为X、Y,请查询其M范围内的相关信息。

根据经纬度距离计算公式可以写出如下SQL,即可按记录由近到远得到想要的目标信息。

SELECT *, ACOS(
		COS(RADIANS(Y)) *
		COS(RADIANS(latitude )) *
		COS(RADIANS(longitude) - RADIANS(X)) +
		SIN(RADIANS(Y)) *
		SIN(RADIANS(latitude ))
	) * 6378 as distance
FROM test ORDER BY distance;

如果请求量以及数据量都不是很大的情况下,使用这种方式完全就足够了,既简单又方便。

基于网格划分的最近邻查询

很明显,当数据量变多,查询量变大以后,如果还继续使用SQL查询的方式,是很难扛得住非常高频的请求的,因此就需要转变查询的方式,最容易想到的方式就是能不能把数据都存储在内存中,这样查询起来就快多了,不过内存容量相比磁盘小多了,所以我们还要想一种能够节约空间的存储方式,那么基于网格划分的最近邻查询算法就是目前比较常用的解法。

该算法将整个数据空间划分成大小相等、互不重叠的网格,目标信息就存放在这些网格中,只要网格大小合适,就能够获得足够精度的信息。

举个简单的例子

假设按照1万条数据一个方格来划分,一共划分出4*4的网格
在这里插入图片描述

当某个区域网格内数据增加时,还可以继续对其分裂,最终就像一颗多叉树一样,且在数据密集区域内网格一定会被划分的很小,而在数据稀疏区域网格则会非常的大,当然,如果网格大小划分不合适,则会导致树的深度太深,每次查找起来性能也不会太理想,不过一旦定位到某个网格之后,再查找邻近的信息就非常简单了,同一个网格内的一定是邻近的,当前网格的上下左右网格就是其次邻近的。

GeoHash

GeoHash是一种优化的网格算法,能够高效的对经纬度进行比较,也是Redis是所使用的算法,其原理就是将网格进行编码,然后根据编码进行Hash存储,且其网格的划分是采用二分区间的方式来完成的,目的就是为了将二维的经纬度转化为一维的二进制数字,这样就可以方便的对齐进行排序、比较了。

划分规则

经度的区间为[-180,180],纬度的区间为[-90,90],当经、纬度值落在左区间时,我们就用0表示,当经、纬度值落在右区间时,我们就用1表示。

最直接的4分区就表示为:00011011
在这里插入图片描述

举个例子,假设我们要记录的经度值为:109.05122,纬度值为:19.292939

经度值经过6次编码后,最终值为:110011
在这里插入图片描述
纬度值经过6次编码后,最终值为:100110
在这里插入图片描述
当经纬度编码值都计算出来以后,再进行合并,合并规则为,从第一位开始,奇数位取经度值,偶数位取纬度值,因此合并后最终的结果为:111000011110

好了,现在经过转换之后,111000011110就可以用来存储、比较了,Redis中对于比较可以使用Sorted Set,我们可以用member来记录数据ID,用score来记录转换后的经纬度,也就是111000011110

GeoHash的使用方式

Redis GEOADD 命令

将指定的地理空间位置(纬度、经度、名称)添加到指定的key中

语法

GEOADD key [NX | XX] [CH] longitude latitude member [longitude
  latitude member ...]

示例

将指定经、纬度添加到指定的类型的集合中,比如:geoadd user:locations 109.05122 19.292939 1 103.05212 23.292939 2,就表示把id为1的用户且经纬度值:109.05122 19.292939和id为2的用户且经纬度值:103.05212 23.292939存放到user:locations集合中。

Redis GEORADIUS 命令

以给定的经纬度为中心, 找出某一半径内的元素

语法

GEORADIUS key longitude latitude radius <M | KM | FT | MI>
  [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC | DESC]
  [STORE key] [STOREDIST key]

半径单位:

M 表示单位为米。
KM 表示单位为千米。
FT 表示单位为英尺。
MI 表示单位为英里。

可选性参数:

WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
WITHCOORD: 将位置元素的经度和维度也一并返回。
WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:

ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。
DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。
在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。

示例

假设,我们现在需要根据给定经纬度,由近到远显示附近前10条1000KM范围内的信息,那么,可以这样写:georadius user:locations 110.05152 20.293939 1000 km withcoord withdist count 10 asc

在这里插入图片描述

Redis GEORADIUSBYMEMBER 命令

找出位于指定范围内的元素,中心点是由给定的位置元素决定

语法

GEORADIUSBYMEMBER key member radius <M | KM | FT | MI> [WITHCOORD]
  [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC | DESC] [STORE key]
  [STOREDIST key]

此命令与GEORADIUS完全相同,唯一的区别是 将经度和纬度值作为要查询的区域的中心,它采用排序集表示的地理空间索引中已存在的成员的名称。

示例

在这里插入图片描述

Redis GEODIST 命令

返回两个给定位置之间的距离

语法

GEODIST key member1 member2 [M | KM | FT | MI]

示例

在这里插入图片描述
如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。
GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 面试中Binder必问,是否了解过?

1.简单介绍下binder binder是一种进程间通讯的机制 进程间通讯需要了解用户空间和内核空间 每个进程拥有自己的独立虚拟机&#xff0c;系统为他们分配的地址空间都是互相隔离的。 如两个进程需要进行通讯&#xff0c;则需要使用到内核空间做载体&#xff0c;内核空间是所有进…

GPS卫星位置解算

本文介绍了基于C语言的GPS卫星位置解算原理与程序设计。针对每个原理、公式、代码设计进行了详细讲解&#xff0c;希望能够给测绘学子们带来帮助。 参考书籍&#xff1a; 李征航 黄劲松&#xff1a;GPS测量与数据处理&#xff08;第三版&#xff09; 目录 基础原理 1&#xf…

Spring框架(十一):手动实现一个@Component,讲一讲Spring的工厂后处理器

手动实现一个Component&#xff0c;讲一讲Spring的工厂后处理器引子需求代码分析Spring工厂后处理器引子 痛定思痛&#xff0c;主要问题出现在自己雀氏不熟悉框架底层、一些面试题&#xff0c;以及sql的一些情况淡忘了。 本章节的开始是对于过去的重新回顾&#xff0c;当然&am…

【AI】Python 实现八数码问题

实验一 八数码问题 1. 题目介绍 八数码问题描述为&#xff1a;在 33 组成的九宫格棋盘上&#xff0c;摆有 8 张牌&#xff0c;每张牌都刻有 1-8 中的某一个数码。棋盘中留有一个空格&#xff0c;允许其周围的某张牌向空格移动&#xff0c;这样通过移动牌就可以不断改变棋盘布…

PDF或PPT中的某个图或表无损、高清的插入word里的方法,再转成pdf后放大6400%倍仍是高清图片...

本人使用Microsoft Office LTSC 专业增强版 2021版本的&#xff0c;其他版本不确定可不可以 可通过office tool plus下载安装相应版本的office&#xff0c;通过安装与激活安装与激活 0. 参考方法网址&#xff1a; PDF 转成 SVG 格式的方法(无损保留笔记痕迹) 1. pdf可能很多页&…

Dubbo SPI扩展机制源码详解(基于2.7.10)

Dubbo SPI 一. 概述 本文主要分享 Dubbo 的拓展机制 SPI。 想要理解 Dubbo &#xff0c;理解 Dubbo SPI 是非常必须的。在 Dubbo 中&#xff0c;提供了大量的拓展点&#xff0c;基于 Dubbo SPI 机制加载 Dubbo SPI官方文档&#xff1a;Dubbo SPI 概述 | Apache Dubbo 本文基…

Spring-IOC控制反转

Spring 1.简介 1.1简介 1.常见的框架&#xff1a; 2.常见的依赖&#xff1a; <dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artif…

SpringBoot基础之声明式事务和切面事务和编程式事务

文章目录前言一、事务特性开启事务二、事务的隔离级别三、事务的传播行为四、 Springboot事务1.Springboot声明式事务优点&#xff1a;缺点&#xff1a;实现方式&#xff1a;Transactional的参数声明式事务的约定流程&#xff1a;2. Springboot编程式事务SpringBoo切面编程式事…

[附源码]Python计算机毕业设计SSM教学团队管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

微服务框架 SpringCloud微服务架构 11 自定义镜像 11.2 Dockerfile

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构11 自定义镜像11.2 Dockerfile11.2.1 什么是Dcokerfile11.2.2 直接开干11.…

【机器学习】支持向量机【上】硬间隔

有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 在阅读本篇之前建议先学习&#xff1a; 【机器学习】拉格朗日对偶性 【机器学习】核函数 由于字数限制&#xff0c;分成两篇博客。 【机器学习】支持向量机【上】硬间隔 【机器学习】支持向量机【下】…

绿色荧光染料FITC-PEG-FA,Folic acid-PEG-Fluorescein,荧光素-聚乙二醇-叶酸

​ 1、名称 英文&#xff1a;FITC-PEG-FA&#xff0c;Folic acid-PEG-Fluorescein 中文&#xff1a;荧光素-聚乙二醇-叶酸 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a; Fluorescent PEG Folic acid&#xff08;FA&#xff09; PEG 4、分子量&#xff1a;可定制&a…

[附源码]计算机毕业设计网上书城网站Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Java实现猜数游戏

1 问题 编写一个Java程序&#xff0c;实现以下功能&#xff1a; 2 方法 首先导入java.util包下的Random&#xff0c;让程序随便分配给用户一个数。 再导入java.util包下的Scanner类&#xff0c;构建Scanner对象&#xff0c;以便输入。 利用Random().nextInt()生成一个随机的i…

统计学中关于自由度的详细解释以及求平均值为什么消耗自由度1

首先我们要了解自由度是什么 自由度在本科教学中一般都不会过度涉及&#xff0c;因为它给老师和学生都带来了很大的困扰&#xff0c;它本身也有一些历史遗留问题&#xff0c;有很多人给出了很多不同的出发点和解释&#xff0c;比如1946年“自由度就是二次型的秩”&#xff0c;…

Android入门第42天-Android中的Service(IntentService)

开篇 在前一篇中我们讲了bindService的使用。并且我们留下了一个念想&#xff0c;即在bindService取值时故意阻塞30秒&#xff0c;引起了一次ANR并引出了今天的章节-IntentService。 IntentService的生命周期中有一个非常好的方法-onHandleIntent方法&#xff0c;它是一个abs…

创建你的第⼀个XXL-Job分布式调度任务

文章目录一、程序讲解1. 注解介绍2. 编写代码二、执⾏器管理2.1. Appname2.2. 名称2.3. 注册⽅式2.4. 机器地址2.5. 效果图三、任务管理一、程序讲解 1. 注解介绍 在 Spring Bean 实例中&#xff0c;开发 Job ⽅法⽅式格式要求为 public ReturnT<String> execute(Stri…

ARM 重定位引入和链接脚本

一、一个事实&#xff1a;大部分指令是位置有关编码 位置无关编码(PIC&#xff0c;position independent code)&#xff1a;汇编源文件被编码成二进制可执行程序时&#xff0c;编码方式与位置&#xff08;内存地址&#xff09;无关。 位置有关编码&#xff1a;汇编源码编码成…

分布式智能家居项目雏形

需求分析 客户端进入室内后(局域网)能够主动发现服务(如: 环境服务&#xff0c;灯光服务) 各种服务可以有不同的载体(如&#xff1a;由不同设备提供) 各种服务之间&#xff0c;服务与客户端之间完全无耦合(服务可自由增减) 客户端可以是移动APP&#xff0c;也可以是桌面软件…

【计算机毕业设计】基于JSP的房产中介系统的设计与实现

分类号&#xff1a;TP315 U D C&#xff1a;D10621-408-(2007) 6032 -0 密 级&#xff1a;公 开 编 号&#xff1a;2003211030 学位论文 基于JSP的房产中介系统的设计与实现 摘要 计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着科学技术的不断提高&#xff…