5.Redis三种特殊数据类型

1.Geospatial 地理位置

思考:朋友的定位,附近的人,打车距离计算如何实现?

解决:Redis 的 Geo 在Redis3.2 版本就推出了,这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人。

参考:城市经度纬度查询网站,可以查询一些测试数据:http://www.jsons.cn/lngcodeinfo/0706D99C19A781A3/

相关六个命令:
- GEOADD
- GEODIST
- GEOHASH
- GEOPOS
- GEORADIUS
- GEORADIUSBYMEMBER

参考文档:https://www.redis.net.cn/order/3685.html

1、GEOADD 添加地理位置

语法:

# 将指定的地理空间位置(经度、纬度、名称)添加到指定的key中
GEOADD key longitude经度 latitude纬度 member地理名 [longitude latitude member ...]

规则:

# 两级无法直接添加,一般开发过程中会下载城市数据,直接通过java程序一次性导入。
# 有效的经度从-180度到180度,有效的纬度从-85.05112878度到85.05112878度,当坐标位置超出上述指定范围时,该命令将会返回一个错误。
#如下:
127.0.0.1:6379> geoadd china:city 39.90 116.40 beijing
(error) ERR invalid longitude,latitude pair 39 .900000,116.400000

案例:

# GEOADD 添加地理位置(经度、纬度、名称)
127.0.0.1:6379> geoadd china:city 116.405285 39.90498 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 114.298572 30.584355 wuhan
(integer) 1
127.0.0.1:6379> geoadd china:city 118.11022 24.490474 xiamen
(integer) 1
127.0.0.1:6379> geoadd china:city 118.767413 32.04154 nanjing
(integer) 1
127.0.0.1:6379> geoadd china:city 106.504962 29.533155 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 114.177314 22.266416 xianggang 113.549134 22.19875 aomen
(integer) 2

2、GEOPOS 获得当前定位,即坐标值

语法:

# 从key里返回所有给定位置元素的位置(经度和纬度)
GEOPOS key member [member ...]

规则:

# GEOPOS 命令返回一个数组,数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。
# 当给定的位置元素不存在时,对应的数组项为空值。

案例:

# GEOPOS  获得指定城市的经度和纬度
127.0.0.1:6379> geopos china:city wuhan
1) 1) "114.29857403039932251"
   2) "30.58435486605102227"
127.0.0.1:6379> geopos china:city nanjing aomen
1) 1) "118.76741319894790649"
   2) "32.04154071334338738"
2) 1) "113.54913264513015747"
   2) "22.19874952821576386"

3、GEODIST 返回两个指定位置之间的距离

使用场景:

# 查看距离朋友有多远,即两人之间的距离

语法:

# 返回两个给定位置之间的距离
GEODIST key member1 member2 [unit]

规则:

# 如果两个位置之间的其中一个不存在, 那么命令返回空值。

# 指定单位的参数 unit 必须是以下单位的其中一个:
	- m 表示单位为米。
	- km 表示单位为千米。
	- mi 表示单位为英里。
	- ft 表示单位为英尺。

# 如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。

案例:

# 北京距离南京的直线距离
127.0.0.1:6379> geodist china:city beijing nanjing
"899992.6369"
# 武汉距离重庆的直线距离,单位是km千米
127.0.0.1:6379> geodist china:city wuhan chongqing km
"759.1648"

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

使用场景:

# 附近的人 (第一步打开定位,第二步获得所有附近的人的地址,第三步通过半径来查询)

# 附近的50人(另指定人的数量)

语法:

# 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUS key longitude latitude radius m|km|ft|mi 
[WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

规则:

# 范围可以使用以下其中一个单位:
	- m  表示单位为米。
	- km 表示单位为千米。
	- mi 表示单位为英里。
	- ft 表示单位为英尺。
	
# 在给定以下可选项时, 命令会返回额外的信息:
	- WITHDIST:在返回位置元素的同时,将位置元素与中心之间的距离也一并返回。距离的单位和用户给定的范围单位保持一致。
	- WITHCOORD:将位置元素的经度和维度也一并返回。
	- WITHHASH:以52位有符号整数的形式,返回位置元素经过原始geohash编码的有序集合分值。这个选项主要用于底层应用或者调试,实际中的作用并不大。
	
# 使用 COUNT <count> 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。

# 命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:
	- ASC:根据中心的位置,按照从近到远的方式返回位置元素。
	- DESC:根据中心的位置,按照从远到近的方式返回位置元素。

案例:

# 以 110 , 30 这个经纬度为中心,寻找方圆1000km内的城市
127.0.0.1:6379> georadius china:city 110 30 1000 km
1) "chongqing"
2) "aomen"
3) "xianggang"
4) "wuhan"
5) "nanjing"
# 以 110 , 30 这个经纬度为中心,寻找方圆500km内的城市
127.0.0.1:6379> georadius china:city 110 30 500 km
1) "chongqing"
2) "wuhan"

# 显示距离中心500km内的城市的位置信息(经纬度) 
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord
1) 1) "chongqing"
   2) 1) "106.50495976209640503"
      2) "29.53315530684997015"
2) 1) "wuhan"
   2) 1) "114.29857403039932251"
      2) "30.58435486605102227"
# 显示距离中心500km内的城市的直线距离
127.0.0.1:6379> georadius china:city 110 30 500 km withdist
1) 1) "chongqing"
   2) "341.4052"
