Redis五种数据类型及底层数据结构
redis五种数据类型,string、hash、list、set、zset及其底层数据结构跳表、ziplist等
目录
1.数据类型
Redis的数据类型5种:String、Hash、List、Set、ZSet
数据类型 | 解释 | 适用 | 底层(最新的) |
string | 最简单的,可以存储文本、数字等 | 缓存、计数器 | SDS |
hash | 适用于存储对象的属性和值之间的映射关系 | 存储用户信息、配置信息 | hashrable、listpack |
list | 有序可重 | 适用于存储按顺序排列的数据,比如消息队列、任务列表 | quicklist |
set | 无序不重 | 适用于存储唯一的、不重复的数据,比如用户标签、文章标签等 | intset、hashtable |
zset | 有序,每个字符串都关联一个分数(score) | 按分数排序的数据,比如排行榜、计分系统 | listpack、skiplist |
1、string
底层的数据结构实现主要是SDS(简单动态字符串)
SDS
- SDS 不仅可以保存文本数据,还可以保存二进制数据。
- SDS 获取字符串长度的时间复杂度是 O(1)
- Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出。
2、hash
Hash 类型的底层数据结构是由压缩列表或哈希表实现的:
- 如果哈希类型元素个数小于
512
个(默认值,可由hash-max-ziplist-entries
配置),所有值小于64
字节(默认值,可由hash-max-ziplist-value
配置)的话,Redis 会使用压缩列表(ziplist)作为 Hash 类型的底层数据结构; - 如果哈希类型元素不满足上面条件,Redis 会使用哈希表作为 Hash 类型的 底层数据结构。
在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。
Ziplist
以一种紧凑的方式存储数据,相邻的数据项紧密排列,不像普通的数据结构那样包含额外的指针或元数据,显著减少内存的使用.可以存储不同类型的数据,字符串、整数和浮点数.
缺点:
- 一是不能保存过多的元素,否则访问性能会降低;
- 二是不能保存过大的元素
listpack
也叫紧凑列表,它的特点就是用一块连续的内存空间来紧凑地保存数据,同时为了节省内存空间,listpack 列表项使用了多种编码方式,来表示不同长度的数据,这些数据包括整数和字符串。
3、list
List 类型的底层数据结构是由双向链表或压缩列表实现的:
- 如果列表的元素个数小于
512
个(默认值,可由list-max-ziplist-entries
配置),列表每个元素的值都小于64
字节(默认值,可由list-max-ziplist-value
配置),Redis 会使用压缩列表作为 List 类型的底层数据结构; - 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构;
但是在 Redis 3.2 版本之后,List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表。
快表(QuickList)
是由多个节点(Node)组成的双向链表,每个节点都是一个ziplist(压缩列表)。快表中的每个节点包含了多个元素,每个元素可以是一个整数或一个字节数组。
4、set
Set 类型的底层数据结构是由哈希表或整数集合实现的:
- 如果集合中的元素都是整数且元素个数小于
512
(默认值,set-maxintset-entries
配置)个,Redis 会使用整数集合作为 Set 类型的底层数据结构; - 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为 Set 类型的底层数据结构
SADD key member [member ...];
key是要操作的集合的键名,member是要添加的成员
127.0.0.1:6379> sadd fruits apple (integer) 1 127.0.0.1:6379> sadd fruits banana orange (integer) 2
在这个示例中,我们先向fruits集合中添加了一个apple成员,返回值为1,表示成功添加了一个新成员。然后向fruits集合中添加了banana和orange两个成员,返回值为2,表示成功添加了两个新成员。
- sadd命令可以向集合中添加一个或多个成员,而且如果添加的成员已经存在于集合中,则不会重复添加。
- sadd命令返回的是添加成功的新成员数量,不包括已经存在于集合中的成员。添加存在的返回0
SREM key member [member ...];
key
是要操作的集合的键值,member
是要移除的成员SADD myset "member1" SADD myset "member2" SADD myset "member3" SREM myset "member1" "member2"
首先使用SADD命令向集合myset中添加了三个成员。然后,使用SREM命令将”member1″和”member2″从myset中同时移除。返回被移除的成员数量,若集合中成员不存在,不起效果返回0
SMOVE source destination member;
SMOVE myset myotherset 123
这个命令原子性的,将尝试将元素
123
从myset
集合移动到myotherset
集合。如果成功,命令将返回1
,表示一个元素被移动。如果元素不存在于源集合中,无效果将返回0
。SMEMBERS key;
key表示要获取成员的集合的键名
# 创建一个名为fruits的集合 > sadd fruits apple banana orange # 获取fruits集合中的所有成员 > smembers fruits
1) "apple" 2) "banana" 3) "orange"
在这个示例中,我们首先创建了一个名为fruits的集合,并添加了三个成员:apple、banana和orange。然后使用smembers命令获取fruits集合中的所有成员,返回了一个包含三个成员的数组。
SCARD key;
返回值为集合中的元素数量
127.0.0.1:6379> scard fruits (integer) 3
scard
命令返回的值为3
,说明fruits
集合中共有 3 个元素。
5、zset
Zset 类型的底层数据结构是由压缩列表或跳表实现的:
- 如果有序集合的元素个数小于
128
个,并且每个元素的值小于64
字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构; - 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;
在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。
ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUE
redis> ZADD myzset 2 "two" 3 "three" (integer) 2
返回的是添加成功的新成员数量,不包括已经存在于集合中的成员
ZCARD key;
计算集合中元素的数量
redis> ZADD myzset 1 "one" (integer) 1
ZCOUNT key min max;
计算有序集合中指定分数区间的成员数量
redis 127.0.0.1:6379> ZADD myzset 1 "hello" (integer) 1 redis 127.0.0.1:6379> ZADD myzset 1 "foo" (integer) 1 redis 127.0.0.1:6379> ZADD myzset 2 "world" 3 "bar" (integer) 2 redis 127.0.0.1:6379> ZCOUNT myzset 1 3 (integer) 4
先加入4个,然后zcount计算score在1到3之间的,有四个,返回4
ZSCORE key member
返回有序集中,成员的分数值
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 测试数据 1) "tom" 2) "2000" 3) "peter" 4) "3500" 5) "jack" 6) "5000" redis 127.0.0.1:6379> ZSCORE salary peter # 注意返回值是字符串 "3500"
ZRANK key member;
返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列
redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示所有成员及其 score 值 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000" redis 127.0.0.1:6379> ZRANK salary tom # 显示 tom 的薪水排名,第二 (integer) 1
ZREM key member [member ...]
返回成功移除的元素个数
跳表(skiplist)
参考:
Skip List--跳表(全网最详细的跳表文章没有之一) - 简书 (jianshu.com)
跳表 (Skip List) 是一种随机化数据结构,支持对数据的快速查找,插入和删除,跳表是可以实现二分查找的有序链表。跳表的期望空间复杂度为 O(n),跳表的查询,插入和删除操作的期望时间复杂度都为O(logN)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)