Redis基础知识(学习笔记13--BitMap、HyperLogLog 与 Geospatial的操作命令)
一. BitMap操作命令
1.1 BitMap 简介
BitMap 是Redis 2.2.0 版本中引入的一种新的数据类型。该数据类型本质上就是一个仅包含0和1的二进制字符串。而其所有相关命令都是对这个字符串二进制位的操作。用于描述该字符串的属性有三个:key、offset、bitvalue。
*** key:BitMap是Redis的key-value中的一种Value的数据类型,所以该Value一定有其对应的Key。
*** offset:每个BitMap数据都是一个字符串,字符串中的每个字符都有其对应的索引,该索引从0开始计数。该索引就称为每个字符在该BitMap中的偏移量offset。这个offset的值的范围是【0,2^32 -1】,即该offset的最大值为4G-1,即4294967295,42亿多。
*** bitBalue:每个BitMap数据中都是一个仅包含0和1的二进制字符串,每个offset位上的字符就称为该位的值bitValue。bitValue的值非0即1。
1.2 setbit
setbit key offset value
为给定key的bitmap数据的offset位置设置值为value。其返回值为修改前该offset位置的bitvalue。
说明:对于原bitmap字符串中不存在的offset进行赋值,字符串会自动伸展以确保它可以将value保存在指定的offset上。当字符串值进行伸展时,空白位置以0填充。当然,设置的value只能是0或1。不过需要注意的是,对使用较大offset的setbit操作来说,内存分配过程可能造成Redis服务器被阻塞。
1.3 getbit
GETBIT key offset
对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
说明:返回值为字符串值指定偏移量上的位(bit)。当 offset 比字符串值的长度大,或者 key 不存在时,返回 0 。
1.4 bitcount
BITCOUNT key [start] [end]
计算给定字符串中,被设置为 1 的比特位的数量。
说明:一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start 和 end 参数的设置和 GETRANGE 命令类似,都可以使用负数值: 比如 -1 表示最后一个字节, -2 表示倒数第二个字节,以此类推。不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。
1.5.bitpos
bitpos key bit [start] [end]
返回key指定的bitmap中第一个值为指定值bit(非0即1)二进制的位置。pos,即position,位置。在默认情况下,命令将检测整个bitmap,但用户也可以通过可选的start参数和end参数指定要检测的范围。
说明:start与end的意义与bitcount命令中的相同。
1.6 bitop
bitop operation destkey key [key...]
对一个或多个bitmap字符串key进行二进制位操作,并将结果保存到destkey上。operation可以是 and、or、not、xor这四种操作中的任意一种:
*** bitop and destkey key [key...]:对一个或多个bitmap 执行 按位与 操作,并将结果保存到destkey。
*** bitop or destkey key [key...]:对一个或多个bitmap 执行 按位或 操作,并将结果保存到destkey。
*** bitop xor destkey key [key...]:对一个或多个bitmap 执行 按位异或 操作,并将结果保存到destkey。
*** bitop and destkey key [key...]:对一个或多个bitmap 执行 按位非 操作,并将结果保存到destkey。
说明:
*** 除了not操作之外,其他操作都可以接受一个或多个bitmap作为输入。
*** 除了not操作之外,其他对一个bitmap的操作其实就是一个复制。
*** 如果参与运算的多个bitmap长度不同,较短的bitmap会以0作为补充位,和输入 key 中最长的字符串长度相等。
1.7 应用场景
由于offset的取值范围很大,所以其一般应用于大数据量的二值性统计。例如平台活跃用户的统计(二值:访问或未访问)、支持率统计(二值:支持或不支持)、员工考勤统计(二值:上班或未上班)、图像二值化(二值:黑或白)等。
不过,对于数据量较小的二值性统计并不适合BitMap,可能使用Set更为合适。当然,具体多少数据量适合用于Set,超过多少数据量适合用于BitMap,这需要根据具体场景进行具体分析。
例如,一个平台要统计日活跃用户数量。如果使用Set来统计,只需上线一个用户,就将其用户ID写入Set集合即可,最后只需统计出Set集合中的元素个数即可完成统计。即Set集合占用内存的大小与上线用户数量成正比。假设用户ID为m位bit位,当前活跃用户数量为n,则该Set集合的大小最少应该是m*n字节。而如果使用BitMap来统计,则需要先定义出一个BitMap,其占用的bit位至少为注册用户数量。只需上线一个用户,就立即使其中一个bit位置为1,最后只需统计出BitMap中1的个数即可完成统计。即BitMap占用内存的大小与注册用户数量成正比,与上线用户数量无关。假设平台具有注册用户数量为N,则BitMap的长度至少为N个bit位,即N/8字符。何时使用BitMap更合适?可以看各自内存的大小,那个占用的内存少,推荐使用那个。
二. HyperLogLog 操作命令
2.1 HyperLogLog 简介
HyperLogLog 是Redis 2.8.9 版本中引入的一种新的数据类型,其意义是HyperLog Log,超级日志记录。该数据类型可以简单理解为一个set集合,集合元素为字符串。但实际上HyperLogLog是一种计数概率算法,通过该算法可以利用极小的内存完成独立总数的统计。其所有相关命令都是对这个“set集合”的操作。
2.2 pfadd
PFADD key element [element ...]
将任意数量的元素添加到指定的 HyperLogLog 里面。如果 HyperLogLog 的内部储存被修改了, 那么返回 1 , 否则返回 0 。
说明:作为这个命令的副作用, HyperLogLog 内部可能会被更新, 以便反映一个不同的唯一元素估计数量(也即是集合的基数)。如果 HyperLogLog 估计的近似基数(approximated cardinality)在命令执行之后出现了变化, 那么命令返回 1 , 否则返回 0 。 如果命令执行时给定的键不存在, 那么程序将先创建一个空的 HyperLogLog 结构, 然后再执行命令。调用 PFADD 命令时可以只给定键名而不给定元素:(1)如果给定键已经是一个 HyperLogLog , 那么这种调用不会产生任何效果;(2)但如果给定的键不存在, 那么命令会创建一个空的 HyperLogLog , 并向客户端返回 1 。
2.3 pfcount
PFCOUNT key [key ...]
当 PFCOUNT 命令作用于单个键时, 返回储存在给定键的 HyperLogLog 的近似基数, 如果键不存在, 那么返回 0 。
说明:当 PFCOUNT 命令作用于多个键时, 返回所有给定 HyperLogLog 的并集的近似基数, 这个近似基数是通过将所有给定 HyperLogLog 合并至一个临时 HyperLogLog 来计算得出的。通过 HyperLogLog 数据结构, 用户可以使用少量固定大小的内存, 来储存集合中的唯一元素 (每个 HyperLogLog 只需使用 12k 字节内存,以及几个字节的内存来储存键本身)。命令返回的可见集合(observed set)基数并不是精确值, 而是一个带有 0.81% 标准错误(standard error)的近似值。举个例子, 为了记录一天会执行多少次各不相同的搜索查询, 一个程序可以在每次执行搜索查询时调用一次 PFADD , 并通过调用 PFCOUNT 命令来获取这个记录的近似结果。
2.4 pfmerge
PFMERGE destkey sourcekey [sourcekey ...]
将多个 HyperLogLog 合并(merge)为一个 HyperLogLog , 合并后的 HyperLogLog 的基数接近于所有输入 HyperLogLog 的可见集合(observed set)的并集。字符串回复:返回 OK 。
说明:合并得出的 HyperLogLog 会被储存在 destkey 键里面, 如果该键并不存在, 那么命令在执行之前, 会先为该键创建一个空的 HyperLogLog 。
2.5 应用场景
HyperLogLog 可对数据量超级庞大的日志数据做不精确的去重计数统计。当然。这个不精确的度在Redis官方给出的误差是0.81%。这个误差对于大多数超大数据量场景是被允许的。对于平台上每个页面每天的UV数据,非常适合使用HyperLogLog进行记录。
三. Geospatial操作命令
3.1 Geospatial 简介
Geospatial,地理空间
Redis在3.2版本中引入了Geospatial这种新的数据类型。该类型本质上仍是一种集合。只不过集合元素比较特殊,是一种由三部分构成的数据结构,这种数据结构称为空间元素:
*** 经度:longitude。有效经度为【-180,180】.正的表示东经,负的表示西经。
*** 纬度:latitude。有效维度为【-85.05112878,85.05112878】。正的表示北纬,负的表示南纬。
*** 位置名称:为该经纬度所标注的位置所命名的名称,也称为该Geospatial集合的空间元素名称。
通过该类型可以设置、查询某地理位置的经纬度,查询某范围内的空间元素,计算两空间元素间的距离等。
3.2 geoadd
GEOADD key longitude latitude member [longitude latitude member ...]
将给定的空间元素(纬度、经度、名字)添加到指定的键里面。 这些数据会以有序集合的形式被储存在键里面, 从而使得像 GEORADIUS 和 GEORADIUSBYMEMBER 这样的命令可以在之后通过位置查询取得这些元素。返回值:新添加到键里面的空间元素数量, 不包括那些已经存在但是被更新的元素。
说明:GEOADD 命令以标准的 x,y 格式接受参数, 所以用户必须先输入经度, 然后再输入纬度。 GEOADD 能够记录的坐标是有限的: 非常接近两极的区域是无法被索引的。当用户尝试输入一个超出范围的经度或者纬度时, GEOADD 命令将返回一个错误。
3.3 geopos
GEOPOS key member [member ...]
从键里面返回所有给定位置元素的位置(经度和纬度)。
说明:因为 GEOPOS 命令接受可变数量的位置元素作为输入, 所以即使用户只给定了一个位置元素, 命令也会返回数组回复。GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。当给定的位置元素不存在时, 对应的数组项为空值。
3.4 geodist
GEODIST key member1 member2 [unit]
返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在, 那么命令返回空值。
说明:指定单位的参数 unit 必须是以下单位的其中一个:m 表示单位为米;km 表示单位为千米;mi 表示单位为英里;ft 表示单位为英尺。如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。
3.5 geohash
GEOHASH key member [member ...]
返回一个或多个位置元素的 Geohash 表示。
说明:geohash是一种地址编码方法。它能够把二维的空间经纬度数据编码成一个字符串。该值主要用于底层应用或者调试。实际中的作用不大。
3.6 georadius
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
以给定的经纬度为中心, 返回指定地理空间中键包含的所有位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素(换句话说,不超过给定半径的元素)。返回时还可携带额外的信息:
***WITHDIST : 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
*** WITHCOORD : 将位置元素的经度和维度也一并返回。
*** WITHHASH : 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
说明:(1)范围可以使用以下其中一个单位:m 表示单位为米;km 表示单位为千米;mi 表示单位为英里;ft 表示单位为英尺。(2)命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:ASC : 根据中心的位置, 按照从近到远的方式返回位置元素;DESC : 根据中心的位置, 按照从远到近的方式返回位置元素。(3)在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT <count> 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。(4)
GEORADIUS 命令返回一个数组, 具体来说:在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 ["New York","Milan","Paris"] 这样的线性(linear)列表。在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。
在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回:【【以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致;geohash 整数;由两个元素组成的坐标,分别为经度和纬度。】】
3.7 GEORADIUSBYMEMBER
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。
说明,其返回值为一个数组, 数组中的每个项表示一个范围之内的位置元素。
3.8 应用场景
Geospatial 的意义是地理位置,所以其主要应用地理位置相关的计算。例如,微信发送中的“附近”功能,添加好友中“雷达加朋友”功能;QQ动态中的“附近”功能;钉钉中的“签到”功能等。
学习参阅声明
1.【Redis视频从入门到高级】
https://www.bilibili.com/video/BV1U24y1y7jF?p=11&vd_source=0e347fbc6c2b049143afaa5a15abfc1c】
2. 【Redis 命令参考】
https://haiyong.site/doc/redis/redis-gh-pages/hash/hscan.html