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

Redis三种特殊数据类型

Bitmaps

Bitmaps这个数据结构可以实现对位的操作。Bitmaps实际上就是字符串,但是它可以对字符串的位进行操作。

可以把Bitmaps想象成一个以为单位数组,数组中的每个单元只能存0或者1,数组的下标在bitmaps中叫做偏移量。单个bitmaps的最大长度是512MB,即2^32个比特位。

详细可以参考大佬写的

Bitmaps类型的基础操作

  • 获取指定key对应偏移量上的bit值

    getbit key offset

  • 设置指定key对应偏移量上的bit值,value只能是1或0

    setbit key offset value

使用bitmap来记录 周一到周日的打卡!
周一:1 周二:0 周三:0 周四:1.....
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(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 0
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0
# 查看某一天是否有打卡!
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 6
(integer) 0
#统计操作,统计打卡的天数
127.0.0.1:6379> bitcount sign	# 统计这周打卡记录,就可以看见是否全勤
(integer) 3

应用案例

  • 电影网站
    • 统计每天某一部电影是否被点播
    • 统计每天有多少部电影被点播
    • 统计每周/月/年有多少部电影被点播
    • 统计年度哪部电影没有被点播

解决方案

  • 对指定key按位进行交、并、非、异或操作,并将结果保存到destKey中

    bitop op destKey key1 [key2…]

    • and:交
      or:并
      not:非
      xor:异或
  • 统计指定key中1的数量

    bitcount key [start end]

状态的统计
127.0.0.1:6379> setbit 20201229 0 1		# 20201229日这一天 0号电脑 点播过 因此为1
(integer) 0
127.0.0.1:6379> setbit 20201229 4 1
(integer) 0
127.0.0.1:6379> setbit 20201229 8 1
(integer) 0
127.0.0.1:6379> setbit 20201230 0 1
(integer) 0
127.0.0.1:6379> setbit 20201230 5 1
(integer) 0
127.0.0.1:6379> setbit 20201230 8 1
(integer) 0
127.0.0.1:6379> bitcount 20201229
(integer) 3
127.0.0.1:6379> bitcount 20201230
(integer) 3
127.0.0.1:6379> setbit 20201229 6 1	
(integer) 0
127.0.0.1:6379> bitcount 20201229
(integer) 4

127.0.0.1:6379> bitop or 29-30 20201229 20201230	# 合并
(integer) 2
127.0.0.1:6379> bitcount 29-30	# 就可以查看出有多少电影被点播
(integer) 5
  • redis 应用于信息状态统计

Hyperloglog

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

Redis Hyperloglog 基数统计的算法

  • 优点:占用的内存是固定,2^64 不同的元素的基数,只需要费12kb内存 。如果要从内存角度来比较的话 Hyperloglog 就是首选

  • 网页的UV(一个人访问一个网站多次,但是还是算作一个人)

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

基数

  • 基数是数据集去重后元素个数
  • HyperLogLog 是用来做基数统计的,运用了LogLog的算法

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

HyperLogLog类型的基本操作

  • 添加数据

    pfadd key element [element …]

  • 统计数据

    pfcount key [key …]

  • 合并数据

    pfmerge destkey sourcekey [sourcekey…]

127.0.0.1:6379> pfadd mykey a b c d e f g h i j		# 创建第一组元素 mykey
(integer) 1
127.0.0.1:6379> pfcount mykey	# 统计mykey中元素的基数数量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n a m	# 创建第二组元素 mykey2
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 10
127.0.0.1:6379> pfmerge mykey3 mykey mykey2		# 合并两组 mykey mykey2 => mykey3 并集
OK
127.0.0.1:6379> pfcount mykey3	# 查看并集的数量!
(integer) 15

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

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

相关说明

  • 用于进行基数统计,不是集合,不保存数据,只记录数量而不是具体数据
  • 核心是基数估算算法,最终数值存在一定误差
  • 误差范围:基数估计的结果是一个带有 0.81% 标准错误的近似值
  • 耗空间极小,每个hyperloglog key占用了12K的内存用于标记基数
  • pfadd命令不是一次性分配12K内存使用,会随着基数的增加内存逐渐增大
  • Pfmerge命令合并后占用的存储空间为12K,无论合并之前数据量多少

Geospatial

Geospatial 地理位置

朋友的定位,附近的人,打车距离计算,但是计算出来的位置只算水平距离,不算垂直距离

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

GEO类型的基本操作

  • 添加坐标点

    geoadd key longitude latitude member [longitude latitude member …]

  • 获取坐标点

    geopos key member [member …]

  • 计算坐标点距离

    geodist key member1 member2 [unit]

  • 根据坐标点求范围内的数据

    georadius key longitude latitude radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]

  • 根据点求范围内数据

    georadiusbymember key member radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]

  • 获取指定点对应的坐标hash值

    geohash key member [member …]

geoadd 添加地理位置
规则:两极无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入!
参数 key 值(经度,纬度,名称)
有效的经度从-180度到180度
有效的维度从-85.05112878度到85.05112878度

127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqin
(integer) 1
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 114.05 22.52 shengzhen 108.96 34.26 xian
(integer) 3

geopos 获得当前定位:一定是一个坐标值
获取指定城市的经度和纬度

127.0.0.1:6379> geopos china:city beijing chongqin xian shengzhen
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "106.49999767541885376"
   2) "29.52999957900659211"
3) 1) "108.96000176668167114"
   2) "34.25999964418929977"
4) 1) "114.04999762773513794"
   2) "22.5200000879503861"
   
geodist
两人之间的距离
单位:
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。

127.0.0.1:6379> geodist china:city beijing shanghai	# 查看北京到上海的直线距离
"1067378.7564"
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.3788"
127.0.0.1:6379> geodist china:city beijing chongqin km
"1464.0708"
127.0.0.1:6379> geodist china:city beijing xian km
"910.0565"

georadius 以给定的经纬度为中心, 找出某一半径内的元素
我附近的人(获取所有附近的人的地址 定位)通过半径来查询
所有的数据都应该录入:china:city 才会让结果更加清晰

127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km	# 以110 30这个经纬度为中心寻找方圆1000km内的城市
1) "chongqin"
2) "xian"
3) "shengzhen"
4) "hangzhou"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km
1) "chongqin"
2) "xian"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord # 显示他人的定位信息
1) 1) "chongqin"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist	# 显示到中心距离的位置
1) 1) "chongqin"
   2) "341.9374"
2) 1) "xian"
   2) "483.8340"
   
# 筛选出指定的的结果
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 1
1) 1) "chongqin"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 2
1) 1) "chongqin"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) "483.8340"
   3) 1) "108.96000176668167114"
      2) "34.25999964418929977"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 3
1) 1) "chongqin"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) "483.8340"
   3) 1) "108.96000176668167114"
      2) "34.25999964418929977"


GEORADIUSBYMEMBER
找出位于指定元素周围的其他元素

127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 200 km
1) "hangzhou"
2) "shanghai"

GEOHASH 
返回一个或多个位置元素的 Geohash 
将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近

127.0.0.1:6379> geohash china:city beijing chongqin
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

GEO底层的实现原理其实就是Zset 我们可以使用Zset命令来操作geo
zrem移除

127.0.0.1:6379> zrange china:city 0 -1	# 查看地图中全部的元素
1) "chongqin"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"

127.0.0.1:6379> zrem china:city beijing	# 移除指定的元素
(integer) 1
上一篇:基于ipset对大量IP进行封禁(Iptables)


下一篇:中国的数字化转型 China’s digital transformation