Redis(三):常见数据类型:List、Set、Zset

news2024/11/25 22:37:31

List 列表

列表类型是用来存储多个有序的字符串,

如图:

a、b、c、d、e 五个元素从左到右组成 了⼀个有序的列表,列表中的每个字符串称为元素(element),⼀个列表最多可以存储个元素。在 Redis 中,可以对列表两端插⼊(push)和弹出(pop),还可以获取指定范围的元素列表、 获取指定索引下标的元素等
列表是⼀种⽐较灵活的数据结构,它可以充当栈和队列的⻆⾊,在实际开发上有很多应⽤场景

Redis列表(Lists)类型的特点如下:

  1. 有序性:Redis列表是按照插入顺序来保存元素的。

  2. 可重复性:Redis列表中的元素可以重复。

  3. 长度可变性:Redis列表可以动态增长和缩小,可以随时添加或删除元素。

  4. 支持左右两端插入和删除操作:Redis列表提供了从左端或右端插入和删除元素的操作,可以方便地实现队列和栈。

  5. 支持范围操作:Redis列表提供了类似于数组的下标范围操作,可以获取指定范围内的元素。

  6. 适合存储有序数据:Redis列表适合存储有序数据,如消息队列、最新消息列表、日志记录等。

总之,Redis列表是一种非常灵活的数据结构,可以用于各种不同的场景,具有很高的实用价值。

Redis基本命令:

  1. LPUSH key value1 [value2 ...] - 在列表左边插入一个或多个元素
  2. RPUSH key value1 [value2 ...] - 在列表右边插入一个或多个元素
  3. LPOP key - 移除并返回列表最左边的元素
  4. RPOP key - 移除并返回列表最右边的元素
  5. LINDEX key index - 返回列表中指定索引位置的元素
  6. LLEN key - 返回列表的长度
  7. LRANGE key start stop - 返回列表中指定范围内的元素
  8. LREM key count value - 移除列表中指定数量的元素
  9. LTRIM key start stop - 保留列表中指定范围内的元素,其它元素均被删除
  10. BLPOP key [key ...] timeout - 阻塞并等待列表最左边的元素,并在超时时间内返回结果
  11. BRPOP key [key ...] timeout - 阻塞并等待列表最右边的元素,并在超时时间内返回结果

从这里我们可以发现,每个基本类型中基本命令开头必带有类型的首字母,但是在 List 中发现首字母不仅只有 L 还有 R;

原因在于: list 是一个双向链表,既可以头插头删,也可以尾插尾删;

L 代表 Left         R 代表 Right 

不只是 L 和 R ;这里居然还有 B 开头的。

 这是我自己记的笔记:百度网盘 ,可以查看命令比较具体的细节

BLPOP:

B 代表 Block 阻塞,L 表示 Left ,这个命令就意味着:阻塞并等待列表最左边的元素,并在超时时间内返回结果

返回值为:取出的元素或者 nil。

内部编码

列表类型的内部编码有两种:

  1. ziplist(压缩列表):当列表的元素个数⼩于 list-max-ziplist-entries 配置(默认 512 个),同时列表中每个元素的⻓度都⼩于 list-max-ziplist-value 配置(默认 64 字节)时,Redis 会选⽤ziplist 来作为列表的内部编码实现来减少内存消耗
  2. linkedlist(链表):当列表类型⽆法满⾜ ziplist 的条件时,Redis 会使⽤ linkedlist 作为列表的内部实现。

当元素个数较少并没有大元素时,内部编码为 ziplist:

1  127.0.0.1:6379> rpush listkey e1 e2 e3
2  OK
3  127.0.0.1:6379> object encoding listkey
4  "ziplist"
当元素个数超过 512 时,内部编码为 linkedlist:
1  127.0.0.1:6379> rpush listkey e1 e2 e3 ... 省略 e512 e513
2  OK
3  127.0.0.1:6379> object encoding listkey
4  "linkedlist"
当某个元素的⻓度超过 64 字节时,内部编码为 linkedlist:
1  127.0.0.1:6379> rpush listkey "one string is bigger than 64 bytes ... 省略 ..."
2  OK
3  127.0.0.1:6379> object encoding listkey
4  "linkedlist"

这个所谓超出某个数字并非唯一的,同样可以在 .conf  配置文件中修改的。

使用场景

消息队列

Redis 可以使用 lpush + brpop 组合命令实现生产者-消费者模型队列,生产者客户端使用 lpush 从列表左侧插入元素,多个消费者客户端使用 brpop 命令阻塞式地从队列中 “争抢” 队首元素。通过多个客户端来保证消费的负载均衡和高可用。

