Redis中3种特殊的数据类型(BitMap、Geo和
HyperLogLog)
前⾔
Reids 在 Web 应⽤的开发中使⽤⾮常⼴泛,⼏乎所有的后端技术都会有涉及到 Redis 的使⽤。Redis 种除了常见的字符串String、字典 Hash、列表 List、集合 Set、有序集合 SortedSet 等等之外,还有⼀些不常⽤的数据类型,这⾥着重介绍三个。下⾯话不多说了,来⼀起看看详细的介绍吧。
BitMap
BitMap 就是通过⼀个 bit 位来表⽰某个元素对应的值或者状态, 其中的 key 就是对应元素本⾝,实际上底层也是通过对字符串的操作来实现。Redis 从 2.2 版本之后新增了setbit, getbit, bitcount 等⼏个 bitmap 相关命令。虽然是新命令,但是本⾝都是对字符串的操作,我们先来看看语法:
SETBIT key offset value
其中 offset 必须是数字,value 只能是 0 或者 1,咋⼀看感觉没啥⽤处,我们先来看看 bitmap 的具体表⽰,当我们使⽤命令setbit key (0,2,5,9,12) 1后,它的具体表⽰为:
byte bit0bit1bit2bit3bit4bit5bit6bit7
byte010100100
byte101001000
可以看出 bit 的默认值是 0,那么 BitMap 在实际开发的运⽤呢?这⾥举⼀个例⼦:储存⽤户在线状态。这⾥只需要⼀个 key,然后把⽤户 ID 作为 offset,如果在线就设置为 1,不在线就设置为 0。实例代码:
//设置在线状态
$redis->setBit('online', $uid, 1);
//设置离线状态
$redis->setBit('online', $uid, 0);
//获取状态
$isOnline = $redis->getBit('online', $uid);
//获取在线⼈数
$isOnline = $redis->bitCount('online');
Geo
Redis 的 GEO 特性在 Redis 3.2 版本中推出,这个功能可以将⽤户给定的地理位置信息储存起来,并对这些信息进⾏操作。GEO 的数据结构总共有六个命令:geoadd、geopos、geodist、georadius、georadiusbymember、gethash,这⾥着重讲解⼏个。
1.GEOADD
redis支持的五种数据类型GEOADD key longitude latitude member [longitude latitude member ...]
将给定的空间元素(纬度、经度、名字)添加到指定的键⾥⾯。这些数据会以有序集合的形式被储存在键⾥⾯,从⽽使得像GEORADIUS 和 GEORADIUSBYMEMBER 这样的命令可以在之后通过位置查询取得这些元素。例⼦:
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
2.GEOPOS
GEOPOS key member [member ...]
从键⾥⾯返回所有给定位置元素的位置(经度和纬度),例⼦:
redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
2) "38.115556395496299"
3.GEODIST
GEODIST key member1 member2 [unit]
返回两个给定位置之间的距离。如果两个位置之间的其中⼀个不存在,那么命令返回空值。指定单位的参数 unit 必须是以下单位的其中⼀个:(默认为m)
m 表⽰单位为⽶。
km 表⽰单位为千⽶。
mi 表⽰单位为英⾥。
ft 表⽰单位为英尺。
redis> GEODIST Sicily Palermo Catania
"166274.151********"
4.GEORADIUS
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
以给定的经纬度为中⼼,返回键包含的位置元素当中,与中⼼的距离不超过给定最⼤距离的所有位置元素。距离单位和上⾯的⼀致,其中后⾯的选项:
WITHDIST:在返回位置元素的同时,将位置元素与中⼼之间的距离也⼀并返回。距离的单位和⽤户给定的范围
单位保持⼀致。
WITHCOORD:将位置元素的经度和维度也⼀并返回。
WITHHASH:以 52 位有符号整数的形式,返回位置元素经过原始 geohash 编码的有序集合分值。这个选项主要⽤于底层应⽤或者调试,实际中的作⽤并不⼤。
redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
2) "190.4424"
2) 1) "Catania"
2) "56.4413"
HyperLogLog
Redis 的基数统计,这个结构可以⾮常省内存的去统计各种计数,⽐如注册 IP 数、每⽇访问 IP 数、页⾯实时UV)、在线⽤户数等。但是它也有局限性,就是只能统计数量,⽽没办法去知道具体的内容是什么。
当然⽤集合也可以解决这个问题。但是⼀个⼤型的⽹站,每天 IP ⽐如有 100 万,粗算⼀个 IP 消耗 15 字节,那么 100 万个IP 就是 15M。⽽ HyperLogLog 在 Redis 中每个键占⽤的内容都是 12K,理论存储近似接近 2^64 个值,不管存储的内容是什么,它⼀个基于基数估算的算法,只能⽐较准确的估算出基数,可以使⽤少量固定的内存去存储并识别集合中的唯⼀元素。⽽且这个估算的基数并不⼀定准确,是⼀个带有 0.81% 标准错误的近似值。
这个数据结构的命令有三个:PFADD、PFCOUNT、PFMERGE
1.PFADD
redis> PFADD databases "Redis" "MongoDB" "MySQL"
(integer) 1
redis> PFADD databases "Redis" # Redis 已经存在,不必对估计数量进⾏更新
(integer) 0
2.PFCOUNT
redis> PFCOUNT databases
(integer) 3
3.PFMERGE
PFMERGE destkey sourcekey [sourcekey ...]
将多个 HyperLogLog 合并为⼀个 HyperLogLog,合并后的 HyperLogLog 的基数接近于所有输⼊ HyperLogLog 的可见集合的并集。合并得出的 HyperLogLog 会被储存在 destkey 键⾥⾯,如果该键并不存在,那么命令在执⾏之前,会先为该键创建⼀个空的 HyperLogLog 。
redis> PFADD nosql "Redis" "MongoDB" "Memcached"
(integer) 1
redis> PFADD RDBMS "MySQL" "MSSQL" "PostgreSQL"
(integer) 1
redis> PFMERGE databases nosql RDBMS
OK
redis> PFCOUNT databases
(integer) 6
总结
以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,如果有疑问⼤家可以留⾔交流,谢谢⼤家对的⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论