如果现在要开发一个功能:

要为一款交友App实现查找附近的人,并按距离进行排序。

让你来开发这个功能,你会如何实现?

MySQL 不合适

你可能想到,把用户用户的经纬度坐标使用MySQL等关系数据库(用户id,经度x,纬度y)存储,但是该如何计算距离和排序呢?

不可能通过遍历来计算所有的用户和目标用户的距离,然后再进行排序,因为这个计算量太大了,性能指标肯定无法满足。

GeoHash的编码方法

为了能高效地对经纬度进行比较,Redis 采用了业界广泛使用的 GeoHash 编码方法,这个方法的基本原理是“二分区间,区间编码”。

关于 GeoHash 参考 https://www.cnblogs.com/LBSer/p/3310455.html

简单来说,GeoHash 能够将二维的经纬度转换为字符串,然后位置就能够直接进行比较和范围查询了。

Redis 中 Geo 的使用

命令 说明  可用版本 时间复杂度
GEOADD 添加位置的经纬度 >= 3.2.0 O(logN)
GEOPOS 返回位置的经纬度 >= 3.2.0 O(logN)
GEODIST 返回两个位置的距离 >= 3.2.0 O(logN)
GEORADIUS 返回与指定位置距离距离不大于指定值的位置的经纬度 >= 3.2.0 O(N+logM)
GEORADIUSBYMEMBER 这个命令和 GEORADIUS 命令一样 >= 3.2.0 O(logN+M)
GEOHASH 返回位置的 GeoHash 值 >= 3.2.0 O(logN)

示例

假设用户ID是33,经纬度位置是(116.054579, 39.030452),我们可以用一个 GEO 集合保存所有用户的经纬度,集合 key 是 users:locations。执行下面的这个命令,就可以把ID号为33的用户的当前经纬度位置存入GEO集合中:

GEOADD users:locations 116.034579 39.030452 33

当用户想要寻找自己附近的人时,就可以使用 GEORADIUS 命令。

例如,执行下面的命令,Redis 会根据输入的用户的经纬度信息(116.054579, 39.030452),查找以这个经纬度为中心的5公里内的用户信息。

GEORADIUS users:locations 116.054579 39.030452 5 km ASC COUNT 10

总结

在一个地图应用中,车的数据、餐馆的数据、人的数据可能会有百万千万条,如果使用 Redis 的 Geo 数据结构,它们将全部放在一个 Sorted Set 集合中。在 Redis 的集群环境中,集合可能会从一个节点迁移到另一个节点,如果单个 key 的数据过大,会对集群的迁移工作造成较大的影响,在集群环境中单个 key 对应的数据量不宜超过 1M,否则会导致集群迁移出现卡顿现象,影响线上服务的正常运行。

所以,这里建议 Geo 的数据使用单独的 Redis 实例部署,不使用集群环境。

如果数据量过亿甚至更大,就需要对 Geo 数据进行拆分,按国家拆分、按省拆分,按市拆分,在人口特大城市甚至可以按区拆分。这样就可以显著降低单个 Sorted Set 集合的大小。

参考资料

