我们之前已经学过了Redis最常用的五个类型了,然而Redis还有一些在特定场景下比较好用的类型
Redis最关键的五个数据类型:
上面的类型是非常常用,很重要的类型。
除此之外的其他类型不常用,只是在特定的场景能够发挥用处,所以这里只是做简单描述与介绍。
stream
它的插入就是往尾部插入log(字符串)。
这其实就是一个队列(阻塞队列),它是Redis作为消息队列的重要支撑。
属于是 list blpop brpop的升级版。
geospatial
这是用来存储经纬度的类型。
在存储一些点以后,就可以让用户给定一些坐标,去从刚才存储的点里进行查找(按照半径)
这个功能在 地图 应用非常重要。
比如在高德地图中,我们对一个位置搜索周边时
就会有这样的圆形区域。
官方文档这里给的命令也就俩。
但是使用起来还是有点复杂的,选项比较多。
HyperLogLog
这个类型的应用场景只有一个,就是估算集合中元素的个数。
之前学过用Set类型可以统计服务器的UV(用户访问次数),这里的统计是精确统计,因为它是老老实实将数据存储起来的,但是HyperLogLog这里应用了位运算的思想,并没有真的将数据存储起来,而是记录这个元素的特征,从而在新增元素的时候来判断这个元素是否已经存在了,这样做会存在一些误差,
官方文档这里给出的误差是 0.81%。
接口也比较少
bitmap
用位图来表示整数,这是专门用来存储整数的。
这个位图的本质其实就是一个集合,属于是Set类型针对整数的特化版本。
这里要区分bitmap与HyperLogLog的区别:
HyperLogLog:
优点:更节省空间,而且既可以存储整数,也可以存储字符串。
短板:不能存储元素内容(信息量丢失了),只能起到一个计数的效果(存在误差)。
bitmap:
优点:能存储元素的内容。
短板:只能存储整数。
bitfields
这个叫做位域(位段)。跟C语言的位段非常相似。
看下官网的使用示例:
先是对key bike:1:stats又执行了一个类似子命令的效果 set了一个 32位int 的key #0,初始值1000
然后又用incrby将其的值减少了50,并对 #1的值进行了+1操作,虽然#1之前不存在,但是在执行这个命令前就会创建出来,并初始化为0。后面就不再赘述了。
渐进式遍历
之前学过keys 命令,它是一次性把Redis中所有的key都获取到。这个命令是不推荐使用的,因为当Redis中的key的数量足够多时,就有可能导致Redis服务器阻塞。
通过渐进式遍历,每一次执行获取部分key,这样就能保证当前一次操作不会太卡,想要获取全部的key,执行多次就可以了。
渐进式遍历其实是一组命令,这一组命令的使用方法是一样的。 其中代表性的命令就是scan。
用法:
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
关于参数选项:
cursor:光标。不是下标,从0开始,每次遍历后,服务器会返回下一次要从哪个光标开始遍历,这个光标是不会按照下标的方式走的,它是由服务器决定的,当光标回到0时说明遍历结束了。
[MATCH pattern] 这个选项就是参数匹配,用法跟keys那里是一样的。
[COUNT count]:count是向Redis服务器建议这一次需要遍历多少个元素。注意这里跟MySQL中的limit不同,limit是精确的,除非元素不够,不然limit 多少个元素就显示多少个元素,而Redis这里的count只是向Redis建议遍历count个元素,因此写入的count与实际返回的key的个数不一定完全相同,但是不会差很多。 一般不写默认是10 。
[TYPE type]:可以选择key的类型,比如list set之类的,那么遍历就会过滤掉其他类型。
使用示例:
可以看到,光标的变动对于客户端来说几乎是随机的,只有重新变回0时则说明遍历结束了。 光标在服务器那端可以理解为是一段字符串。
在这里的渐进式遍历过程中,不会在服务器这边存储任何的状态信息。
也就是说,此处的遍历是可以随时终止的,不会对服务器产生任何副作用。
打个比方:
我们去超时买东西,结账到一半时,剩下的一些商品不想要了,我们可以随时跟收银员说,然后会有工作人员将这些商品放回原位,不会产生什么影响,就跟这里的渐进式遍历一样;
再比如,我们去吃烧烤,有些菜上得特别慢,导致我们都吃完了菜还没上,此时我们就想直接结账,把未上的菜给退掉,但是恰巧这些菜又已经在后厨烧了,那么此时我们想强行退掉就会产生一些副作用(比如跟老板吵架,或者老板扣员工工资等等)。
所以Redis属于前者,这点还是比较好的。
最后,需要注意:虽然渐进式遍历scan解决了阻塞的问题,但是键如果在遍历期间发生了变化(增加,修改,删除),可能会导致遍历时键出现重复遍历或者遗漏,这点需要我们开发者在实际开发中进行考虑的。
这点其实就跟C++的迭代器失效问题差不多。如果C++遇到这个问题一般就程序崩溃了,但是Redis不会使程序崩溃,而是会出现重复遍历或者遗漏,这样反而不方便发现问题的所在。
在C++语言中,前置++要比后置++的性能更高,因为会少一次临时对象的拷贝。
关于Redis数据库管理
在MySQL中有一个很重要的概念,就是database,也就是数据库。一个mysql服务器可以有很多个database。然而在对Redis的学习过程中,感觉好像一上来就是 key value。
其实Redis也是有database的概念的,只是不像MySQL那样随意,在Redis中的数据库都是现成的,用户不能创建新的database,也不能删除已有的database。Redis默认提供了16个数据库,编号 0 ~ 15。我们一开始用的就是0号数据库,并且实际使用Redis会很少关注到数据库,一般都是使用默认的0号数据库。
切换数据库:
select dbIndex
比如我们在0号数据库下有一些key,切换到1号数据库就看不见属于0号数据库的key了
DBSIZE
返回当前数据库有多少个key
关于删库的操作
FLUSHDB
这是删除当前数据库的。
FLUSHALL
这是删除所有数据库中的所有元素。
注意:永远不要在线上环境执⾏清除数据的操作,除⾮你想体验⼀把 “从删库到跑路” 的操作。