最近又重新学习了下redis相关的知识,在这里做下分享,我们在实际工作中最常用的还是它的5种基础数据结构,今天不介绍这5种数据结构的基本语法,主要简单的介绍下它们的底层结构还有使用场景。
5种基础数据结构
+
String
String是Redis最简单的数据结构,它的内部结构表示就是一个字符数组,字符串应用非常广泛,最常见的是缓存用户信息。我们将用户信息结构体使用JSON序列化成字符串,然后将字符串存入到Redis来缓存。
Redis的字符串是动态字符串,是可以修改的字符串,内部结构类似于java的ArrayList,采用预分配的方式减少内存的频繁分配,内部为当前字符串分配的内容一般高于实际的字符串长度。当需要扩容时会遵循如下规则:
当字符串长度小于1MB时,扩容都是加倍现有空间。
当字符串长度大于1MB时,扩容时一次只能多扩1MB的空间。
最终需要注意的是字符串最大长度为512MB。
List
相当于java语言里面的LinkedList,它是链表而不是数组,这意味着list的插入和删除操作非常快,时间负责度是O(1),但是查找很慢,时间负责度是O(n)。列表中的每个元素都是用双向指针顺序,串起来可以同时支持前后向的遍历。
Redis 的list 常用来做异步队列使用。将需要延后处理的任务结构序列化成字符串,塞进Redis的列表,另一个线程从这个列表中轮询数据进行处理。
Redis的底层结构并不是简单的 LinkedList,而是称为“快速链表”(QuickList)的结构,
QuickList结构可以理解为由LinkedList与ZipList组合而成,所谓ZipList是在列表中元素很少的情况下,会使用一块连续的内存存储,这个结构就是ZipList。它所有的元素彼此紧挨着一起存储,分配的是一个连续的内存。
hash
Redis中的hash相当于java语言中的HashMap。实现结构上都是“数组+链表”的二维结构。不同的是,Redis的字典的值只能是字符串,另外它们rehash的方式不一样。java的HashMap,当字典很大时,rehash是一个耗时的操作,需要一次性全部rehash,Redis为了追求高性能,不能堵塞服务,所以采用了渐进式rehash策略。也就是在rehash的同时保留新旧两个hash结构,查询时会同时查询两个hash结构,然后在后续的定时任务以及hash操作指令中,循序渐进地将就hash的内容一点点地迁移到新的hash结构中。
hash结构也可以用来存储用户信息。与字符串需要一次性全部序列化整个对象不同,hash可以对用户结构中的每个字段单独存储。这样我们在获取信息的时候就可以实现部分获取。在存储用户信息这个问题上与字符串相比hash的缺点是存储消耗更多一些。
set
Redis中的set相当于java语言中的HashSet。它内部的键值对是无序的,唯一的。
字典中所有的value都是一个值NULL。
Redis的set接口可用用来存储在某活动中中奖的用户ID,因为有去重功能,可以保证同一个用户不会中奖两次。
zset
zset是Redis提供的最有特色的数据结构。类似java语言中的SortedSet和HashMap的结合体。一方面是一个set保证了value的唯一性,另一方面可以给每个value赋值一个score 。
zset可以用来存储学生的成绩,value是学生的ID,score是学生的成绩。还可以用来存储粉丝的列表,value的只是粉丝的ID,score是关注时间,这样可以对粉丝列表按关注事件进行排序。
总结
+
本文从内存结构上介绍了下Redis的五种基本结构,这些在实际工作中也许用不到,但是多一些了解还是有必要的。
参考资料
+
《Redis 深度历险 核心原理与应用实践》 钱文品/著