共计 5961 个字符,预计需要花费 15 分钟才能阅读完成。
本篇内容主要讲解“常见 Redis 数据结构有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“常见 Redis 数据结构有哪些”吧!
什么是数据结构?
有 Java 基础的应该知道常用的一些数据结构,比如数组、队列、栈等等 … 那 Redis 的数据结构跟 Java 的数据结构有什么区别吗?答案是有的,如果一些小伙伴了解的 Map 的话就知道 Map 中有一个 Key 值和一个 Value 值,Redis 的数据结构也是这样的。
Redis 的数据结构:String、List、Hash、Set 的话都是有一个 Key 值和一个 Value 值。
Key 值是名字,Value 值就是数据。这两个是绑定在一起的,一个 Key 值对应一个 Value 值,我们称之这样的为键值对。
Redis 常用的基本命令
在 Redis 中,在不同的场景下会使用不同的命令。但是不是每个命令都需要记住呢?不是的,只需要熟悉最常用的命令就好了,在需要使用一些少用的命令可以去官方文档查阅即可。下面来介绍 Redis 中一些常用的命令。
1.# exists(判断 key 值是否存在):如果存在返回 1,反之返回 0
例子: exists name(name 为 key)
2.# del(删除 key): 删除成功返回 1,反之返回 0
3.# type(判断 key 的类型)4.ttl(查看 key 存活时间
想学习更多命令可以自行到中文文档进行查询:http://www.redis.cn/
String 类型的介绍与使用场景
String 字符串类型是 Redis 中最基本的数据类型,在 Redis 中的应用场景很广,一个 key 对应一个 value。
Redis 的 String 是动态字符串,可修改的字符串,它的内部结构类似于 Java 的 ArrayList, 采用预分配冗余空间的方式来减少内存的分配。
String 类型是二进制安全的,意思就是 Redis 的 String 可以包含任何的数据。如:数字,字符串,图片等
String 类型的应用场景:验证码、计数器、订单重复提交、用户登录信息、商品详情的实现
String 的常用命令
1.# set/get 设置和获取 key-value 注意中间一定要加空格
例子: set xxx(key) xxx(value)
get xxx(key)
2.# mget/mset 批量设置或获取多个 key 的值
mset user:name jack user:age 2
mget user:name user:age
3.# incr incr 对 key 对应的值进行加 1 操作,并返回新的值
incr video:uv:1
4. # incrby 将 key 对应的数字加 increment. 如果 key 不存在,操作之前,key 就会被置为 0
incrby video:uv:1 10
5.# setex 设置 key 对应字符串 value,并且设置 key 在给定的 seconds 时间之后超时过期操作
setex code 20 778899 (设置一个 key 为 code value 为 778899 20 秒后过期)4
6. # setnx 将 key 设置值为 value,如果存在该 key 那么什么都不做,如果不存在 key 那么等同于 set 命令
setnx name xdclass.net
7. # getset 设置 key 的值,并返回 key 旧的值
get name uuuuu (这时会返回 xdclass.net,重新在 get 一下会获得重新设置的值 uuuuu)
注意:值的长度不能超过 512MB,遵循 key 的命名规范:业务名:表明:ID(不要过长,用冒号分割)
String 的内部结构(内部结构为深入探究)
Redis 中没有使用 C 语言的传统字符串来表示,而是构建了一种名为简单动态字符串(SDS)的抽象类型。为什么 Redis 要用自己构建的 SDS 而不是直接用 C 语言的 String 呢?原因其实很简单,就是为了提升 Redis 操作的性能。
SDS 字符串与 C 语言字符串具有什么优势?
常数复杂度获取字符串长度:C 语言想获取长度,那么它必须要遍历一整个字符串才行。SDS 通过 len 属性获取 SDS 字符串长度的时间复杂度从 O(N) 变成了 O(1),保证了获取字符串长度时不会成为 Redis 的性能瓶颈。
减少修改带来的内存重新分配次数:内存重分配就是说在修改字符串时,由于内存空间的不足或者是超出了,需要对执行内存的重分配操作,这种操作由于会涉及到内存,所以导致时间的成本高,所以我们应该尽量的避免内存重分配。而在 SDS 就是有 len 和 free 这两个属性,可以使用优化策略来减少对内存重分配次数。
List 类型的介绍与使用场景
List 类型说白了就是一个链表,插入元素进去后是有序排列的,value 值是可以重复的,可以通过对应的下标获取对应的 value 值,链表的左右两边都能进行插入和删除数据。在插入时,如果该键并不存在,那么 Redis 将为该键创建一个新的链表。与此相反,如果这个链表中的所有元素都被删除,那么该键也会被删除掉。
应用场景:简单队列、最新评论列表、非实时排行榜:定时计算榜单,如手机日销榜单
List 的常用命令
1. # lpush 将一个或多个值插入到列表头部
lpush phone:rank:daily iphone6
2. # rpop 移除并获取列表的最后一个元素
rpor phone:rank:daily
3. # llen 获取列表长度
llen phone:rank:daily
4. # lrange 获取 key 对应的 list 的指定下标范围元素,其中 0 表示列表的第一个元素,- 1 表示获取列表的所有元素
lrange phone:rank:daily 0 -1
5. # rpush 在 key 对应的 list 尾部添加一个元素
rpush phone:rank:daily xiaodi
6. # lpop 从 key 对应的 List 的尾部删除一个元素,并返回该元素
lpop phone:rank:daily
7. # bropo 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
brpop phone:rank:daily 20
8. # lrem 移除元素
lrem phone:rank:daily 2 a
List 的内部结构(内部结构为深入探究)
上面了解了 List 的常用命令的使用,我们现在就来看下 list 的底层结构。
List 有两种实现方式
压缩链表 (ziplist):是 Redis 为了节省内存空间而开发的,它是特殊编码的连续内存块而组成的一个顺序数据结构,一个压缩列表 可以包含许多任意的节点,它的重点是内存连续!
双端链表:使用 prev 和 next 这两个指针,是可以从前向后也可以从后向前来实现 lpush 和 rpush 这些指令。因为是链表,所以也导致了 lindex 指令获取某个元素需要遍历链表才能获取得到。时间复杂度 O(n)。
当列表的对象同时满足下述两个条件时,列表对象采用压缩链表编码:
(1)列表对象保存的所有元素长度都小于 64 个字节;
(2)列表元素所保存的元素个数小于 512 个
在 Redis3.2 之后,采用的是快速链表 -quicklist。quicklist 是一个双向链表,并且它还是一个有 ziplist 特性的双向链表,就是说 quicklist 每个节点都是 ziplist。这个快速链表结合了两者的优点。
Hash 类型的介绍与使用场景
Redis 中的 Hash 类型是一个 String 类型的 field 和 value 的映射表,Hash 特别适合用于存储对象,Hash 类似于 Map 结构。因为在 Redis 里,Hash 又是另外的一种键值对结构,而 Redis 本身就是 key-value 类型,所以这个 Hash 结构是套在了 Redis 下的 value 里。
下面说说 Hash 的底层数据结构:
一种是 ziplist,当存储的数据超过所配置的数量大小时就是转成 Hashtable 这种结构。这种转换会比较消耗性能,所以尽量少用这种转换操作。
另一种就是 hashtable,这种结构的时间复杂度为 O(1),但是会比较消耗内存空间。
对于 Hash 在 Redis 中的应用场景:购物车、用户个人信息、商品详情的实现
Hash 的常用命令
1. # hset 设置 key 指定的哈希集指定字段的值
hset product:detail:1 title iphone11
2. # hget 返回 key 指定的哈希集中该字段所关联的值
hget product:detail:1 title
3. # hgetall 返回 key 指定的哈希集中所有的字段和值
hegetall product:detail:1
4. # hdel 从 key 指定的哈希集中移除指定的域
hdel product:detail:1 title
5. # hexists 返回 hash 里面的 field 是否存在
hexists product:detail:1 title (存在返回 1,不存在返回 0)
6. # hincrby 增加 key 指定的哈希集中的指定字段的数值,如果是 - 1 则是递减
hincrby product:detail:1 key 1 (对 key 里的 value 值进行递增或递减)
7. # hmset 设置 key 指定的哈希集中指定字段的值
hmset product:detail:2 title xiaomi price 1000 stock 10
8. # hmget 返回 key 指定的哈希集中指定字段的值
hmget product:detail:2 title price
注意:每个 Hash 可以存储 232- 1 键值对
Set 类型的介绍与使用场景
Redis 中的 Set 类型是一个集合,集合的概念是一堆不重复的组合。利用 Redis 提供的 Set 数据结构可以存储一些集合性的数据。因为 Redis 很友好的为集合提供了求集、并集、差集等操作 (PS: 不懂的同学可以问下以前的数学老师哦~ 哈哈哈哈),那么就可以非常方便的实现共同关注、共同喜好等功能。对上面的集合操作,你还可以使用不同的命令选择奖结果返回给客户端还是存集合到一个新的集合中。
Redis 中 Set 应用场景:去重、社交应用关注(粉丝,共同好友)、统计网站 PV(UV、IP)大数据里面的用户画像标签集合
Set 的常用命令
1. # sadd 添加一个或多个指定的元素到集合中,如果指定的元素已经在集合 key 中则忽略
sadd user:tags female
sadd user:tags bmw
2. # scard 返回集合存储的 key 的基数(集合元素的数量) scard user:tags
3. # sdiff 返回的集合元素是第一个 key 集合与后面所有 key 集合的差集
sdiff user:tags:1 user:tags:2
4. # sinter 返回指定所有的集合的成员的交集
sinter user:tags:1 user:tags:2
5. # sismember 返回成员是否有存储的集合 key 的成员
sismember user:tags:1 bmw
6. # srem 在集合中移除指定的元素,如果指定元素不是 key 集合中的则忽略
srem user:tags:1 bmw
7. # sunion 返回给定的多个集合的并集所有的成员
sunion user:tags:1 user:tags:2
SortedSet 类型的介绍与使用场景
和 Set 相比,SortedSet 是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排序,比如存储一个存储班上同学成绩的 SortedSet 集合,该集合 value 可以设为同学的学号,然而 score 就可以是考试成绩。这样才插入数据的时候,就已经为数据进行了排序。另外,SortedSet 还可以用来做带权重的队列。
应用场景:实时排行榜、优先级任务(队列)、朋友圈(文章)点赞 - 取消
SortedSet 中跳跃表的介绍
跳跃表实则是一个链表,在传统的链表中想要查找一个元素就要从最原始的地方开始查找,直到查找到该元素。在跳跃表中呢,它会把链表进行抽层,抽层的时候会隔几个元素分为一个节点,抽层之后也是一条链表,节点会变少了。如下图所示,当要寻找元素 78 时,如果是寻常的链表就会从左往右挨个查询,这时查询了 8 次才能找带该元素。当使用跳跃表后,从第二层的开始出发,当查询到 79 这个节点时发现没有 78,则返回到 57 这个节点再返回第一层去寻找该元素。
SortedSet 的常用命令
1.# zadd 向有序集合里添加一个或者多个成员,或者更新已存在成员的分数
zadd video:rank 90 springcloud
zadd video:rank 80 springboot
zadd video:rank 50 redis
2.# zcard 获取有序集合的成员数
zcard video:rank
3.# zcount 计算在有序集合中指定的区间分数的成员数
zcount video:rank 0 60
4.# zincrby 在有序集合中对指定成员的分数加上增量
zincrby video:rank 2 springcloud
5.# zrange 通过索引区间返回有序集合指定内的成员,成员位置分数按(从小到大排序) zrange voideo:rank 0 -1
zrange voideo:rank 0 -1 withscores(返回分数)
6.# zrevrange 通过索引集合中指定成员的排名,其中有序集合成员按 score 值递增(从大到小排序) zrevrange voideo:rank 0 -1
7.# zrevrank 返回有序集合中指定的成员排名,有序集合成员按分数递减(从大到小排序) zrevrank voideo:rank springcloud
8.# zrank 返回有序集 key 中成员 member 的排名,其中有序集成员按 score 值递增(从小到大排序) zrank voideo:rank
9.# zrem 移除有序集合中的一个或者多个成员
zrem voideo:rank redis
10.# zscore 返回有序集合中的成员分数值
zscore voideo:rank springcloud
到此,相信大家对“常见 Redis 数据结构有哪些”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!