Redis实战篇(四)基于GEO实现查找附近的人功能的更多相关文章

  1. Redis实战篇

    Redis实战篇 1 Redis 客户端 1.1 客户端通信 原理 客户端和服务器通过 TCP 连接来进行数据交互, 服务器默认的端口号为 6379 . 客户端和服务器发送的命令或数据一律以 \r\n ...

  2. Redis 实战篇:巧用数据类型实现亿级数据统计

    在移动应用的业务场景中,我们需要保存这样的信息:一个 key 关联了一个数据集合,同时还要对集合中的数据进行统计排序. 常见的场景如下: 给一个 userId ,判断用户登陆状态: 两亿用户最近 7 ...

  3. Redis 实战篇:巧用Bitmap 实现亿级海量数据统计

    在移动应用的业务场景中,我们需要保存这样的信息:一个 key 关联了一个数据集合. 常见的场景如下: 给一个 userId ,判断用户登陆状态: 显示用户某个月的签到次数和首次签到时间: 两亿用户最近 ...

  4. Redis实战篇(一)搭建Redis实例

    今天是Redis实战系列的第一讲,先从如何搭建一个Redis实例开始. 下面介绍如何在Docker.Windows.Linux下安装. Docker下安装 1.查看可用的 Redis 版本 访问 Re ...

  5. Redis 实战篇:GEO助我邂逅附近女神

    码老湿,阅读了你的巧用数据类型实现亿级数据统计之后,我学会了如何游刃有余的使用不同的数据类型(String.Hash.List.Set.Sorted Set.HyperLogLog.Bitmap)去解 ...

  6. Redis实战篇(二)基于Bitmap实现用户签到功能

    很多应用上都有用户签到的功能,尤其是配合积分系统一起使用.现在有以下需求: 签到1天得1积分,连续签到2天得2积分,3天得3积分,3天以上均得3积分等. 如果连续签到中断,则重置计数,每月重置计数. ...

  7. Redis实战篇(三)基于HyperLogLog实现UV统计功能

    如果现在要开发一个功能: 统计APP或网页的一个页面,每天有多少用户点击进入的次数.同一个用户的反复点击进入记为 1 次,也就是统计 UV 数据. 让你来开发这个统计模块,你会如何实现? 如果统计 P ...

  8. Redis 实战篇之搭建集群

    Redis 集群简介# Redis Cluster 即 Redis 集群,是 Redis 官方在 3.0 版本推出的一套分布式存储方案.完全去中心化,由多个节点组成,所有节点彼此互联.Redis 客户 ...

  9. 微信小程序实战篇:基于wxcharts.js绘制移动报表

    前言 微信小程序图表插件(wx-charts)是基于canvas绘制,体积小巧,支持图表类型饼图.线图.柱状图 .区域图等图表图形绘制,目前wx-charts是微信小程序图表插件中比较强大好使的一个. ...

随机推荐

  1. web components in action

    web components in action web components css-doodle.js https://alligator.io/workflow/ https://d33wubr ...

  2. React Big Changes All in One

    React Big Changes All in One React 重大更新 React Versions React 版本变更 https://reactjs.org/versions/ sema ...

  3. Flutter: SliverAppBar 应用程序栏与滚动视图集成,以便它可以根据滚动偏移量在高度上变化

    API class _MyHomeState extends State<MyHome> with SingleTickerProviderStateMixin { @override W ...

  4. 心之所向·智慧绽放丨NGK区块链赋能实体经济论坛圆满落幕

    据外媒报导,近日,由NGK主办的"NGK区块链赋能实体经济论坛"于英国伦敦的威斯敏斯特中央大厅圆满落幕.大会现场到来了NGK北美市场领导人.区块链行业的专业人士.NGK英国社区代表 ...

  5. django学习-21.优化表数据的标题展示

    目录结构 1.前言 2.表数据的标题默认展示的数据格式是[模型类名 object(主键名)]的相关信息 3.优化表数据的标题展示的数据格式是[改成我们想要展示的数据格式]的相关完整操作步骤 3.1.第 ...

  6. 遇见ZooKeeper:初识

    0. 什么是ZooKeeper ZooKeeper 是一个开源的分布式,它的设计目标是将那些复杂且容易出错的分布式协同服务封装起来,抽象出一个高效可靠的原语集,并以一系列简单的接口提供个用户使用. Z ...

  7. 运行maven遇到的坑,差点崩溃了。

    参考链接1:https://blog.csdn.net/lch_cn/article/details/8225448/ 参考链接2:https://jingyan.baidu.com/article/ ...

  8. Loki日志系统

    一.概述 背景 Loki的第一个稳定版本于2019年11月19日发布,是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统. Grafana 对 Loki ...

  9. Java获取微信公众号新增用户事件

    一.新建项目工程 新建一个spring项目 填写 Group 和 Artifact 信息 这步可以直接跳过,后面再按需导入 选择工程地址 二.配置 pom.xml <dependencies&g ...

  10. es6 快速入门 —— 函数

    其他章节请看: es6 快速入门 系列 函数 函数是所有编程语言的重要组成部分,es6之前函数语法一直没什么变化,遗留了许多问题,javaScript开发者多年来不断抱怨,es6终于决定大力度更新函数 ...