2) 1) "wuhan"
   2) "417.8920"

# 显示距离中心500km内的城市的位置信息、直线距离、第一项 
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord withdist count 1
1) 1) "chongqing"
   2) "341.4052"
   3) 1) "106.50495976209640503"
      2) "29.53315530684997015"

# 显示距离中心500km内的城市,由远到近
127.0.0.1:6379> georadius china:city 110 30 1000 km desc
1) "xianggang"
2) "aomen"
3) "nanjing"
4) "wuhan"
5) "chongqing"

5、GEORADIUSBYMEMBER 根据位置元素找出位于指定范围内的元素

使用场景:

# 城市与城市之间的距离、导航距离等

语法:

# 这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点指定成员的位置被用作查询的中心。
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

案例:

# 根据位置元素,查询指定范围内的元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "nanjing"
2) "beijing"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city wuhan 500 km
1) "wuhan"
2) "nanjing"

6、GEOHASH 返回一个或多个位置元素的 Geohash 表示

语法:

# 返回一个或多个位置元素的Geohash表示,该命令将返回11个字符的Geohash字符串
GEOHASH key member [member ...]

案例:

# 将位置元素的经纬度转换成11位的hash值显示
# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近
127.0.0.1:6379> GEOHASH china:city beijing nanjing
1) "wx4g0b7xre0"
2) "wtsqq8gz920"

7、GEO 底层的实现原理其实就是 Zset

可以使用Zset命令来操作Geospatial地理位置

# 查看地图中全部的元素
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "aomen"
3) "xianggang"
4) "xiamen"
5) "wuhan"
6) "nanjing"
7) "beijing"

# 移除指定元素
127.0.0.1:6379> zrem china:city aomen
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xianggang"
3) "xiamen"
4) "wuhan"
5) "nanjing"
6) "beijing"

2.Hyperloglog 基数统计

1、什么是基数?

一个数据集内不重复的元素,且可以接受误差。

2、简介

Redis 2.8.9 版本就更新了 Hyperloglog 数据结构,Redis Hyperloglog 基数统计的算法。

3、使用场景

网页的 UV 即页面访问量(例如,一个人访问一个网站多次,但是还是算作一个人)

传统的方式, set(无序不重复)保存用户的id,然后就可以统计 set 中的元素数量作为标准判断。这个方式如果保存大量的用户id,就会比较麻烦,占内存, 我们的目的是为了计数,而不是保存用户id。

现在的方式,可以使用 Hyperloglog进行存储,占用的内存是固定,2^64 不同元素的基数,只需要12KB内存。如果要从内存角度来比较的话Hyperloglog首选。可能会出现0.81%的 错误率,统计UV任务时,是可以忽略不计的。

4、案例

PFADD 创建元素 PFCOUNT 基数统计(不统计重复数据) PFMERGE 合并元素

# 创建第一组元素 my1
127.0.0.1:6379> PFADD my1 a b c d e f g h i j k
(integer) 1
# 统计 my1 元素的基数数量
127.0.0.1:6379> PFCOUNT my1
(integer) 11

# 创建第二组元素 my2
127.0.0.1:6379> PFADD my2 j k l m n a d e o p
(integer) 1
# 统计 my2 元素的基数数量
127.0.0.1:6379> PFCOUNT my2
(integer) 10

# 合并两组 my1 my2 => my3 并集
127.0.0.1:6379> PFMERGE my3 my1 my2
OK
# 统计 my3 元素的基数数量,即并集的数量
127.0.0.1:6379> PFCOUNT my3
(integer) 16

5、测试使用

如果允许容错,那么一定可以使用 Hyperloglog。

如果不允许容错,就使用 set 或者自己的数据类型即可。

3.Bitmap 位存储

1、使用场景

统计用户信息,活跃 或 不活跃、 登录 或 未登录、 打卡 或 未打卡。涉及 两个状态的,都可以使用Bitmap位存储。

Bitmap 位图也是一种数据结构,都是操作二进制位来进行记录,就只有 0 和 1 两个状态。

等价于 365 天 = 365 bit 1字节 = 8bit 46 个字节左右,即若记录某个学生的一年打卡情况,则只需耗费46个字节左右。

2、案例

# 使用Bitmap来记录周一到周日的打卡,例如,周一: 1 周二: 1 周三: 1 周四:0 ......
127.0.0.1:6379> setbit ding 0 1
(integer) 0
127.0.0.1:6379> setbit ding 1 1
(integer) 0
127.0.0.1:6379> setbit ding 2 1
(integer) 0
127.0.0.1:6379> setbit ding 3 0
(integer) 0
127.0.0.1:6379> setbit ding 4 1
(integer) 0
127.0.0.1:6379> setbit ding 5 1
(integer) 0
127.0.0.1:6379> setbit ding 6 0
(integer) 0
127.0.0.1:6379> setbit ding 7 0
(integer) 0

# 查看某一天是否有打卡,返回1则打卡,返回0则未打卡
127.0.0.1:6379> getbit ding 1
(integer) 1
127.0.0.1:6379> getbit ding 3
(integer) 0

# 统计操作,统计打卡的天数,即统计这周的打卡记录,就可以看到是否有全勤
127.0.0.1:6379> bitcount ding
(integer) 5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

what's your name.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值