Loading

REDIS中常见的数据结构有几种?在你看来每种数据结构的应用场景应该是怎样的?

今天这个问题比较初级,很多同学应该可能都知道,即便是没吃过猪肉,也应该见过猪跑。废话不多说,步入正题。

小提示,redis是使用C语言实现的。

字符串

第一种数据就是字符串,也就是string,这是redis中最基础的数据类型了,最起码redis中所有的key本身都是字符串类型。

场景

我举几个常见的场景:
这个东西用处就比较广了。如果一个数据表数据量过千万了,而你的业务需要反复count表的总数,这个操作是很耗费性能的,这会儿你就可以用string字符串来缓存这个总数
如果你需要一个计数器,那么也可以利用字符串类型,因为字符串类型有一个incr操作,可以在收到操作后将数字+1
有些博客中还说将用户信息也存到字符串中,我认为这很脑残。因为要往字符串中存用户数据,你就必须得先将用户信息序列化了之后才能存储到字符串中,用的时候,你还得反序列化,我认为这不科学
字符串在redis中实现本质上讲就是c语言的字符串,但是大家知道C语言中实际上压根没有字符串这种数据类型,对C语言来说字符串也就是一坨字符+一个\0结束符。redis中的字符串要比单纯的C语言字符串要稍微复杂一些,叫做SDS。redis的SDS除了保存字符串本身外,还有该字符串的长度,以及尚未使用完剩余的空间长度。当你使用redis中strlen来获取一个字符串长度的时候,实际上就是直接读取的长度属性,所以在O(1)时间复杂度情况下读出长度。先到此为止,不能扯太深的SDS,放到后面。

list

第二种数据结构就是list,也就是链表。你们先记住了,redis的list本质上是一个双向链表,双向链条的意思就是组成链表的每个节点中,有一个指向前面节点的指针,也有一个指向后面节点的指针,穿成了一串。

场景

充当简单的消息队列。我们知道list有四个风骚的操作,在list的头部添加元素或删除元素,在list在尾部添加元素或删除元素,利用这个特性我们可以利用list来充当一个简单的消息队列,避免了很多同学不懂rabbitmq、kafka之类的高端玩意
做简单的抢购秒杀。比如抢购10个元素,那么可以预先向list中插入10个任意元素,每抢到一个就rpop一下,当list中什么都没有了的话,rpop值就是false,这会儿就算抢购完毕了。有同学有疑问,说利用字符串保存一个计数器不是也能抢购吗?并不能,你一定是这么想的,比如你存了一个counter数值是10,每抢到一次就减1,一直到0,是吧。但是你为了实现这个逻辑一定有两个分开的关键操作,一个判断counter大小,另一个是减1,这个时候在并发大的时候会出现一种可能性,就是当一个路人甲用户判断完counter为1后,还剩最后一个库存,于是就准减1了,但是恰巧,在路人甲对counter减1之前完成前,又来了一个路人乙用户也刚执行完了判断counter,由于路人甲还没有减1,所以路人乙判断的counter也一定是1,那么,超卖就产生了

无序集合

第三种数据是set,这是一种无序集合,集合中只能存数字,而且不会重复,也就是说如果你反复存了两个数字22,那么最终也会只有一个22,所以set有两大特征:无序和唯一!set在redis中实现本质上就是一个struct结构体,如果你不知道struct是啥,那就简单点儿,其实就是一个整数数组,还有一个数组长度。所以,获取set中元素数量的时候,对于redis是轻而易举的,O(1)内拿下!

场景

set最厉害的地方就是求交集、求差集以及并集。所以当我们查看两个人共同好友的时候,可以迅速获取到。
大家都玩过探探吧,左滑右滑,单凡滑过的人都不会再次出现,那么如何记录你曾经滑过的人呢?我认为set就可以大放异彩了。然后比如著名社交软件,积目,就是靠这个实现的,是不是很垃圾?

有序结合

第四种数据结构是zset,叫做有序结合,zset中的数据可以重复,所以zset有两大特征,一是可以重复,二是这些数据是有序的并且可以排序。利用这个特征,我们可以知道zset中的数据是可以分页的!一定要记住!zset中的数据可以分页!zset在redis中实现本质上就是skiplist,也就是传输中的跳表,不懂可以先记住!之所以具备有序特性,也完全是因为跳表本身的特性。跳表的结构是redis常见数据结构比较复杂的了,至少在我看来是这样的。具体结构我们放到后面解析。

场景

zset可以做什么?粉丝列表。因为粉丝列表查看粉丝是需要按照关注时间倒序进行排列的,而且还可以分页!这个就很屌!
排行榜。比如我们要做一个积分用户榜单,当然使用mysql也可以使用order by来解决,但是利用redis显然是更快更猛。

字典

第五种数据结构是字典了,这种数据结构很类似于php的数组,专门用于存放一坨key=》value键值对。字典这个东西在redis中的C语言实现就是哈希这个著名的数据结构,不理解是吧,先背过,后面有解析,你记住了知道了就比不知道强。

场景

前面说了,用字符串来存储序列化后的用户数据是愚蠢的,原因就是有现成的字典,用这个就是绝配。
举个例子,比如api服务中我们知道一个token对应着一个用户,就相当于web开发中的cookie和session,那么这会儿就可以拿token当作redis的key,然后将整个用户数据当作value存储到一个字典中
好了,总体来说今天这道题比较简单比较入门!如果大家对redis这种五种数据结构的操作还不熟悉,那么你们一定要去熟悉一下!千万不要懒惰,我说了这面试题是基础入门的,对这五种数据操作几乎是人人应该必备操作必会,连入门都不算。

今天算是用一道入门基础题开刀,后面我会持续对redis进行更高门槛的面试题提问。如果今天这些题你有一半以上搞不定,说明你的基础很差,赶紧补吧!

转:老李秀

posted @ 2018-09-05 13:21  王召波  阅读(965)  评论(0编辑  收藏  举报