redis开发与运维-redis03-redis其他数据类型与命令(Bitmaps++HyperLogLog+GEO)
文章目录
- 【README】
- 【1】Bitmaps
- 【1.1】命令
- 【2】HyperLoglog
- 【2.1】命令
- 【2.2】HyperLogLog优缺点
- 【3】GEO-地理信息定位(仅了解)
- 【3.1】命令
- 【4】使用redis实现发布订阅
- 【4.1】命令
- 【4.2】基于redis的发布订阅模式的使用场景
【README】
本文总结自《redis开发与运维》,作者付磊,张益军,墙裂推荐;
- 本文使用的redis版本是 7.0.15 ;
- 本文主要介绍redis其他数据类型,包括 Bitmaps ,HyperLogLog,GEO,以及基于redis实现发布订阅模式;
【1】Bitmaps
1)Bitmaps定义:Bitmaps不是一种数据结构,它就是字符串,只不过可以对字符串的位(单个bit)进行操作;
- 简单理解: Bitmaps是一个以位为单位的数组,数组的每个单元只能存储0和1, 数组的下标在 Bitmaps中叫做偏移量offset(偏移量从0开始计数);
【1.1】命令
业务场景: 使用Bitmaps记录用户访问chatgpt的状态,用户有访问记为1,否则记为0;
1)setbit key offset value 设置key在偏移量offset上的值
业务场景:用户id=0,2,5的用户访问过chatgpt;
# setbit key offset value 设置key在0号偏移量offset上的值
192.168.163.211:6379> setbit access_his 0 1
(integer) 0
# setbit key offset value 设置key在2号偏移量offset上的值
192.168.163.211:6379> setbit access_his 2 1
(integer) 0
# setbit key offset value 设置key在5号偏移量offset上的值
192.168.163.211:6379> setbit access_his 5 1
(integer) 0
# getbit key offset 获取值
192.168.163.211:6379> getbit access_his 1
(integer) 0
192.168.163.211:6379> getbit access_his 0
(integer) 1
192.168.163.211:6379> getbit access_his 2
(integer) 1
【注意1】如果此时有userid=50的用户访问了chatgpt,那么Bitmaps第6号到第49号偏移量上的值为0,第50号偏移量上的值为1;
- 如果用户id以10000开头,则会导致Bitmaps的内存浪费,因为第0号到第9999号偏移量上的值为0;
- 通常做法是使用用户id减去某个指定数字;
【注意2】第1次初始化Bitmaps时, 若偏移量特别大,整个初始化过程会非常慢,可能阻塞redis;
2)getbit key offset 获取值
# getbit key offset 获取值
192.168.163.211:6379> getbit access_his 2
(integer) 1
# 若offset不存在,返回结果也是0
192.168.163.211:6379> getbit access_his 100000
(integer) 0
3)bitcount key [start end] 获取指定范围值为1的bit个数
其中 start,end表示开始与结束字节数; 其中start,end从0计数,1字节=8bit
# access_his 第0,2,5号offset上的值为1,其余为0
# 获取第0个字节到第10个字节上的值为1的bit个数
192.168.163.211:6379> bitcount access_his 0 10
(integer) 3
# 获取第1个字节到第10个字节上的值为1的bit个数 (因为第0,2,5号bit在第0个字节)
192.168.163.211:6379> bitcount access_his 1 10
(integer) 0
4)bitop op result_key key [key…] Bitmaps间的运算
bitop是一个复合操作,可以做多个Bitmaps的and交集, or并集, not非,xor异或运算,并把结果保存到result_key;
192.168.163.211:6379> setbit baidu_access 0 1
(integer) 0
192.168.163.211:6379> setbit baidu_access 2 1
(integer) 0
192.168.163.211:6379> setbit baidu_access 6 1
(integer) 0
192.168.163.211:6379> setbit chatgpt_access 0 1
(integer) 0
192.168.163.211:6379> setbit chatgpt_access 2 1
(integer) 0
192.168.163.211:6379> setbit chatgpt_access 3 1
(integer) 0
# bitop op result_key key [key...] Bitmaps间的运算
# and交集运算, 其中 baidu_access第0,2,6号bit为1, chatgpt_access第0,2,3号bit为1
192.168.163.211:6379> bitop and result_key1 baidu_access chatgpt_access
(integer) 1
192.168.163.211:6379> bitcount result_key1 0 10
(integer) 2
5)bitpos key targetBit [start] [end] 计算Bitmaps中第1个值为targetBit的偏移量
其中 start,end表示开始与结束字节数;
192.168.163.211:6379> setbit history 3 1
(integer) 0
# bitpos key targetBit [start] [end] 计算Bitmaps中第1个值为targetBit的偏移量
# 计算第0个字节到第1个字节范围内,第1个值为1的bit偏移量
192.168.163.211:6379> bitpos history 1 0 1
(integer) 3
【2】HyperLoglog
1)HyperLogLog定义:它是一种基数算法,可以利用极小内存空间完成数量统计;
- 数据可以是 ip,email,id等;
2)HyperLogLog提供了3个命令: pfadd, pfcount, pfmerge ;
3)HyperLogLog: 是由 Philippe Flajolet提出的,本文推测 命令以pf作为前缀是取了作者名字的首字母 ;
【2.1】命令
1)pfadd key element [element…] 向HyperLogLog添加元素
# pfadd key element [element...] 向HyperLogLog添加元素
192.168.163.211:6379> pfadd ids cd01 cd02 cd03 #新增id,包括 cd01, cd02, cd03
(integer) 1
192.168.163.211:6379> pfadd ids cd02 cd03 cd05 cd06 #新增id,包括 cd02, cd03, cd05, cd06
(integer) 1
# pfcount 计算独立用户数(去重)
192.168.163.211:6379> pfcount ids
(integer) 5
2)pfcount key [key …] 计算独立用户数(去重)
3)pfmerge destKey sourceKey [key…] 合并多个key的元素
192.168.163.211:6379> pfadd user0305 a b c d
(integer) 1
192.168.163.211:6379> pfadd user0306 c d e f
(integer) 1
# pfmerge destKey sourceKey [key...] 合并多个key的元素,合并结果保存到destKey
192.168.163.211:6379> pfmerge result_key user0305 user0306
OK
192.168.163.211:6379> pfcount result_key
(integer) 6
【2.2】HyperLogLog优缺点
1)优缺点:
- 优点: 内存占用非常小;
- 缺点: 存在统计错误率;
2)开发者在选择HyperLogLog数据类型时需要确认如下两条:
- 只为了计算独立总数,不需要获取单条数据;
- 可以容忍一定误差率;
【3】GEO-地理信息定位(仅了解)
1)GEO地理信息定位数据类型:存储地理位置信息;
【3.1】命令
【业务场景】保存中国一二线城市的经纬度,并计算它们之间的距离 ;
1)geoadd key longitude latitude member [longitude latitude member…] 增加地理位置信息
其中 longitude,latitude是经纬度,member是成员;
# geoadd key longitude latitude member [longitude latitude member...] 增加地理位置信息
# 新增beijing经纬度信息到cities键
192.168.163.211:6379> geoadd cities 116.28 39.55 beijing
(integer) 1
192.168.163.211:6379> geoadd cities 117.12 39.08 tianjin
(integer) 1
2)geopos key member [member] 获取地理位置信息
# geopos key member [member] 获取地理位置信息
# geopos cities beijing 获取北京地理位置信息
192.168.163.211:6379> geopos cities beijing
1) 1) "116.28000229597091675"
2) "39.5500007245470826"
3)geodist key member1 member2 [unit] 获取两个地址位置的距离
其中unit是单位,如下:
- m:米;
- km:公里;
- mi:英里;
- ft:尺;
192.168.163.211:6379> geoadd cities 116.28 39.55 beijing
(integer) 1
192.168.163.211:6379> geoadd cities 117.12 39.08 tianjin
(integer) 1
# 计算北京到天津的距离,单位km
192.168.163.211:6379> geodist cities beijing tianjin km
"89.2061"
4)zrem key member 删除地理位置信息
因为GEO的数据类型为zset,所以使用zrem删除地理位置信息;
192.168.163.211:6379> type cities
zset
# zrem key member 删除地理位置信息
192.168.163.211:6379> zrem cities tianjin
(integer) 1
192.168.163.211:6379> geopos cities tianjin
1) (nil)
【4】使用redis实现发布订阅
1)发布订阅模式: 发布者向指定频道发布消息, 订阅该频道的每个客户端都可以接收消息;
【4.1】命令
1)publish channel message 发布消息
192.168.163.211:6379> publish channel01 'hello world'
(integer) 0
# publish channel message 发布消息
192.168.163.211:6379> publish channel01 'hello world 01'
(integer) 1
192.168.163.211:6379> publish channel01 'hello world 02'
(integer) 1
2)subscribe channel [channel] 订阅消息
# subscribe channel [channel] 订阅消息
192.168.163.211:6379> subscribe channel01
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel01"
3) (integer) 1
#接收到消息1
1) "message"
2) "channel01"
3) "hello world 01"
#接收到消息2
1) "message"
2) "channel01"
3) "hello world 02"
注意:因为redis不持久化消息,所以新开启的订阅客户端,无法接收到订阅前的消息;
3)unsubscribe [channel] [channel…] 取消订阅
192.168.163.211:6379> unsubscribe channel01
1) "unsubscribe"
2) "channel01"
3) (integer) 0
4)按照模式订阅和取消订阅
- psubscribe pattern [pattern…]
- punsubscribe pattern [pattern…]
- pattern指的是通配符模式;
5)查询订阅:
# pubsub channels [pattern] 查看活跃的频道
192.168.163.211:6379> pubsub channels
1) "channel01"
2) "channel02"
# pubsub numsub [channel] 查看频道订阅数
192.168.163.211:6379> pubsub numsub channel02 channel01
1) "channel02"
2) (integer) 2
3) "channel01"
4) (integer) 1
# pubsub numpat 查看模式订阅数
192.168.163.211:6379> pubsub numpat
(integer) 0
【4.2】基于redis的发布订阅模式的使用场景
1)使用场景:聊天室, 公告牌,服务之间利用消息解耦都可以使用发布订阅模式;
2)发布订阅模式: 用于视频信息变化通知;