Redis篇(4)--三种特殊类型

Geospatial(地理空间)

朋友圈的定位、附近的人、打车距离 … 如何计算?

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

geoadd 添加一个或多个地理空间位置(经度、纬度、名称)到添加到指定的key中

  • 参数:key 值(经度、纬度、名称)

  • 两极地区无法直接添加

  • 一般会下载城市数据,直接通过程序一次性导入

  • 有效的经度从-180度到180度

  • 有效的纬度从-85.05112878度到85.05112878度

当坐标位置超出上述指定范围时,该命令将会返回一个错误。

127.0.0.1:6379> geoadd china:city 116.405289 39.904987 beijing # 添加一个
(integer) 1
127.0.0.1:6379> geoadd china:city 121.472641 31.231707 shanghai 113.28064 23.125177 guangzhou # 添加多个
(integer) 2
127.0.0.1:6379> geoadd china:city 114.085945 22.547001 shenzhen 120.15358 30.287458 hangzhou
(integer) 2

geopos 返回地理空间的经纬度

127.0.0.1:6379> geopos china:city beijing
1) 1) "116.40528827905654907"
   2) "39.90498588819134085"
127.0.0.1:6379> geopos china:city shanghai
1) 1) "121.47264093160629272"
   2) "31.23170744181923197"

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

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

指定单位的参数 unit 必须是以下单位的其中一个:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

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

127.0.0.1:6379> geodist china:city beijing shanghai    # 北京到上海直线距离(米)
"1067597.0432"
127.0.0.1:6379> geodist china:city beijing shanghai km # 千米
"1067.5970"

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

范围可以使用以下其中一个单位:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

在给定以下可选项时, 命令会返回额外的信息:

  • WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
  • WITHCOORD: 将位置元素的经度和纬度也一并返回。
127.0.0.1:6379> georadius china:city 110 20 500 km  # 以110,20 这个经纬度为中心,寻找半径500km以内的城市
1) "guangzhou"
127.0.0.1:6379> georadius china:city 110 20 1000 km # 半径1000km以内
1) "shenzhen"
2) "guangzhou"
127.0.0.1:6379> georadius china:city 110 20 1000 km withcoord # withcoord 额外返回经纬度
1) 1) "shenzhen"
   2) 1) "114.08594459295272827"
      2) "22.54699993773966327"
2) 1) "guangzhou"
   2) 1) "113.28063815832138062"
      2) "23.12517743834835215"
127.0.0.1:6379> georadius china:city 110 20 1000 km withdist  # withdist 额外返回到中心的直线距离
1) 1) "shenzhen"
   2) "509.4622"
2) 1) "guangzhou"
   2) "485.7406"
127.0.0.1:6379> georadius china:city 110 20 1000 km withcoord withdist count 1 # count 获取前 N 个匹配元素
1) 1) "guangzhou"
   2) "485.7406"
   3) 1) "113.28063815832138062"
      2) "23.12517743834835215"

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

这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点

指定成员的位置被用作查询的中心。

127.0.0.1:6379> georadiusbymember china:city guangzhou 1000 km # 以广州为中心,查询半径1000km以内的城市
1) "shenzhen"
2) "guangzhou"
127.0.0.1:6379> georadiusbymember china:city shanghai 500 km   # 以上海为中心,查询半径500km以内的城市
1) "hangzhou"
2) "shanghai"

geohash 返回一个或多个位置元素的 Geohash 表示

该命令将返回11个字符的Geohash字符串

将二维的经纬度转换为一维的字符串,如果两个字符串越接近,则代表该距离越近

127.0.0.1:6379> geohash china:city guangzhou		  # 返回一个
1) "ws0e9cb3yj0"
127.0.0.1:6379> geohash china:city guangzhou shenzhen # 返回多个
1) "ws0e9cb3yj0"
2) "ws10k0dcg10"

小结

Geo 底层的实现原理其实就是Zset,我们可以使用Zset命令来实现Geo

