Redis三种特殊数据类型——geospatial、Hyperloglog、Bitmaps

Redis三种特殊数据类型——geospatial

关于地理位置相关的,例如:

  • 好友定位,附近的人,打车距离计算等。

查询经纬度网站:http://www.jsons.cn/lngcodeinfo/

相关命令

增:geoadd

# GEOADD key longitude latitude member [longitude latitude member ...]
# 地球两极无法直接添加,我们一般会下载城市数据,直接通过程序一次性导入
# 有效的经度从-180°到180°
# 有效的纬度从-85.05112878°到85.05112878°
# 在redis中,如果经纬度超出上述范围,则会报错
127.0.0.1:6379> GEOADD China:city 116.40 39.90 beijing 121.47 31.23 shanghai 106.50 29.53 chongqing 114.05 22.54 shenzhen
(integer) 4
127.0.0.1:6379> GEOADD China:city 120.16 30.28 hangzhou 108.96 34.26 xian
(integer) 2

查:

GEOPOS:获取指定元素的经纬度

127.0.0.1:6379> GEOPOS China:city beijing
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"

127.0.0.1:6379> GEOPOS China:city beijing chongqing
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "106.49999767541885376"
   2) "29.52999957900659211"

GEODIST:查询两个经纬度之间的距离

127.0.0.1:6379> GEODIST China:city beijing shanghai
"1067378.7564"
# 如果有一个元素的地理位置不存在,则返回nil
127.0.0.1:6379> GEODIST China:city beijing shang
(nil)
127.0.0.1:6379> GEODIST China:city beijing shanghai km
"1067.3788"

单位:

  • mi:英里
  • ft:英尺

不加参数默认为米(m)

应用场景:

  • 附近的人

    获得所有附近的人的定位,通过半径来进行查询

# GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST k

127.0.0.1:6379> GEORADIUS China:city 108 35 1000 km
1) "xian"
2) "chongqing"
3) "beijing"
127.0.0.1:6379> GEORADIUS China:city 108 35 800 km
1) "xian"
2) "chongqing"

127.0.0.1:6379> GEORADIUS China:city 108 35 800 km withcoord	# 查出对应元素具体的经纬度的值
1) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
2) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
      
127.0.0.1:6379> GEORADIUS China:city 108 35 800 km withcoord count 3 # 限制查询数量
1) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
2) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
      
127.0.0.1:6379> GEORADIUS China:city 108 35 800 km withcoord count 1 # 类似于MySQL的limit
1) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"

GEORADIUSBYMEMBER

127.0.0.1:6379> GEORADIUSBYMEMBER China:city beijing 1000 km
1) "beijing"
2) "xian"

GEO底层的实现原理:就是zset(有序集合),插入每个元素的时候,标一个序号,所以我们可以用zset命令来操作geo。

127.0.0.1:6379> ZRANGE China:city 0 -1
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> ZREM China:city beijing xian
(integer) 2
127.0.0.1:6379> ZRANGE China:city 0 -1
1) "chongqing"
2) "shenzhen"
3) "hangzhou"
4) "shanghai"

redis三种特殊类型——Hyperloglog

什么是基数?

基数:一个数据集中不重复的元素。

A: {1, 3, 5, 7, 9, 7}

B: {1, 3, 5, 7, 9}

基数(不重复的元素)=5,可以接受误差

Hyperloglog简介

Redis tribution 2.8.9版本就更新了Hyperloglog数据结构。

Redis Hyperloglog 是基数统计的算法。

场景:

统计网页的UV(即Unique Visitor,不重复访客,访问量,一个人访问某个网站多次,但是还是只计算为一次)。

  • 传统方式

    • 使用set来保存用户的id,然后就可以统计set中元素数量作为标准来判断(在高并发的场景可能会有误差)。如果网站访问量大,用户id比较长,而且用户比较多,那么就增加网络资源的消耗,且会降低查询效率。
    • 我们的目的是为了计数,而不是保存用户id
  • Hyperloglog

    • 占用内存是固定的,2^64不同元素的基数,只需要12kb内存。
    • 官方说法,使用该方法的错误率是0.81%,对于统计UV任务来说,可以忽略不计。

因此,从内存角度来比较的话,Hyperloglog就是首选。

127.0.0.1:6379> PFADD mykey a b c d e f g
(integer) 1
127.0.0.1:6379> PFCOUNT mykey
(integer) 7

# ===========
# PFMERGE destkey sourcekey [sourcekey ...]
# 从源(sourcekey)key合并数据到目标(destkey)key中
127.0.0.1:6379> PFMERGE mykey2 mykey
OK
127.0.0.1:6379> PFCOUNT mykey2
(integer) 12
127.0.0.1:6379> PFCOUNT mykey
(integer) 7
# 可以看到,destkey可以是已存在的key,也可以是不存在的key,最后把合并的结果保存到destkey中
127.0.0.1:6379> PFMERGE mykey3 mykey2 mykey
OK

总结:

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

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

Redis三种特殊数据类型——Bitmaps

位存储

场景

  • 统计用户信息,活跃,不活跃

  • 登录,未登录

  • 打卡,未打卡

    传统做法:设计一个数据库表,包含以下字段user_id, status, day,最后按年或者按月统计。

总结:只要是只有两个状态的(0,1),都可以使用Bitmaps

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

365天的打卡记录,只需要存365个0或1,一个0或1的大小是1bit,8bit=1bytes,总共只需46个字节左右。

记录7天的打卡记录,0:未打卡,1:已打卡

127.0.0.1:6379> SETBIT status 0 1
(integer) 0
127.0.0.1:6379> SETBIT status 1 1
(integer) 0
127.0.0.1:6379> SETBIT status 2 0
(integer) 0
127.0.0.1:6379> SETBIT status 3 1
(integer) 0
127.0.0.1:6379> SETBIT status 4 0
(integer) 0
127.0.0.1:6379> SETBIT status 5 1
(integer) 0
127.0.0.1:6379> SETBIT status 6 1
(integer) 0

查看某一天的打卡记录

127.0.0.1:6379> GETBIT status 1
(integer) 1
127.0.0.1:6379> GETBIT status 2
(integer) 0

统计操作(7天的已打卡记录):

127.0.0.1:6379> bitcount status
(integer) 5
# BITCOUNT key [start end]
# start:设置位索引起始位置(包含该位置计数),第一个位置以0开始,start参数需和end参数同时设置才合法。
# end:	设置位索引结束位置(包含该位置计数),end参数需和start参数同时设置才合法。

注意:BITCOUNT 的 start 和 end 参数的索引意义是以 1 byte 作为单位,如 bitcount mykey 0 0 命令表示 mykey 的字符串的第一个字节中比特位 1 的个数(即字符串第一个字符的比特位为 1 的个数)。

设置了day 1到day 24的打卡状态,day 3, 5, 9, 13, 14为0,其他为1

127.0.0.1:6379> BITCOUNT status 0 0
(integer) 5
127.0.0.1:6379> BITCOUNT status 0 1
(integer) 10
127.0.0.1:6379> BITCOUNT status 0 2
(integer) 18
127.0.0.1:6379> BITCOUNT status 0 3
(integer) 19
127.0.0.1:6379> BITCOUNT status 1 3
(integer) 14
127.0.0.1:6379> BITCOUNT status 2 3
(integer) 9
127.0.0.1:6379> BITCOUNT status 3 3
(integer) 1
原文地址:https://www.cnblogs.com/liuhuan086/p/13582907.html