微博 Timeline

每个⽤⼾都有属于⾃⼰的 Timeline(微博列表),现需要分⻚展⽰⽂章列表。此时可以考虑使⽤
列表,因为列表不但是有序的,同时⽀持按照索引范围获取元素。

1)每篇微博使⽤哈希结构存储,例如微博中 3 个属性:title、timestamp、content:
hmset mblog: 1 title xx timestamp 1476536196 content xxxxx
...
hmset mblog:n title xx timestamp 1476536196 content xxxxx
2)向⽤⼾ Timeline 添加微博,user:<uid>:mblogs 作为微博的键:
lpush user: 1 :mblogs mblog: 1 mblog: 3
...
lpush user:k:mblogs mblog: 9
3)分⻚获取⽤⼾的 Timeline,例如获取⽤⼾ 1 的前 10 篇微博:
keylist = lrange user: 1 :mblogs 0 9
for key in keylist {
        hgetall key
}
此⽅案在实际中可能存在两个问题:
  1. 1 + n 问题。即如果每次分⻚获取的微博个数较多,需要执⾏多次 hgetall 操作,此时可以考虑使⽤pipeline(流⽔线)模式批量提交命令,或者微博不采⽤哈希类型,⽽是使⽤序列化的字符串类型,使⽤ mget 获取。
  2. 分裂获取⽂章时,lrange 在列表两端表现较好,获取列表中间的元素表现较差,此时可以考虑将列表做拆分。

注意:

同侧存取(lpush + lpop 或者 rpush + rpop)为栈
异侧存取(lpush + rpop 或者 rpush + lpop)为队列

Set 类型

集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是:
1. 集合中元素之间是⽆序的
2. 集合中元素不允许重复

如图:

⼀个集合中最多可以存储 2^32 - 1 个元素。Redis 除了⽀持 集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集,合理地使⽤好集合类型,能在实 际开发中解决很多问题。

基本命令

  1. SADD key member1 [member2]:向集合中添加一个或多个元素
  2. SCARD key:获取集合中元素数量
  3. SDIFF key1 [key2]:返回第一个集合与其它集合的差集
  4. SDIFFSTORE destination key1 [key2]:将第一个集合与其它集合的差集存储到一个新的集合中
  5. SINTER key1 [key2]:返回第一个集合与其它集合的交集
  6. SINTERSTORE destination key1 [key2]:将第一个集合与其它集合的交集存储到一个新的集合中
  7. SISMEMBER key member:判断元素是否在集合中
  8. SMEMBERS key:获取集合中所有元素
  9. SMOVE source destination member:将一个元素从一个集合中移动到另一个集合中
  10. SPOP key [count]:随机移除并返回集合中一个或多个元素
  11. SRANDMEMBER key [count]:随机获取集合中一个或多个元素
  12. SREM key member1 [member2]:从集合中移除一个或多个元素
  13. SUNION key1 [key2]:返回多个集合的并集
  14. SUNIONSTORE destination key1 [key2]:将多个集合的并集存储到一个新的集合中

 这是我自己记的笔记:百度网盘 ,可以查看命令比较具体的细节

内部编码

集合类型的内部编码同样也分两种:

  1. intset(整数集合):当集合中的元素都是整数并且元素的个数⼩于 set-max-intset-entries 配置 (默认 512 个)时,Redis 会选⽤ intset 来作为集合的内部实现,从⽽减少内存的使⽤。 
  2. hashtable(哈希表):当集合类型⽆法满⾜ intset 的条件时,Redis 会使⽤ hashtable 作为集合的内部实现。
1)当元素个数较少并且都为整数时,内部编码为 intset:
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 4
127.0.0.1:6379> object encoding setkey
"intset"
2)当元素个数超过 512 个,内部编码为 hashtable:
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 513
127.0.0.1:6379> object encoding setkey
"hashtable"
3)当存在元素不是整数时,内部编码为 hashtable:
127.0.0.1:6379> sadd setkey a
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"

同样的,这里所谓超出某个数字并非唯一的,同样可以在 .conf  配置文件中修改的。

使用场景

集合类型⽐较典型的使⽤场景是标签(tag)。例如 A ⽤⼾对娱乐、体育板块⽐较感兴趣,B ⽤⼾ 对历史、新闻⽐较感兴趣,这些兴趣点可以被抽象为标签。有了这些数据就可以得到喜欢同⼀个标签的⼈,以及⽤⼾的共同喜好的标签,这些数据对于增强⽤⼾体验和⽤⼾黏度都⾮常有帮助。 例如⼀个电⼦商务⽹站会对不同标签的⽤⼾做不同的产品推荐。