# 使用Zset命令操作Geo
127.0.0.1:6379> zrange china:city 0 -1   # 查看地图中的全部元素
1) "shenzhen"
2) "guangzhou"
3) "hangzhou"
4) "shanghai"
5) "beijing"
127.0.0.1:6379> zrem china:city hangzhou # 移除指定元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "shenzhen"
2) "guangzhou"
3) "shanghai"
4) "beijing"

HyperLogLog(基数统计)

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

什么是基数?

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

统计网站的UV?(uv 访客数,一天内同个访客多次访问仅计算一个UV)

传统方式:

  • set保存用户的id,然后就可以统计set中元素数量作为判断标准。
  • 如果保存大量的用户id,相对麻烦,我们的目的是计数而不是为了保存用的id

HyperLogLog :

  • 占用的内存是固定的,计算 2^64 个不同元素的基数,只需要花费 12 KB 内存。
  • 如果从内存的角度来比较的话 HyperLogLog 首选
  • 0.81%错误率,统计UV,可以忽略不计
# pfadd   添加指定元素到 HyperLogLog 中
# pfcount 返回给定 HyperLogLog 的基数估算值
# pfmerge 将多个 HyperLogLog 合并为一个 HyperLogLog
127.0.0.1:6379> pfadd mykey1 A B C D         # 创建第一组元素 mykey1
(integer) 1
127.0.0.1:6379> pfcount mykey1 				 # 统计 mykey1 元素的基数值
(integer) 4
127.0.0.1:6379> pfadd mykey2 C D E F		 # 创建第一组元素 mykey2
(integer) 1
127.0.0.1:6379> pfcount mykey2				 # 统计 mykey2 元素的基数值
(integer) 4
127.0.0.1:6379> pfmerge mykey3 mykey1 mykey2 # 合并 mykey1 + mykey2 => mykey3(并集)
OK
127.0.0.1:6379> pfcount mykey3				 # 合并后的基数值
(integer) 6

Bitmaps(位图)

什么是 Bitmaps ?

Bitmaps是一种数据结构,通过操作二进制的位来记录,只有 0 或 1两种状态

Bitmaps 并不是实际的数据类型,而是定义在String类型上的一个面向字节操作的集合。因为字符串是二进制安全的块,他们的最大长度是512M,最适合设置成2^32个不同字节。

Bitmaps 的最大优势之一在存储信息时极其节约空间。

在计算机系统中,最小的信息单位是字节,1个字节等于8位,每一位都只可能是0或1(计算机只认识这两个数)。使用Bitmaps可以直接对位进行操作。

可以把bigmaps看做一个数组,数组里每一位只可能是0或者1,数组的下标在这里看做偏移量

可用于位存储,使用场景:

  • 打卡
  • 活跃度:活跃、不活跃
  • 登录状态:登录、未登录
  • 两个状态的切换、表示…

使用bitmaps来记录周一到周日打卡状态

# setbit   对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)
# getbit   对 key 所储存的字符串值,获取指定偏移量上的位(bit)
# bitcount 统计字符串被设置为1的bit数

# 0 未打卡,1 已打卡
127.0.0.1:6379> setbit sign 0 0 # 周日 未打卡
(integer) 0
127.0.0.1:6379> setbit sign 1 1 # 周一 已打卡
(integer) 0
127.0.0.1:6379> setbit sign 2 1 # 周二 已打卡
(integer) 0
127.0.0.1:6379> setbit sign 3 1 # 周三 已打卡
(integer) 0
127.0.0.1:6379> setbit sign 4 1 # 周四 已打卡
(integer) 0
127.0.0.1:6379> setbit sign 5 1 # 周五 已打卡
(integer) 0
127.0.0.1:6379> setbit sign 6 0 # 周六 未打卡
(integer) 0
127.0.0.1:6379> getbit sign 1   # 获取周一打卡状态,已打卡
(integer) 1
127.0.0.1:6379> bitcount sign   # 统计一周打卡天数
(integer) 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值