Redis三种特殊数据类型

1,823 阅读5分钟

我的原文:www.yuque.com/docs/share/…

官网数据类型的介绍:redis.io/topics/data…

bitmap

官方说明

bitmap 事实上不是数据类型,而是一组 定义在 string 类型上、面向二进制位** **的操作。string 数据类型是二进制安全的,并且它最大可存储 512MB 的值,因此 bitmap 可以存储 2^32 个不同的二进制位

bitmap 最大的优势之一是存储信息时,它经常可以极大的节省空间。例如,一个用户的系统中,使用递增的 id 来表示不同的用户,这时候 bitmap 使用 512MB 内存就可以记录 40 亿用户的一个比特信息(例如,1是男生,0是女生,一个男生的id为19,那么这个 bitmap 的第 19 位就是 1)。

通常 bitmap 的使用例子是:

  • 各种实时分析
  • 存储于对象 id 相关联的、节省空间的、高性能的布尔信息

setbit

向 key 中设置一个 bit

127.0.0.1:6379> setbit mybit 0 1
(integer) 0

127.0.0.1:6379> setbit mybit 10 1
(integer) 0

127.0.0.1:6379> setbit mybit 15 0
(integer) 0

第一个参数是 key 的名称,第二个是 bit 在第几位,第三个是 bit 的值(0或1)

getbit

获取 bitmap 中指定位置的 bit 值,没有设置过值的位默认为0

127.0.0.1:6379> setbit mybit 0 1
(integer) 0

127.0.0.1:6379> setbit mybit 10 1
(integer) 0

127.0.0.1:6379> setbit mybit 15 0
(integer) 0

127.0.0.1:6379> getbit mybit 0
(integer) 1

127.0.0.1:6379> getbit mybit 10
(integer) 1

127.0.0.1:6379> getbit mybit 15
(integer) 0

127.0.0.1:6379> getbit mybit 16     # 没有设置过值的位默认为0
(integer) 0

bitcount

计算 bitmap 中存储的 1 的个数

127.0.0.1:6379> setbit mybit 0 1
(integer) 0

127.0.0.1:6379> setbit mybit 10 1
(integer) 0

127.0.0.1:6379> setbit mybit 15 0
(integer) 0

127.0.0.1:6379> bitcount mybit
(integer) 2

bitpos

找出 bitmap 中指定范围内第一个 0 或 1 的位置

127.0.0.1:6379> setbit mybit 3 0
(integer) 0

127.0.0.1:6379> setbit mybit 5 1
(integer) 0

127.0.0.1:6379> setbit mybit 7 1
(integer) 0

127.0.0.1:6379> bitpos mybit 1 0 -1       # 最后两个参数设置检索范围, 0 -1 表示所有的数
(integer) 5

127.0.0.1:6379> bitpos mybit 0 0 -1
(integer) 0

bitop

对多个 bitmap 进行 and(与)、or(或)、xor(异或)操作,还有针对一个 bitmap 的 not(非) 这里只对 or 操作进行演示

127.0.0.1:6379> setbit mybit1 0 1
(integer) 0

127.0.0.1:6379> setbit mybit1 1 0
(integer) 0

127.0.0.1:6379> setbit mybit2 0 0
(integer) 0

127.0.0.1:6379> setbit mybit2 1 1
(integer) 0

127.0.0.1:6379> bitop or mybit3 mybit1 mybit2
(integer) 1

127.0.0.1:6379> getbit mybit3 0
(integer) 1

127.0.0.1:6379> getbit mybit3 1
(integer) 1

HyperLogLogs

什么是基数

基数是一个集合中不重复的元素,例如 A{1,1,2,3,4,4,5} 这个集合的基数是 5

官方说明

超日志(HyperLogLog)是一种概率数据结构,用于统计唯一的事物(从技术上讲,这是指估计集合的基数)。通常,计算唯一项目需要使用与要计数的项目数成比例的内存量,因为您需要记住您在过去看到的元素,以避免多次计数。但是,有一组算法会以内存换取精度:您最终会得到带有标准误差的估计量,在Redis实现的情况下,该误差小于1%。该算法的神奇之处在于,您不再需要使用与所计数项目数成正比的内存量,而是可以使用固定的内存空间!在最坏的情况下为12k字节,如果您的HyperLogLog(从现在开始将它们称为HLL)的元素很少,则使用内存更少。

Redis中的HLL尽管在技术上是不同的数据结构,但被编码为Redis String,因此您可以调用GET来序列化HLL,然后调用SET来将其反序列化回服务器。