ZSet 类型

有序集合相对于字符串、列表、哈希、集合来说会有⼀些陌⽣。它保留了集合不能有重复成员的
特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关 联,着使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个分数。

基本命令

Redis中ZSet类型是有序集合,每个元素都有一个对应的分数(score)。以下是ZSet类型的基本命令:

  1. ZADD key score member:向有序集合添加一个或多个成员,或者更新已存在成员的分数
  2. ZCARD key:获取有序集合的元素数量
  3. ZCOUNT key min max:获取有序集合中分数范围内的成员数量
  4. ZINCRBY key increment member:对有序集合中指定成员的分数增加increment
  5. ZRANK key member:获取有序集合中指定成员的排名(从小到大)
  6. ZREVRANK key member:获取有序集合中指定成员的排名(从大到小)
  7. ZSCORE key member:获取有序集合中指定成员的分数
  8. ZRANGE key start stop [WITHSCORES]:获取有序集合中指定排名范围内的成员(从小到大),如果WITHSCORES选项被指定,则同时返回成员的分数
  9. ZREVRANGE key start stop [WITHSCORES]:获取有序集合中指定排名范围内的成员(从大到小)
  10. ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]:获取有序集合中指定分数范围内的成员,如果WITHSCORES选项被指定,则同时返回成员的分数,如果LIMIT选项被指定,则返回指定数量的成员(从小到大)
  11. ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]:获取有序集合中指定分数范围内的成员,如果WITHSCORES选项被指定,则同时返回成员的分数,如果LIMIT选项被指定,则返回指定数量的成员(从大到小)
  12. ZREM key member:从有序集合中移除一个或多个成员
  13. ZREMRENGEByRANK key start stop:移除有序集合中指定排名范围内的成员(从小到大)
  14. ZREMRENGEBySCORE key min max:移除有序集合中指定分数范围内的成员
  15. ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]:计算给定numkeys个有序集合的并集,并将结果保存到destination,如果WEIGHTS选项被指定,则计算时使用指定权重,如果AGGREGATE选项被指定,则使用指定聚合方式

 这是我自己记的笔记:百度网盘 ,可以查看命令比较具体的细节

内部编码

有序集合类型的内部编码有两种:

  1. ziplist(压缩列表):当有序集合的元素个数⼩于 zset-max-ziplist-entries 配置(默认 128 个),同时每个元素的值都⼩于 zset-max-ziplist-value 配置(默认 64 字节)时,Redis 会⽤ ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使⽤。
  2. skiplist(跳表):当 ziplist 条件不满⾜时,有序集合会使⽤ skiplist 作为内部实现,因为此时
    ziplist 的操作效率会下降。
1)当元素个数较少且每个元素较⼩时,内部编码为 ziplist:
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3
(integer) 3
127.0.0.1:6379> object encoding zsetkey
"ziplist"
2)当元素个数超过 128 个,内部编码 skiplist:
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3 ... 省略 ... 82 e129
(integer) 129
127.0.0.1:6379> object encoding zsetkey
"skiplist"
3)当某个元素⼤于 64 字节时,内部编码 skiplist:
127.0.0.1:6379> zadd zsetkey 50 "one string bigger than 64 bytes ... 省略 ..."
(integer) 1
127.0.0.1:6379> object encoding zsetkey
"skiplist"

使用场景

有序集合⽐较典型的使⽤场景就是排⾏榜系统。例如常⻅的⽹站上的热榜信息,榜单的维度可能
是多⽅⾯的:按照时间、按照阅读量、按照点赞量。本例中我们使⽤点赞数这个维度,维护每天的热榜:

1)添加⽤⼾赞数
例如⽤⼾ james 发布了⼀篇⽂章,并获得 3 个赞,可以使⽤有序集合的 zadd 和 zincrby 功能:
zadd user:ranking: 2022 - 03 - 15 3 james
之后如果再获得赞,可以使⽤ zincrby:
zincrby user:ranking: 2022 - 03 - 15 1 james
2)取消⽤⼾赞数
由于各种原因(例如⽤⼾注销、⽤⼾作弊等)需要将⽤⼾删除,此时需要将⽤⼾从榜单中删除掉,可以使⽤ zrem。例如删除成员 tom:
zrem user:ranking: 2022 - 03 - 15 tom
3)展⽰获取赞数最多的 10 个⽤⼾
此功能使⽤ zrevrange 命令实现:
zrevrangebyrank user:ranking: 2022 - 03 - 15 0 9

渐进式遍历

