2.Redis系列之特殊数据类型

1. bitmaps与bitfields

Redis中提供了bitmaps实现对位的操作,应用在统计月活跃用户数【活跃用户量千万级别】时比set能够明显的提高内存使用率

我们可以把bitmaps想象为一个以位为单位的数组,数组每个单元智能存储0和1,数字的下标在bitmaps中称为偏移量offset

1.1 bitmaps基本操作及底层数据结构

# setbit <key> <offset> <value>设置键指定偏移量的值
127.0.0.1:6379> setbit user 0 1
(integer) 0
127.0.0.1:6379> setbit user 1 1
(integer) 0
127.0.0.1:6379> setbit user 2 0
(integer) 0
127.0.0.1:6379> setbit user 3 1
(integer) 0
# getbit <key> <offset>获取键指定便宜量的值
127.0.0.1:6379> getbit user 0
(integer) 1
# bitcount <key> [start end]统计指定范围内比特值为1的数量
127.0.0.1:6379> bitcount user 0 -1
(integer) 3
127.0.0.1:6379> setbit user_day2 0 0
(integer) 0
127.0.0.1:6379> setbit user_day2 1 1
(integer) 0
127.0.0.1:6379> setbit user_day2 2 1
(integer) 0
127.0.0.1:6379> setbit user_day2 3 0
(integer) 0
# bitop and/or <destkey> key [key...]返回多个bitmaps的交集/并集到目标key中
127.0.0.1:6379> bitop and user_day1_2 user user_day2
(integer) 1
## 比如该例子返回两天都访问的用户数
127.0.0.1:6379> bitcount user_day1_2
(integer) 1
127.0.0.1:6379> bitop or all_day1_2 user user_day2
(integer) 1
## 比如该例子返回两天总共访问的用户数
127.0.0.1:6379> bitcount all_day1_2
(integer) 4
# 可以看到内部编码为字符串的编码方式raw
127.0.0.1:6379> object encoding user
"raw"

1.2 bitfields基本操作及底层数据结构

对于我们想自定义存储位数,可以采用bitfield

# bitfield key set/get encoding offset value
# bitfield存储32位偏移量为0的值为8888
127.0.0.1:6379> bitfield user set u32 0 8888
1) (integer) 3489660928
# bitfield获取32位偏移量为0的值
127.0.0.1:6379> bitfield user get u32 0
1) (integer) 8888
#  bitfield为32位偏移量为0的值增加1000
127.0.0.1:6379> bitfield user incrby u32 0 1000
1) (integer) 9888
# 可以看到内部编码为字符串的编码方式raw
127.0.0.1:6379> object encoding user
"raw"

2. HyperLogLog

我们讲解Redis中基数统计利器HyperLogLog[简称HLL]基本操作及原理

对于海量级别UV(独立访客)、独立IP数等需要去重计数问题如何解决?对于求集合中不重复元素个数的问题称为基数问题

2.1 基本操作

# pfadd添加元素至HLL
127.0.0.1:6379> pfadd user 1 2 3
(integer) 3
# 再次添加重复元素返回0,不成功
127.0.0.1:6379> pfadd user 2
(integer) 0
# pfcount计算HLL的近似基数
127.0.0.1:6379> pfcount user
(integer) 3
127.0.0.1:6379> pfadd user2 2 4
(integer) 2
# pfmerge合并两个或多个HLL至新的HLL
127.0.0.1:6379> pfmerge all_user user user2
OK
127.0.0.1:6379> pfcount all_user
(integer) 4

2.2 底层原理

# 内部编码同样为raw
127.0.0.1:6379> object encoding all_user
"raw"

为了解决基数问题,我们可以通过数据库distinct或者用redis中我们之前说到的hash \set\bitmaps来处理,对于bitmaps最为节省:一个1G的空间,有 8102410241024=8.5810^9bit, 也就是可以表示85亿个不同的数,但是当数据量为2^64bit=2048PB,这已经不是硬件可以解决的问题了,所以HLL就派上了用场

每个HyperLogLog键只需要占用12KB内存,就可以计算接近2^64个不同元素的基数。
因为HyperLogLog只会根据输入元素来近似计算基数,而不会储存输入元素本身,所以 HyperLogLog不返回输入的各个元素

HyperLogLog可类比伯努利试验,HyperLogLog设置为:m=16834[分桶对应实验轮数],p=6[每个桶占用bit位存储存储k_max最大抛掷次数],L[总长度]=16834 * 6。占用内存为=16834 * 6 / 8 / 1024 = 12K
具体参考https://juejin.cn/post/6844903785744056333#heading-4

3. GeoSpatial

我们讲解redis中对经纬度操作支持的数据类型GeoSpatial

3.1 geoadd经纬度添加

我们打开https://lbs.amap.com/tools/picker进行坐标拾取,分别拾取静安区
、黄浦区、杨浦区、浦东新区坐标点

127.0.0.1:6379> geoadd region 121.447348 31.227718 jingan
(integer) 1
127.0.0.1:6379> geoadd region 121.48442 31.231661 huangpu
(integer) 1
127.0.0.1:6379> geoadd region 121.525409 31.259588 yangpu
(integer) 1
127.0.0.1:6379> geoadd region 121.544346 31.221461 pudong
(integer) 1

3.2 geodist求两点之间距离

# 计算静安与黄浦直线距离
127.0.0.1:6379> geodist region jingan huangpu
"3553.2114"

3.3 geohash编码

GeoHash就是一种将经纬度转换成字符串的方法,字符串前缀匹配越多的距离越近

3

127.0.0.1:6379> geohash region jingan huangpu
1) "wtw3esg68k0"
2) "wtw3smw3850"

3.4 geopos返回坐标点

127.0.0.1:6379> geopos region jingan
1) 1) "121.44734770059585571"
   2) "31.22771779071442921"

3.5 返回圆形内所有点

# 自从6.2.0开始,采用geosearch
# 通过坐标点名搜索周边4公里点
127.0.0.1:6379> geosearch region frommember jingan BYRADIUS 4 KM
1) "jingan"
2) "huangpu"
# 通过具体坐标点搜索周边4公里点
127.0.0.1:6379> geosearch region fromlonlat 121.447348 31.227718 BYRADIUS 4 KM
1) "jingan"
2) "huangpu"
# 返回额外距离、经纬度信息
127.0.0.1:6379> geosearch region fromlonlat 121.447348 31.227718 BYRADIUS 4 KM withdist withcoord
1) 1) "jingan"
   2) "0.0000"
   3) 1) "121.44734770059585571"
      2) "31.22771779071442921"
2) 1) "huangpu"
   2) "3.5532"
   3) 1) "121.48442119359970093"
      2) "31.23166181683836129"

3.6 返回矩形内点

# 以静安为矩形坐标中心点,查找宽高各为8KM的矩形内点
127.0.0.1:6379> geosearch region fromlonlat 121.447348 31.227718 bybox 8 8 KM
1) "jingan"
2) "huangpu"

3.7 存储搜索结果到新key

127.0.0.1:6379> geosearchstore result region fromlonlat 121.447348 31.227718 bybox 8 8 KM
(integer) 2
127.0.0.1:6379> zrange result 0 -1
1) "jingan"
2) "huangpu"

一般在工作中,用ES坐标点geo_point及形状geo_shape[支持多边形围栏搜索]比较多些,但也要看实际工作需求了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

算法小生Đ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值