Redis 副本-03 【Redis三种特殊类型】
Redis 三种特殊类型
geospatial(地理位置)
可以先思考一下:朋友定位、附近的人、打车距离是怎么实现的?
Redis 的 Geo 在 3.2 版本的时候就推出了。这个功能可以推算出地理位置的信息、两地的距离、方圆几里的人。
添加地理位置
GEOADD key longitude latitude member [longitude latitude member ...]
两极无法直接添加
127.0.0.1:6379> geoadd china:city 104.071 30.67 chengdu (integer) 1 127.0.0.1:6379> geoadd china:city 116.408 39.904 beijing 117.246 39.117 tianjin (integer) 2
GEOPOS key member [member ...] # 获取指定城市的经度和纬度
127.0.0.1:6379> geopos china:city chengdu # 获取指定城市的经度和纬度 1) 1) "104.07099992036819458" 2) "30.67000055930392222"
获取两个地理位置之间的距离
GEODIST key member1 member2 [m|km|ft|mi]
如果缺少一个或两个成员,该命令将返回错误: (error) ERR wrong number of arguments for ‘geodist‘ command
单位必须是以下之一,默认为 meters(米):
- m(米)
- km(千米)
- mi(英里)
- ft(英尺)
假设地球是一个完美的球体,因此计算距离,因此在极端情况下可能会产生高达0.5%的误差。
127.0.0.1:6379> geodist china:city chengdu beijing "1516909.8552" 127.0.0.1:6379> geodist china:city chengdu beijing km "1516.9099"
以给定的经纬度为中心,找出某一半径内的元素
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
该命令可以选择使用以下选项返回其他信息:
WITHDIST
:还返回返回的项目到指定中心的距离。距离以与指定为命令的radius参数的单位相同的单位返回。WITHCOORD
:还返回匹配项的经度,纬度坐标。WITHHASH
:还以52位无符号整数的形式返回商品的原始geohash编码排序集得分。这仅对低级黑客或调试有用,否则对普通用户几乎没有兴趣。该命令默认为返回未排序的项目。可以使用以下两个选项来调用两种不同的排序方法:
ASC
:相对于中心,从最近到最远对返回的项目进行排序。DESC
:相对于中心,从最远到最近对返回的项目进行排序。默认情况下,将返回所有匹配项。通过使用COUNT``选项,可以将结果限制为前N个匹配项。但是请注意,命令内部需要执行与指定区域匹配的项数成比例的工作量,因此
COUNT
即使返回的结果很少,使用很小的选项查询很大的区域也可能很慢。另一方面,COUNT
如果通常仅使用第一个结果,则这可能是减少带宽使用的非常有效的方法。
127.0.0.1:6379> georadius china:city 100 35 2000 km 1) "chengdu" 2) "tianjin" 3) "beijing" 127.0.0.1:6379> georadius china:city 100 35 1000 km 1) "chengdu" 127.0.0.1:6379> georadius china:city 100 35 2000 km withcoord 1) 1) "chengdu" 2) 1) "104.07099992036819458" 2) "30.67000055930392222" 2) 1) "tianjin" 2) 1) "117.24599987268447876" 2) "39.11699937833952134" 3) 1) "beijing" 2) 1) "116.40800267457962036" 2) "39.90399988166036138" 127.0.0.1:6379> georadius china:city 100 35 2000 km withdist 1) 1) "chengdu" 2) "613.6166" 2) 1) "tianjin" 2) "1594.9157" 3) 1) "beijing" 2) "1545.2112" 127.0.0.1:6379> georadius china:city 100 35 2000 km withdist desc 1) 1) "tianjin" 2) "1594.9157" 2) 1) "beijing" 2) "1545.2112" 3) 1) "chengdu" 2) "613.6166" 127.0.0.1:6379> georadius china:city 100 35 2000 km withdist count 1 1) 1) "chengdu" 2) "613.6166"
找出指定范围内的元素,中心点由给定的位置元素指定
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
该命令与GEORADIUS完全相同,唯一的区别在于,它不使用经度和纬度值作为要查询的区域的中心,而是采用已存在于由排序集表示的地理空间索引中的成员的名称。
127.0.0.1:6379> georadiusbymember china:city tianjin 1000 km 1) "tianjin" 2) "beijing"
返回一个或多个位置元素的 Geohash 表示,了解即可!
GEOHASH key member [member ...]
返回有效的Geohash字符串,该字符串表示一个或多个元素在代表地理空间索引的排序后的集合值中的位置(使用GEOADD在其中添加了元素)。
通常,Redis使用Geohash技术的变体表示元素的位置,其中位置是使用52位整数编码的。与标准相比,编码也有所不同,因为在编码和解码过程中使用的初始最小和最大坐标是不同的。但是,此命令以字符串形式返回标准的Geohash,如Wikipedia文章中所述,并且与geohash.org网站兼容。
Geohash字符串属性
该命令返回11个字符的Geohash字符串,因此与Redis内部52位表示形式相比,不会损失任何精度。返回的Geohash具有以下属性:
127.0.0.1:6379> geohash china:city chengdu 1) "wm6n2pq1wn0"
Geo 底层的实现原理就是 Zset,所以我们可以使用 Zset 的命令删除一个元素
127.0.0.1:6379> keys * 1) "china:city" 127.0.0.1:6379> type china:city zset 127.0.0.1:6379> zrange china:city 0 -1 1) "chengdu" 2) "tianjin" 3) "beijing" 127.0.0.1:6379> zrem china:city chengdu (integer) 1 127.0.0.1:6379> zrange china:city 0 -1 1) "tianjin" 2) "beijing"
HyperLogLogs(基数统计)
什么是基数?
A{1, 2, 3, 4, 5}
B{3, 5, 6, 7, 9}基数(不重复的元素)= 1, 2, 4, 6, 7, 9
可以接收误差!
HyperLogLogs 基数统计的算法!
比如:网站的 UA(一个人访问网站多次,但还是算作一个人)
传统解决方式:使用 Set 保存用户的 id,然后统计 Set 中的元素
但是这种方式会保存大量的用户 id,比较麻烦!
HyperLogLogs 优点:占用内存固定,2^64 不同的元素的基数,只需要 12KB 内存
127.0.0.1:6379> pfadd key1 a b c d e f g h i # 创建第一组元素 (integer) 1 127.0.0.1:6379> pfcount key1 # 统计元素的基数数量 (integer) 9 127.0.0.1:6379> pfadd key2 c j k l m e g a # 创建第二组元素 (integer) 1 127.0.0.1:6379> pfcount key2 (integer) 8 127.0.0.1:6379> pfmerge key3 key1 key2 # 合并两组:key1 key2 -> key3 并集 OK 127.0.0.1:6379> pfcount key3 (integer) 13
BitMaps(位存储)
统计用户是否活跃,登录及未登录状态......。两个状态的都可以使用 BitMaps
BitMaps 位图,数据结构!都是操作二进制位来进行记录,只有 0 和 1 两种状态!
# 使用 bitmap 来记录 周一到周日的登录状态 127.0.0.1:6379> setbit touyel:sign 0 1 (integer) 0 127.0.0.1:6379> setbit touyel:sign 1 1 (integer) 0 127.0.0.1:6379> setbit touyel:sign 2 0 (integer) 0 127.0.0.1:6379> setbit touyel:sign 3 1 (integer) 0 127.0.0.1:6379> setbit touyel:sign 4 0 (integer) 0 127.0.0.1:6379> setbit touyel:sign 5 0 (integer) 0 127.0.0.1:6379> setbit touyel:sign 6 1 (integer) 0 # 查看是否登录 127.0.0.1:6379> getbit touyel:sign 1 (integer) 1 127.0.0.1:6379> getbit touyel:sign 2 (integer) 0 # 统计登录的天数 127.0.0.1:6379> bitcount touyel:sign (integer) 4