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相关命令。虽然是新命令,但是本身都是对字符串的操作,我们先来看看语法:
SETBITkeyoffsetvalue
其中offset必须是数字,value只能是0或者1,咋一看感觉没啥用处,我们先来看看bitmap的具体表示,当我们使用命令setbitkey(0,2,5,9,12)1后,它的具体表示为:
byte | bit0 | bit1 | bit2 | bit3 | bit4 | bit5 | bit6 | bit7 |
---|---|---|---|---|---|---|---|---|
byte0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
byte1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
可以看出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特性在Redis3.2版本中推出,这个功能可以将用户给定的地理位置信息储存起来,并对这些信息进行操作。GEO的数据结构总共有六个命令:geoadd、geopos、geodist、georadius、georadiusbymember、gethash,这里着重讲解几个。
1.GEOADD
GEOADDkeylongitudelatitudemember[longitudelatitudemember...]
将给定的空间元素(纬度、经度、名字)添加到指定的键里面。这些数据会以有序集合的形式被储存在键里面,从而使得像GEORADIUS和GEORADIUSBYMEMBER这样的命令可以在之后通过位置查询取得这些元素。例子:
redis>GEOADDSicily13.36138938.115556"Palermo"15.08726937.502669"Catania" (integer)2
2.GEOPOS
GEOPOSkeymember[member...]
从键里面返回所有给定位置元素的位置(经度和纬度),例子:
redis>GEOPOSSicilyPalermoCataniaNonExisting 1)1)"13.361389338970184" 2)"38.115556395496299"
3.GEODIST
GEODISTkeymember1member2[unit]
返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在,那么命令返回空值。指定单位的参数unit必须是以下单位的其中一个:(默认为m)
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
redis>GEODISTSicilyPalermoCatania "166274.15156960039"
4.GEORADIUS
GEORADIUSkeylongitudelatituderadiusm|km|ft|mi[WITHCOORD][WITHDIST][WITHHASH][ASC|DESC][COUNTcount]
以给定的经纬度为中心,返回键包含的位置元素当中,与中心的距离不超过给定最大距离的所有位置元素。距离单位和上面的一致,其中后面的选项:
WITHDIST:在返回位置元素的同时,将位置元素与中心之间的距离也一并返回。距离的单位和用户给定的范围单位保持一致。
WITHCOORD:将位置元素的经度和维度也一并返回。
WITHHASH:以52位有符号整数的形式,返回位置元素经过原始geohash编码的有序集合分值。这个选项主要用于底层应用或者调试,实际中的作用并不大。
redis>GEORADIUSSicily1537200kmWITHDIST 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>PFADDdatabases"Redis""MongoDB""MySQL" (integer)1 redis>PFADDdatabases"Redis"#Redis已经存在,不必对估计数量进行更新 (integer)0
2.PFCOUNT
redis>PFCOUNTdatabases (integer)3
3.PFMERGE
PFMERGEdestkeysourcekey[sourcekey...]
将多个HyperLogLog合并为一个HyperLogLog,合并后的HyperLogLog的基数接近于所有输入HyperLogLog的可见集合的并集。合并得出的HyperLogLog会被储存在destkey键里面,如果该键并不存在,那么命令在执行之前,会先为该键创建一个空的HyperLogLog。
redis>PFADDnosql"Redis""MongoDB""Memcached" (integer)1 redis>PFADDRDBMS"MySQL""MSSQL""PostgreSQL" (integer)1 redis>PFMERGEdatabasesnosqlRDBMS OK redis>PFCOUNTdatabases (integer)6
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。