Redis 使⽤ scan 命令进⾏渐进式遍历键,进⽽解决直接使⽤ keys 获取键时可能出现的阻塞问
题。每次 scan 命令的时间复杂度是 O(1),但是要完整地完成所有键的遍历,需要执⾏多次 scan。

我来演示一下就明白我再说啥了。

我们现在一共存在了 11 个 key,那么现在我要使用 scan 渐进式遍历。

除了 scan 以外,Redis ⾯向哈希类型、集合类型、有序集合类型分别提供了 hscan、sscan、zscan 命 令,它们的⽤法和 scan 基本类似,感兴趣的读者可以⾃⾏做扩展学习。

渐进性遍历 scan 虽然解决了阻塞的问题,但如果在遍历期间键有所变化(增加、修改、删
除),可能导致遍历时键的重复遍历或者遗漏,这点务必在实际开发中考虑。

本章节到此就结束了,具体的命令还是建议去看官网,当然也可以和 scan 一样有更优的解,不听从我的建议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1288567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剪刀石头布游戏

csdn问答社区的一道题目&#xff0c;题目描述都像一篇论文了&#xff0c;界面设置不敢恭维&#xff0c;不过也算是可练手工程。 (笔记模板由python脚本于2023年12月05日 22:15:03创建&#xff0c;本篇笔记适合熟悉Python字典、列表、字符串的coder翻阅) 【学习的细节是欢悦的历…

军大衣方歇 东北大花袄正当时

聊起最近军大衣和各式棉服的销量&#xff0c;丽亮服饰的陈先生正忙于打包&#xff0c;他说现在订购的军大衣最早也得20天后才能到货&#xff0c;除了零散的几件&#xff0c;市面基本都处于断货状态。 做了十多年服装生意&#xff0c;陈先生也没想到军大衣会从自己的父辈&#x…

【Vue】element组件不显示问题

使用element组件但不显示 不显示的原因&#xff1a;&#xff08;未引入element-ui&#xff09; 首先在控制台输入 npm i element-ui 进行安装 安装完之后&#xff0c;再去main.js配置element-ui组件库 import ElementUI from element-ui import element-ui/lib/theme-chal…

MYSQL数据库中运行SQL文件报错

报错显示 当使用mysql数据库运行SQL文件报错时 [Err] 1273 - Unknown collation: utf8mb4_0900_ai_ci 报错原因 版本高低问题&#xff0c;一个是5.7版本&#xff0c;一个是8.0版本生成转储文件的数据库版本为8.0,要导入sql文件的数据库版本为5.7,因为是高版本导入到低版本&a…

.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection(未完待续)

文章目录 前言什么是依赖注入C# 使用依赖注入框架介绍 Microsoft.Extensions.DependencyInjectionNuget安装简单单例使用打印结果 暂时结束 前言 依赖注入是一个非常重要的编程思想&#xff0c;就和面向过程和面向对象一样&#xff0c;IOC和控制反转是一种解耦的编程思想。 什…

小满CRM与畅捷通T+系统数据集成方案分享

小满CRM与畅捷通T系统数据集成方案分享 在当前数字化浪潮的推动下&#xff0c;越来越多的企业选择使用各种信息化系统来提高工作效率和管理水平。其中&#xff0c;小满CRM和畅捷通T系统成为了广受企业欢迎的两个主流系统。然而&#xff0c;企业在使用这两个系统的过程中&#…

【数据分享】1990-2022年我国省市县三级的各类土地覆盖面积

土地覆盖数据是我们在各项研究中经常使用的数据。土地覆盖数据可以帮助我们确定哪儿是建设用地&#xff0c;哪儿是水域&#xff0c;哪儿是农田等&#xff01;我们之前分享了武汉大学杨杰和黄昕教授发布的1990-2022年中国30米年度土地覆盖栅格数据&#xff08;可查看之前的文章获…

在微信小程序中如何改变默认打开的页面

在微信小程序中&#xff0c;在我们编写页面的时候&#xff0c;可能会在重新渲染的时候导致页面跳转到默认打开的页面上&#xff0c;为了提升用户的一个体验&#xff0c;我们可以设置一些内容来修改小程序默认打开的页面&#xff0c;提升开发者的开发体验。 当我们打开一个微信…

CentOS中安装数据库

1.下载 网址&#xff1a;https://dev.mysql.com/downloads/mysql/ 按如图选择&#xff0c;然后点击Download 这里它让我们登录&#xff0c;我们直接选择不登录&#xff0c;直接下载 2.关闭防火墙 systemctl disable firewalld3.正式安装 切换到/usr/local下 cd /usr/l…

扰动观测器(Disturbance observer)