然而您并没有真正将项添加到HLL中,因为它的数据结构只存储不含实际元素的状态

使用场景 一个人访问一个网站多次,但是还是算作一个人

**传统方式:**使用 set 来存储访问的人的 id,但是这样 set 集合中会存储大量的用户 id,我们的目的是计数,不是存储 id。

**现在解决方案:**使用 hyperloglog 数据类型,因为它不是真正的添加元素到 HLL 中,占用内存很小

pfadd

把一个或多个值添加到数据类型为 hyperLogLogs 的 key 中

127.0.0.1:6379> pfadd hyper a b c d
(integer) 1

pfcount

计算一个或多个key中存储的元素的个数

127.0.0.1:6379> pfadd hyper a b c d
(integer) 1

127.0.0.1:6379> pfadd info d g h
(integer) 1

127.0.0.1:6379> pfcount hyper info
(integer) 6

127.0.0.1:6379> pfcount hyper
(integer) 4

pfmerge

合并多个 key 中的数据到一个 key

127.0.0.1:6379> pfadd hyper a b c d
(integer) 1

127.0.0.1:6379> pfadd info d g h
(integer) 1

127.0.0.1:6379> pfmerge test hyper info
OK

127.0.0.1:6379> pfcount test
(integer) 6

geospatial

官方说明

这个数据类型可以存储地球上地理位置的经纬度信息,能够通过经纬度信息计算出两地之间的距离,能够通过坐标和半径的方式找出范围内的其他地理位置

如果你的程序需要使用 附近的人 的功能,使用 geospatial 数据类型就能做到。

geoadd

添加一个或多个带有经纬度的地理位置

# 格式:geoadd key 经度 维度 地点名称  [经度 维度 地点名称 ...]

127.0.0.1:6379> geoadd geo 120.21201 30.2084 hangzhou 121.48941 31.40527 shanghai  
(integer) 2																								

geodist

返回两地之间的距离

127.0.0.1:6379> geoadd geo 120.21201 30.2084 hangzhou 121.48941 31.40527 shanghai  
(integer) 2	                                              

127.0.0.1:6379> geodist geo hangzhou shanghai km   # 最后一个参数指定单位
"180.5896"

image.png

geohash

获取一个或多个地点的 geohash 值,这个 geohash 其实就是地点的经纬度信息经过编码形成的,每个字符串代表唯一的坐标

127.0.0.1:6379> geoadd geo 120.21201 30.2084 hangzhou 121.48941 31.40527 shanghai  
(integer) 2	  

127.0.0.1:6379> geohash geo hangzhou shanghai
1) "wtm7z7r8wv0"
2) "wtw6st1uuq0"

geopos

返回一个或多个地理位置的经纬度坐标

127.0.0.1:6379> geoadd geo 120.21201 30.2084 hangzhou 121.48941 31.40527 shanghai  
(integer) 2	  

127.0.0.1:6379> geopos geo hangzhou shanghai
1) 1) "120.21200805902481079"
   2) "30.20839995425554747"
2) 1) "121.48941010236740112"
   2) "31.40526993848380499"

georadius

给定一个坐标作为圆心,给定一个距离作为半径,扫描这个圆范围内的地点(前提是redis中存在)

127.0.0.1:6379> geoadd geo 120.21201 30.2084 hangzhou 121.48941 31.40527 shanghai  
(integer) 2	 

127.0.0.1:6379> geoadd geo 113.27324 23.15792 guangzhou 91.13775 29.65262 xizang  
(integer) 2	

# 格式:georadius key 经度 维度 半径 单位 [可选项,见官网]
127.0.0.1:6379> georadius geo 120.21201 30.2084 200 km  # 以杭州为中心200km为半径扫描
1) "hangzhou"
2) "shanghai"

127.0.0.1:6379> georadius geo 120.21201 30.2084 5000 km  # 杭州为中心,5000km为半径扫描
1) "xizang"
2) "guangzhou"
3) "hangzhou"
4) "shanghai"

georadiusbymember

这个命令和 georadius 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是像 georadius 那样, 需要输入的经度和纬度来决定中心点。

127.0.0.1:6379> geoadd geo 120.21201 30.2084 hangzhou 121.48941 31.40527 shanghai  
(integer) 2	 

127.0.0.1:6379> geoadd geo 113.27324 23.15792 guangzhou 91.13775 29.65262 xizang  
(integer) 2	

127.0.0.1:6379> georadiusbymember geo hangzhou 200 km
1) "hangzhou"
2) "shanghai"