redis的数据结构

Redis的基础数据结构分为5种,分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。熟练掌握这 5 种基本数据结构的使用是 Redis 知识最基础也最重要的部分。

String 字符串结构
String 字符串是动态字符串内部实现结构类似于Arraylist,采用预分配冗余的方式,减少内存空间的频繁分配。内部为字符串分配的空间会大于实际长度。当字符串长度小于1M,扩容都是加倍当前空间,大于1M则每次扩容增加1M,最大长度为512M。
其底层实现是简单动态字符串sds,一个sds字符串的完整结构由在内存地址前后两部分组成。第一,hearder。第二,字符数组。sds本质为char但是和char不相同的是sds是二进制安全的,可以存储任意二进制数据,不像c一样遇到’\0’来标识字符串的结束。另外其一种的header包含字符串长度,所以查询长度的复杂度为O(1)。

基本语法:
SET key value
1.字符串值 value 关联到 key 。
2.如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
在这里插入图片描述
SETEX key seconds value
1.value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。
2.如果 key 已经存在, SETEX 命令将覆写旧值。
redis的数据结构_第1张图片
ETNX key value
1.将 key 的值设为 value ,当且仅当 key 不存在。
2.若给定的 key 已经存在,则 SETNX 不做任何动作。
在这里插入图片描述
使用场景:缓存信息,session,计数(bitmap)

List 列表结构
List列表3.2之前LinkList和ziplink,3.2之后改为qucklink,是一个按照插入顺序排序的链表。在3.2版本之前,如果list数据的长度较少,或者数据量不多用ziplink,如果过大,则用双向链表。Ziplink存放在一段连续的内存中,存储效率高,但是删除和插入就需要频繁申请内存和释放内存。如果数据长度很长 可能会导致realloc(内存分配)时候大批量拷贝数据。Linklist的push和pop操作使插入节点上复杂度很低。但是内存开销大,在每个节点上要保存数据外,还要保存额外两个指针记录前后标识。其次,各个节点都是单独内存块,不连续,容易产生内存碎片。Qucklink的每个节点都是Ziplink。Redis的参数list-max-ziplist-size可以设置,默认-2 ,8kb。对于内部压缩算法为LZF,无损压缩算法。
通常做异步队列,将需要延后处理的任务结构体序列化存进redis的列表,然后在另一线程中取出进行业务处理
Redis的list数据结构常用来作为异步消息队列使用,使用rpush/lpush操作入队列,使用lpop 和 rpop来出队列。

如图:右进左出为队列
redis的数据结构_第2张图片

Hash 结构
Redis的Hash内部是数组加链表的结构和hsahmap相同。但是redis的值只能是字符串。还有一点不同的是java的HashMap采用的一次性扩容的方式,而Redis为了高性能,采用渐进式策略。渐进式的rehash会在rehash的时候保留新旧hash结构,然后再后续的hash操作中逐渐将旧hash迁徙到新hash上,当迁徙完成旧hash会被删除,内存被回收。
Rehash介绍:当hash表保存的键较多或者较少时,哈希表会进行扩容或者缩减。在逐渐式rehash时,hash表会同时使用ht[0],ht[1]。字典的curd都会在这两个表进行。如果是新增只会新增在新表,这样保证旧表只会随着rehash或进行删除操作减少。最终变为空表,被回收释放内存。

redis的数据结构_第3张图片
使用场景:商品展示(用于两层嵌套场景。比如一个商品多重类型,每个类型多重样式)
也能用来存储用户信息。(可以对用户结构的每个字段单独存储,获取时不像String一样序列化整个字符串,可以单独读取部分)

Set结构
Set是一种无序不重复的集合。
在这里插入图片描述

使用场景:抽奖(确保不重复中奖)

Zset 结构
Zset集合一方面是个set,保证了唯一性。另一方面它给内部的value赋了一个score,代表这个value的排序权重。排序功能是通过跳跃列表的数据结构实现的。Zset内部数据结构可以是ziplist或者skiplist。
当满足元素数量小于128和所有menber长度小于64字节,使用ziplist。当然,可以通过修改zset-max-ziplist-entries和zset-max-ziplist-value来修改上限阈值。Ziplist使用紧挨在一起的压缩列表节点保存。第一个节点保存menber,第二个节点保存score。内部按照score从小到大排序,小的排在表头。
skipList内部结构是zset结构体。一个zset包含hash和一个跳跃表。跳跃表按照score进行从小到大的排序。而hash则保存menber和score的映射。这样通过menber查询score复杂度为O(1),虽然是使用了两个结构,但是是通过指针来共享menber和score,并不会造成内存的浪费。

redis的数据结构_第4张图片
使用场景:粉丝列表(key 为id,value为时间排序),订单列表

参考书籍:
《Redis深度历险:核心原理与运用实践》
《redis设计与实现》

你可能感兴趣的:(redis系列,java,数据结构)