干扰观测器是将外部干扰以及模型参数变化造成的实际对象与名义模型之间的差异等效到控制输入端&#xff0c;即观测出等效干扰。并在控制中引入等效的补偿&#xff0c;实现对干扰的完全控制。 参考文献&#xff1a; 聊聊控制领域的干扰观测器(DOB) - 知乎1. 简介1987 年日本学者…

[Python从零到壹] 七十三.图像识别及经典案例篇之图像去雾ACE算法和暗通道先验去雾算法实现

十月太忙&#xff0c;还是写一篇吧&#xff01;祝大家1024节日快乐O(∩_∩)O 欢迎大家来到“Python从零到壹”&#xff0c;在这里我将分享约200篇Python系列文章&#xff0c;带大家一起去学习和玩耍&#xff0c;看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经…

打开率高的开发信主题?邮件的标题怎么写?

如何写高点击率的开发信主题&#xff1f;推荐的邮件标题模板&#xff1f; 一封高效的开发信可以是你争取客户的第一步。但是&#xff0c;要让你的邮件在收件人的收件箱中引起关注并被打开&#xff0c;你需要选择一个吸引人的主题。蜂邮将介绍一些打开率高的开发信主题&#xf…

安卓设备发送指令操作蓝牙打印机打印信息

引用安卓蓝牙设备驱动 蓝牙打印指令测试下载https://download.csdn.net/download/u014596302/16231571 示例运行页面 使用起步wex5 - 3.9 编辑器打开 .w文件 下载 所需插件及驱动 wex5 开发软件http://www.justep.com/wex5downloads/ 安卓蓝牙驱动 cordova 版https://down…

第74讲:MySQL数据库InnoDB存储引擎事务:Redo Log与Undo Logo的核心概念

文章目录 1.InnoDB引擎中的逻辑存储结构2.事务的基本概念3.Redo log的核心概念3.1.什么是Redo log3.2.如果没有redo log面临的问题3.3.使用redo log之后是怎样的流程 4.Undo log的核心概念 1.InnoDB引擎中的逻辑存储结构 InnoDB存储引擎的逻辑结构分为以下几层&#xff1a; Ta…

Python 对中文名称逐字按字母表进行排序并输出

使用场景 代码适用于需要对中文名称进行排序并规范化输出的情景&#xff0c;具体为处理一个包含中文姓名的文本文件&#xff0c;按姓名的拼音首字母进行排序&#xff0c;并以规范的格式输出。 排序规则&#xff1a; 将名称按照姓氏首字母A-Z的次序&#xff0c;进行排序&#x…

15+铁死亡超高分推荐,快来码思路

今天给同学们分享一篇生信文章“Polydopamine Nanoparticles Targeting Ferroptosis Mitigate Intervertebral Disc Degeneration Via Reactive Oxygen Species Depletion, Iron Ions Chelation, and GPX4 Ubiquitination Suppression”&#xff0c;这篇文章发表在Adv Sci (Wei…

【漏洞复现】狮子鱼任意文件上传漏洞

漏洞描述 狮子鱼CMS(Content Management System)是一种网站管理系统,旨在帮助用户更轻松地创建和管理网站。它具有用户友好的界面和丰富的功能,包括页面管理、博客、新闻、产品展示等。 狮子鱼CMS使用简单直观的管理界面,使得网站所有者可以方便地进行内容的发布、管理和…

Python插件 - 动态 简单账表 通过SQL存储过程输出列实现动态展示

第一步 新建一个简单账表加上表头标签 第二步 新建一个过滤框 第三步 修改过滤窗口标识 第四步 注册插件 python代码实现 import clr clr.AddReference("System") clr.AddReference("System.Core") clr.AddReference("Kingdee.BOS") clr.AddRe…

思腾云计算中心 | 5千平米超大空间,基础设施完善,提供裸金属GPU算力租赁业务

2021年&#xff0c;思腾合力全资收购包头市易慧信息科技有限公司&#xff0c;正式开启云计算业务。思腾云计算中心占地2400平米&#xff0c;位于包头市稀土高新区&#xff0c;毗邻多家知名企业&#xff0c;地理位置优越&#xff0c;交通便利&#xff0c;是区内重要的信息化产业…

数据结构实验—宿舍管理系统(C,Python,Java三种代码版本)

目录 实验课程 实验内容 数据结构类型定义 模块划分 &#xff08;C语言&#xff09;详细代码设计 &#xff08;python&#xff09;详细代码设计 &#xff08;Java&#xff09;详细代码设计 测试数据及结果 实验总结 实验课程 课程名称&#xff1a;数据结构 实验名称&…