1.Redis的源码数据类型-GEO
2.LBS - 空间索引Spatial Index
3.Redis GEO 命令学习及原理浅析
4.redis应用 8:GeoHash
5.使用Go语言手写一个简易版Redis,项目经验稳了!源码
6.Redis 源码限流的 3 种方式,还有谁不会!源码
Redis的数据类型-GEO
Redis新增的GEO数据类型主要用于存储和操作地理位置信息。GEO实际上是源码网站源码查看后门一种有序集合(zset),每个元素包含经度、源码纬度和位置名称,源码通过这些属性,源码可以在Redis中存储和操作地理坐标。源码 使用场景主要涉及地图应用、源码位置服务、源码地理空间分析等,源码例如商家定位、源码位置搜索和推荐、源码用户位置分析等。常用命令
1. 添加:GEOADD命令 功能:用于存储指定的地理空间位置,可以将一个或多个经度、纬度和位置名称添加到指定的key中。 语法:GEOADD key [NX|XX] [CH] longitude latitude member [longitude latitude member ...] 参数说明:longite:地点的经度,范围:-度到度,经度必须放在纬度之前。
latitude:地点的纬度,范围:-.度到.度。
member:地点名称。
选项说明:NX:不添加新元素,只更新既有元素,v6.2.0版本出现。
XX:不更新既有元素,只添加新元素,v6.2.0版本出现。
CH:返回变更过的元素数量,同时包含新增和更新,v6.2.0版本出现。
返回值:整型,返回新增或变更的元素数量。 注意:使用GEOADD命令添加坐标时,若已有相同位置,则使用新坐标替换已有坐标。 示例: 2. 查询:GEOPOS命令 功能:从给定key中返回指定名称的位置(经度和纬度)。 语法:GEOPOS key member [member ...] 返回:数组,每个元素为一个包含经度和纬度的源码动漫是什么子数组。 示例: 3. 计算举例:GEODIST命令 功能:返回两个成员之间的距离,基于地球为完美球体的假设,计算结果可能存在%0.5误差。 语法:GEODIST key member1 member2 [M | KM | FT | MI] 选项说明:M:单位:米。
KM:单位:公里(千米)。
FT:单位:英里。
M:单位:英尺。
返回:可以转换为双精度浮点型的字符串。 4. 获取GEOHASH值:GEOHASH命令 Geohash是一种地理编码系统,将经纬度编码为数字和字母组成的字符串。虽然表示的是区域,但可以用于隐私保护。 功能:返回指定成员的地理位置的GEOHASH值。 语法:GEOHASH key member [member ...] 返回值:数组,包含每个位置成员对应的GEOHASH值。 示例: 5. 查询指定范围的地点:GEOSEARCH命令 功能:以经纬度为中心,返回距离不超过最大距离的所有位置元素。 语法:GEOSEARCH key FROMMEMBER member | FROMLONLAT longitude latitude BYRADIUS radius [ASC | DESC][COUNT count [ANY]][WITHCOORD][WITHDIST][WITHHASH] 选项说明:FROMMEMBER:指定起始成员。
FROMLONLAT:指定经纬度。
BYRADIUS:指定最大距离。
ASC | DESC:返回结果的排序。
COUNT:返回结果的数量。
WITHCOORD:返回经度和纬度。
WITHDIST:返回与中心点的距离。
WITHHASH:返回GEOHASH值。
返回值:数组,包含名称、经纬度、距离、GEOHASH值等信息。 示例: 6. 查询指定范围的地点:GEOSEARCHSTORE命令 功能:存储匹配结果,将位置信息存储到目标键中。默认存储位置信息,可选以距离作为分数存储。 语法:GEOSEARCHSTORE destination source FROMMEMBER member | FROMLONLAT longitude latitude BYRADIUS radius [ASC | DESC] [COUNT count [ANY]][STOREDIST] 返回值:整型,存储的成员数量。 示例:LBS - 空间索引Spatial Index
空间索引Spatial Index
在O2O行业中,LBS(基于位置的服务)应用广泛,例如根据用户定位召回附近商家,或召回附近空闲出租车。这些服务依赖空间检索(Spatial Index)技术,Linux 内核源码量通常将球面坐标系通过墨卡托投影映射到二维平面坐标系,以此实现位置检索。
空间索引的基本概念包括GeoHash、R-树、四叉树等。GeoHash通过将二维矩形区域映射成一维字符串,实现空间对象的高效存储和检索。R-树是一种基于矩形的平衡树,适用于处理空间数据的索引。四叉树是二维空间的递归细分,适合存储和查询有二维属性的数据。
不同存储系统如MySQL、PostgreSQL、Redis、MongoDB和ElasticSearch在空间索引方面具有各自特点。MySQL 5.7引入了原生的GeoHash支持和空间索引功能,适合需要高性能和可扩展性的应用。PostgreSQL通过PostGIS扩展支持复杂查询,效率极高。Redis在3.2版本后增加了空间索引支持,适用于数据量较小的应用。MongoDB提供灵活的空间索引和查询,支持多种几何操作。ElasticSearch提供强大的地理位置功能和全文搜索结合,适用于复杂查询和分析。
在实际业务中,应综合考虑数据量、检索复杂度和运维需求,选择合适的存储引擎。例如,MySQL适用于需要高性能和可扩展性的应用,而MongoDB则在处理大量非结构化数据时表现良好。ElasticSearch在复杂查询和分析场景中展现出色性能。
本文旨在介绍空间索引的基本概念和技术,并对比不同存储系统的特点,希望为开发者在空间检索服务技术评估和选型时提供参考。
Redis GEO 命令学习及原理浅析
Redis GEO命令在地理位置服务应用中发挥着关键作用,它利用Sorted Set数据结构和GeoHash编码实现高效地基于经纬度的查询。GeoHash编码将经纬度转换为分数值,确保了具有相近分数的元素在实际地理空间上也接近。通过划分小方格并映射到一维空间,酷喵影视源码Redis GEO允许精准的"搜索附近"功能。
例如,GEOADD命令在≥3.2.0版本可用,它将地理位置信息添加到Sorted Set中,使用O(log(N))的时间复杂度。GEOPOS命令用于获取指定元素的经纬度,GEODIST则计算两点间的距离。GEOHASH则返回元素的GeoHash编码,便于范围查询。而6.2.0版本之后,GEORADIUS和GEORADIUSBYMEMBER命令被废弃,推荐使用GEOSEARCH和GEOSEARCHSTORE,它们提供了更灵活的查询和结果处理方式。
总结来说,Redis GEO利用GeoHash编码和Sorted Set的数据结构,为基于位置的服务提供了高效且精确的查询能力。通过理解这些命令的原理和使用方法,开发者可以更好地在实际应用中利用Redis GEO实现地理位置相关的需求。
redis应用 8:GeoHash
Redis在3.2版本后加入的GEO模块使我们能利用Redis实现地理定位功能,如摩拜单车的"附近Mobike"、美团与饿了么的"附近餐馆"。
地图元素位置数据用二维经纬度表示,范围在经度(-, ],纬度(-, ]。掘金办公室在望京SOHO的坐标(.,.)正数,中国位于东北半球。
当元素距离不遥远时,使用勾股定理计算距离。但考虑经纬度坐标密度不均,计算距离时需加权。精确计算时,避免加权。
经度度,维度度,距离密度非2:1,原因在于地球形状。
计算"附近的人",即给定坐标,按距离排序元素,如何入手?
遍历计算所有元素距离过于耗时,应使用矩形区域限定元素数量,价值线公式源码计算区域内元素距离,再排序。选择半径r,通过SQL圈定区域。用户不满意结果时,扩大半径继续筛选。
高性能矩形区域算法要求数据表在经纬度坐标上加双向复合索引(x, y)。
高并发场景下,数据库查询性能有限,大量"附近的人"查询可能不是一个好方案。
GeoHash算法
业界常用GeoHash算法计算地理距离。Redis采用GeoHash。该算法将二维坐标映射到一维整数,元素距离相近的坐标映射后点间距亦相近。需计算附近的人时,将目标位置映射到线上,获取线上的附近点。
GeoHash算法如何映射坐标?假设地球为二维平面,分割成正方形方格,每格唯一。方格越小,坐标越精确。然后对这些方格进行整数编码,越近的方格编码越接近。编码法为“切蛋糕法”,将正方形蛋糕二刀均分成四块,标记为、、、四个二进制整数。接着将每个小正方形继续切割,每块使用4bit二进制整数表示。如此递归,正方形变小,二进制整数变长,精确度提高。
编码后,每个坐标变为整数,损失程度与整数长度相关。对于"附近的人"功能,损失的精度忽略不计。
GeoHash算法将整数base编码,存入Redis的zset中,score为元素key,值为位整数。
在Redis进行Geo查询时,注意其内部结构为zset(skiplist),通过score排序获取坐标附近的元素。将score还原为坐标值即可得到元素原始坐标。
Redis Geo指令
Redis提供6个Geo指令,易于掌握。使用时,需牢记其本质上是zset。
增加指令:使用geoadd添加集合名称和多个经纬度名称三元组。
距离计算:使用geodist指令计算两个元素距离,携带集合名称、名称和单位。
获取位置:geopos指令获取集合中任意元素经纬度坐标,一次可获取多个。
获取元素hash值:使用geohash指令获取元素经纬度编码字符串,可用于查询。
附近公司查询:georadiusbymember指令查询指定元素附近元素,参数复杂。
总结与注意事项
地图应用中,数据量庞大,使用Redis Geo结构时,应避免单个key数据量过大影响集群迁移,线上服务运行。推荐使用单独的Redis实例部署Geo数据,避免集群环境。
数据量过大时,Geo数据应按国家、省、市乃至区拆分,降低单个集合大小。
使用Go语言手写一个简易版Redis,项目经验稳了!
大家好,我是 G哥! 今天,我向大家分享一个利用 Go 语言打造的简易版 Redis 项目,这个项目旨在帮助开发者深入了解 Go 语言和构建高并发中间件。 这个简易版 Redis 具备基本功能,如数据存储、缓存和键值对操作等,满足开发者学习和实践需求。通过探索此项目,不仅能够深化对 Go 语言的理解,还能够领略到使用 Go 语言开发高性能、并发处理系统的魅力。 项目提供了 Darwin (MacOS) 和 Linux 版本的可执行文件,使用简便。启动方法如下:下载项目可执行文件
运行启动命令
启动后,即可通过 redis-cli 或其他 Redis 客户端连接到默认监听的 端口,进行数据交互。 项目代码量较多,但学习并非难事。作者提供了详尽的教程指南,覆盖从 Go 编写 TCP 服务器到实现内存数据库、GeoHash 搜索功能等核心内容,对学习者友好。 感谢作者对开源社区的贡献,通过这个项目,开发者能够在实践中学到宝贵的经验。项目地址如下: github.com/HDT/godi... 通过探索和实践这个简易版 Redis 项目,相信你能够提升编程技能,更好地理解 Go 语言在并发处理和高性能系统构建中的应用。Redis 限流的 3 种方式,还有谁不会!
面对越来越多的高并发场景,限流显示的尤为重要。当然,限流有许多种实现的方式,Redis具有很强大的功能,我用Redis实践了三种的实现方式,可以较为简单的实现其方式。Redis不仅仅是可以做限流,还可以做数据统计,附近的人等功能,这些可能会后续写到。
第一种:基于Redis的setnx的操作我们在使用Redis的分布式锁的时候,大家都知道是依靠了setnx的指令,在CAS(Compare and swap)的操作的时候,同时给指定的key设置了过期实践(expire),我们在限流的主要目的就是为了在单位时间内,有且仅有N数量的请求能够访问我的代码程序。所以依靠setnx可以很轻松的做到这方面的功能。
比如我们需要在秒内限定个请求,那么我们在setnx的时候可以设置过期时间,当请求的setnx数量达到时候即达到了限流效果。代码比较简单就不做展示了。
当然这种做法的弊端是很多的,比如当统计1-秒的时候,无法统计2-秒之内,如果需要统计N秒内的M个请求,那么我们的Redis中需要保持N个key等等问题。
第二种:基于Redis的数据结构zset其实限流涉及的最主要的就是滑动窗口,上面也提到1-怎么变成2-。其实也就是起始值和末端值都各+1即可。
而我们如果用Redis的list数据结构可以轻而易举的实现该功能。
我们可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求
代码如下
publicResponselimitFlow(){ LongcurrentTime=newDate().getTime();System.out.println(currentTime);if(redisTemplate.hasKey("limit")){ Integercount=redisTemplate.opsForZSet().rangeByScore("limit",currentTime-intervalTime,currentTime).size();//intervalTime是限流的时间System.out.println(count);if(count!=null&&count>5){ returnResponse.ok("每分钟最多只能访问5次");}}redisTemplate.opsForZSet().add("limit",UUID.randomUUID().toString(),currentTime);returnResponse.ok("访问成功");}通过上述代码可以做到滑动窗口的效果,并且能保证每N秒内至多M个请求,缺点就是zset的数据结构会越来越大。实现方式相对也是比较简单的。
第三种:基于Redis的令牌桶算法提到限流就不得不提到令牌桶算法了。
令牌桶算法提及到输入速率和输出速率,当输出速率大于输入速率,那么就是超出流量限制了。
也就是说我们每访问一次请求的时候,可以从Redis中获取一个令牌,如果拿到令牌了,那就说明没超出限制,而如果拿不到,则结果相反。
依靠上述的思想,我们可以结合Redis的List数据结构很轻易的做到这样的代码,只是简单实现
依靠List的leftPop来获取令牌
//输出令牌publicResponselimitFlow2(Longid){ Objectresult=redisTemplate.opsForList().leftPop("limit_list");if(result==null){ returnResponse.ok("当前令牌桶中无令牌");}returnResponse.ok(articleDescription2);}再依靠Java的定时任务,定时往List中rightPush令牌,当然令牌也需要唯一性,所以我这里还是用UUID进行了生成
//S的速率往令牌桶中添加UUID,只为保证唯一性@Scheduled(fixedDelay=_,initialDelay=0)publicvoidsetIntervalTimeTask(){ redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());}综上,代码实现起始都不是很难,针对这些限流方式我们可以在AOP或者filter中加入以上代码,用来做到接口的限流,最终保护你的网站。
Redis其实还有很多其他的用处,他的作用不仅仅是缓存,分布式锁的作用。他的数据结构也不仅仅是只有String,Hash,List,Set,Zset。有兴趣的可以后续了解下他的GeoHash算法;BitMap,HLL以及布隆过滤器数据(Redis4.0之后加入,可以用Docker直接安装Redislabs/rebloom)结构。
有问题欢迎留言探讨。
原文链接:/lmx/article/details/
redis学习笔记(二) - redis的数据类型bitmap/hyperloglog/GEO
数据类型与应用案例
在日常应用中,常见数据类型如bitmap、hyperloglog与GEO数据结构用于处理大规模数据的收集与统计,具有存取高效、多维度统计分析的优势。
例如,手机App中的每天用户登录信息、电商网站商品的用户评论列表、用户在App上的签到打卡信息以及网页访问信息等,这些场景下数据量大,需要快速存取与统计。
面试问题可能涉及如何利用集合数据进行统计分析,如在移动应用中统计每日新增用户数与留存用户数,电商网站评论列表中最新评论的处理,签到打卡中连续打卡用户的数量统计,以及网页访问记录中独立访客数量的计算。
数据类型选择与功能
针对统计需求,常用数据类型包括:
二值统计(如bitmap):用于表示集合中元素的取值,仅支持0和1两种状态,适合记录如用户是否登录过、**是否被点击播放等二元信息。
基数统计(如hyperloglog):用于统计集合中不重复的元素个数,即去重后的真实数量,适合计算UV(独立访客)、PV(页面访问量)、DAU(日活跃用户量)和MAU(月活跃用户量)等指标。
地理定位(如GEO):在需要处理地理位置数据的应用中,如滴滴打车等,GEO数据结构可实现高效地理位置查询与存储。
应用场景举例
日活跃用户统计、连续签到打卡情况分析、一周活跃用户列表、特定用户登录天数统计等,均可以通过上述数据类型实现高效、准确的数据统计与分析。
以抖音应用的最新留言评价为例,需要对评论进行排序与分页显示,此时可使用Redis数据结构实现排序与分页功能,提高用户体验。
关于签到打卡统计,bitmap数据类型能够高效记录用户是否签到的状态,节省存储空间,且便于计算连续签到天数等统计指标。
基数统计如hyperloglog,则适用于处理大量数据的UV与PV等统计需求,通过概率算法降低内存占用,牺牲部分准确率以换取更高的效率。
GEO数据结构在地理信息处理中,如滴滴打车定位车辆位置,通过GEOHash算法将三维坐标转换为一维点块,再进行高效查询。
综合而言,Redis提供的多种数据类型与操作命令,能够针对不同场景与需求提供高效的数据存储与统计分析能力,实现大数据环境下应用的性能优化。
2024-11-27 10:31
2024-11-27 10:29
2024-11-27 09:26
2024-11-27 09:00
2024-11-27 08:39
2024-11-27 08:39