| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 2 万字 + 20张图| 细说 Redis 九种数据类型和应用场景 -> 正文阅读 |
|
[大数据]2 万字 + 20张图| 细说 Redis 九种数据类型和应用场景 |
大家好,我是小林。 我们都知道 Redis 提供了丰富的数据类型,常见的有五种:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。 随着 Redis 版本的更新,后面又支持了四种数据类型: BitMap(2.2 版新增)、HyperLogLog(2.8 版新增)、GEO(3.2 版新增)、Stream(5.0 版新增)。 每种数据对象都各自的应用场景,你能说出它们各自的应用场景吗? 面试过程中,这个问题也很常被问到,又比如会举例一个应用场景来问你,让你说使用哪种 Redis 数据类型来实现。 所以,这次我们就来学习 Redis 数据类型的使用以及应用场景。
String介绍String 是最基本的 key-value 结构,key 是唯一标识,value 是具体的值,value其实不仅是字符串, 也可以是数字(整数或浮点数),value 最多可以容纳的数据长度是 内部实现String 类型的底层的数据结构实现主要是 int 和 SDS(简单动态字符串)。 SDS 和我们认识的 C 字符串不太一样,之所以没有使用 C 语言的字符串表示,因为 SDS 相比于 C 的原生字符串:
字符串对象的内部编码(encoding)有 3 种 :int、raw和 embstr。 如果一个字符串对象保存的是整数值,并且这个整数值可以用 如果字符串对象保存的是一个字符串,并且这个字符申的长度小于等于 32 字节,那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串,并将对象的编码设置为 如果字符串对象保存的是一个字符串,并且这个字符串的长度大于 32 字节,那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串,并将对象的编码设置为 可以看到
但是 embstr 也有缺点的:
常用指令普通字符串的基本操作:
批量设置 :
计数器(字符串的内容为整数的时候可以使用):
过期(默认为永不过期):
不存在就插入:
应用场景缓存对象使用 String 来缓存对象有两种方式:
常规计数因为 Redis 处理命令是单线程,所以执行命令的过程是原子的。因此 String 数据类型适合计数场景,比如计算访问次数、点赞、转发、库存数量等等。 比如计算文章的阅读量:
分布式锁SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁:
一般而言,还会对分布式锁加上过期时间,分布式锁的命令如下:
而解锁的过程就是将 lock_key 键删除,但不能乱删,要保证执行操作的客户端就是加锁的客户端。所以,解锁的时候,我们要先判断锁的 unique_value 是否为加锁客户端,是的话,才将 lock_key 键删除。 可以看到,解锁是有两个操作,这时就需要 Lua 脚本来保证解锁的原子性,因为 Redis 在执行 Lua 脚本时,可以以原子性的方式执行,保证了锁释放操作的原子性。
这样一来,就通过使用 SET 命令和 Lua 脚本在 Redis 单节点上完成了分布式锁的加锁和解锁。 List介绍List 列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。 列表的最大长度为 内部实现List 类型的底层数据结构是由双向链表或压缩列表实现的:
但是在 Redis 3.2 版本之后,List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表。 常用命令
应用场景消息队列消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息和保证消息可靠性。 Redis 的 List 和 Stream 两种数据类型,就可以满足消息队列的这三个需求。我们先来了解下基于 List 的消息队列实现方法,后面在介绍 Stream 数据类型时候,在详细说说 Stream。 1、如何满足消息保序需求? List 本身就是按先进先出的顺序对数据进行存取的,所以,如果使用 List 作为消息队列保存消息的话,就已经能满足消息保序的需求了。 List 可以使用 LPUSH + RPOP (或者反过来,RPUSH+LPOP)命令实现消息队列。
不过,在消费者读取数据时,有一个潜在的性能风险点。 在生产者往 List 中写入数据时,List 并不会主动地通知消费者有新消息写入,如果消费者想要及时处理消息,就需要在程序中不停地调用 所以,即使没有新消息写入List,消费者也要不停地调用 RPOP 命令,这就会导致消费者程序的 CPU 一直消耗在执行 RPOP 命令上,带来不必要的性能损失。 为了解决这个问题,Redis提供了 BRPOP 命令。BRPOP命令也称为阻塞式读取,客户端在没有读到队列数据时,自动阻塞,直到有新的数据写入队列,再开始读取新数据。和消费者程序自己不停地调用RPOP命令相比,这种方式能节省CPU开销。 2、如何处理重复的消息? 消费者要实现重复消息的判断,需要 2 个方面的要求:
但是 List 并不会为每个消息生成 ID 号,所以我们需要自行为每个消息生成一个全局唯一ID,生成之后,我们在用 LPUSH 命令把消息插入 List 时,需要在消息中包含这个全局唯一 ID。 例如,我们执行以下命令,就把一条全局 ID 为 111000102、库存量为 99 的消息插入了消息队列:
3、如何保证消息可靠性? 当消费者程序从 List 中读取一条消息后,List 就不会再留存这条消息了。所以,如果消费者程序在处理消息的过程出现了故障或宕机,就会导致消息没有处理完成,那么,消费者程序再次启动后,就没法再次从 List 中读取消息了。 为了留存消息,List 类型提供了 这样一来,如果消费者程序读了消息但没能正常处理,等它重启后,就可以从备份 List 中重新读取消息并进行处理了。 好了,到这里可以知道基于 List 类型的消息队列,满足消息队列的三大需求(消息保序、处理重复的消息和保证消息可靠性)。
但是,在用 List 做消息队列时,如果生产者消息发送很快,而消费者处理消息的速度比较慢,这就导致 List 中的消息越积越多,给 Redis 的内存带来很大压力。 要解决这个问题,就要启动多个消费者程序组成一个消费组,一起分担处理 List 中的消息。但是,List 类型并不支持消费组的实现。 这就要说起 Redis 从 5.0 版本开始提供的 Stream 数据类型了,Stream 同样能够满足消息队列的三大需求,而且它还支持「消费组」形式的消息读取。 Hash介绍Hash 是一个键值对(key - value)集合,其中 value 的形式入: Hash 与 String 对象的区别如下图所示: 内部实现Hash 类型的底层数据结构是由压缩列表或哈希表实现的:
在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。 常用命令
应用场景缓存对象Hash 类型的 (key,field, value) 的结构与对象的(对象id, 属性, 值)的结构相似,也可以用来存储对象。 我们以用户信息为例,它在关系型数据库中的结构是这样的: 我们可以使用如下命令,将用户对象的信息存储到 Hash 类型:
Redis Hash 存储其结构如下图: 在介绍 String 类型的应用场景时有所介绍,String + Json也是存储对象的一种方式,那么存储对象时,到底用 String + json 还是用 Hash 呢? 一般对象用 String + Json 存储,对象中某些频繁变化的属性可以考虑抽出来用 Hash 类型存储。 购物车以用户 id 为 key,商品 id 为 field,商品数量为 value,恰好构成了购物车的3个要素,如下图所示。 涉及的命令如下:
当前仅仅是将商品ID存储到了Redis 中,在回显商品具体信息的时候,还需要拿着商品 id 查询一次数据库,获取完整的商品的信息。 Set介绍Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。 一个集合最多可以存储 Set 类型和 List 类型的区别如下:
内部实现Set 类型的底层数据结构是由哈希表或整数集合实现的:
常用命令Set常用操作:
Set运算操作:
应用场景集合的主要几个特性,无序、不可重复、支持并交差等操作。 因此 Set 类型比较适合用来数据去重和保障数据的唯一性,还可以用来统计多个集合的交集、错集和并集等,当我们存储的数据是无序并且需要去重的情况下,比较适合使用集合类型进行存储。 但是要提醒你一下,这里有一个潜在的风险。Set 的差集、并集和交集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 实例阻塞。 在主从集群中,为了避免主库因为 Set 做聚合计算(交集、差集、并集)时导致主库被阻塞,我们可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端来完成聚合统计。 点赞Set 类型可以保证一个用户只能点一个赞,这里举例子一个场景,key 是文章id,value 是用户id。
获取 article:1 文章所有点赞用户 :
获取 article:1 文章的点赞用户数量:
判断用户
共同关注Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等。 key 可以是用户id,value 则是已关注的公众号的id。
给
验证某个公众号是否同时被
抽奖活动存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次。 key为抽奖活动名,value为员工名称,把所有员工名称放入抽奖箱 :
如果允许重复中奖,可以使用 SRANDMEMBER 命令。
如果不允许重复中奖,可以使用 SPOP 命令。
Zset介绍Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。 有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。 内部实现Zset 类型的底层数据结构是由压缩列表或跳表实现的:
在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。 常用命令Zset 常用操作:
Zset 运算操作(相比于 Set 类型,ZSet 类型没有支持差集运算):
应用场景Zset 类型(Sorted Set,有序集合) 可以根据元素的权重来排序,我们可以自己来决定每个元素的权重值。比如说,我们可以根据元素插入 Sorted Set 的时间确定权重值,先插入的元素权重小,后插入的元素权重大。 在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,可以优先考虑使用 Sorted Set。 排行榜有序集合比较典型的使用场景就是排行榜。例如学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名等。 我们以博文点赞排名为例,小林发表了五篇博文,分别获得赞为 200、40、100、50、150。
文章 arcticle:4 新增一个赞,可以使用 ZINCRBY 命令(为有序集合key中元素member的分值加上increment):
查看某篇文章的赞数,可以使用 ZSCORE 命令(返回有序集合key中元素个数):
获取小林文章赞数最多的 3 篇文章,可以使用 ZREVRANGE 命令(倒序获取有序集合 key 从start下标到stop下标的元素):
获取小林 100 赞到 200 赞的文章,可以使用 ZRANGEBYSCORE 命令(返回有序集合中指定分数区间内的成员,分数由低到高排序):
电话、姓名排序使用有序集合的 注意:不要在分数不一致的 SortSet 集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因为获取的结果会不准确。 1、电话排序 我们可以将电话号码存储到 SortSet 中,然后根据需要来获取号段:
获取所有号码:
获取 132 号段的号码:
获取132、133号段的号码:
2、姓名排序
获取所有人的名字:
获取名字中大写字母A开头的所有人:
获取名字中大写字母 C 到 Z 的所有人:
BitMap介绍Bitmap,即位图,是一串连续的二进制数组(0和1),可以通过偏移量(offset)定位元素。BitMap通过最小的单位bit来进行 由于 bit 是计算机中最小的单位,使用它进行储存将非常节省空间,特别适合一些数据量大且使用二值统计的场景。 内部实现Bitmap 本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型。 String 类型是会保存为二进制的字节数组,所以,Redis 就把字节数组的每个 bit 位利用起来,用来表示一个元素的二值状态,你可以把 Bitmap 看作是一个 bit 数组。 常用命令bitmap 基本操作:
bitmap 运算操作:
应用场景Bitmap 类型非常适合二值状态统计的场景,这里的二值状态就是指集合元素的取值就只有 0 和 1 两种,在记录海量数据时,Bitmap 能够有效地节省内存空间。 签到统计在签到打卡的场景中,我们只用记录签到(1)或未签到(0),所以它就是非常典型的二值状态。 签到统计时,每个用户一天的签到用 1 个 bit 位就能表示,一个月(假设是 31 天)的签到情况用 31 个 bit 位就可以,而一年的签到也只需要用 365 个 bit 位,根本不用太复杂的集合类型。 假设我们要统计 ID 100 的用户在 2022 年 6 月份的签到情况,就可以按照下面的步骤进行操作。 第一步,执行下面的命令,记录该用户 6 月 3 号已签到。
第二步,检查该用户 6 月 3 日是否签到。
第三步,统计该用户在 6 月份的签到次数。
这样,我们就知道该用户在 6 月份的签到情况了。
Redis 提供了 在默认情况下, 命令将检测整个位图, 用户可以通过可选的
需要注意的是,因为 offset 从 0 开始的,所以我们需要将返回的 value + 1 。 判断用户登陆态Bitmap 提供了 只需要一个 key = login_status 表示存储用户登陆状态集合数据, 将用户 ID 作为 offset,在线就设置为 1,下线设置 0。通过 假如我们要判断 ID = 10086 的用户的登陆情况: 第一步,执行以下指令,表示用户已登录。
第二步,检查该用户是否登陆,返回值 1 表示已登录。
第三步,登出,将 offset 对应的 value 设置成 0。
连续签到用户总数如何统计出这连续 7 天连续打卡用户总数呢? 我们把每天的日期作为 Bitmap 的 key,userId 作为 offset,若是打卡则将 offset 位置的 bit 设置成 1。 key 对应的集合的每个 bit 位的数据则是一个用户在该日期的打卡记录。 一共有 7 个这样的 Bitmap,如果我们能对这 7 个 Bitmap 的对应的 bit 位做 『与』运算。同样的 UserID offset 都是一样的,当一个 userID 在 7 个 Bitmap 对应对应的 offset 位置的 bit = 1 就说明该用户 7 天连续打卡。 结果保存到一个新 Bitmap 中,我们再通过 Redis 提供了
举个例子,比如将三个 bitmap 进行 AND 操作,并将结果保存到 destmap 中,接着对 destmap 执行 BITCOUNT 统计。
即使一天产生一个亿的数据,Bitmap 占用的内存也不大,大约占 12 MB 的内存(10^8/8/1024/1024),7 天的 Bitmap 的内存开销约为 84 MB。同时我们最好给 Bitmap 设置过期时间,让 Redis 删除过期的打卡数据,节省内存。 HyperLogLog介绍Redis HyperLogLog 是 Redis 2.8.9 版本新增的数据类型,是一种用于「统计基数」的数据集合类型,基数统计就是指统计一个集合中不重复的元素个数。但要注意,HyperLogLog 是统计规则是基于概率完成的,不是非常准确,标准误算率是 0.81%。 所以,简单来说 HyperLogLog 提供不精确的去重计数。 HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的内存空间总是固定的、并且是很小的。 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 这什么概念?举个例子给大家对比一下。 用 Java 语言来说,一般 long 类型占用 8 字节,而 1 字节有 8 位,即:1 byte = 8 bit,即 long 数据类型最大可以表示的数是: 内部实现HyperLogLog 的实现涉及到很多数学问题,太费脑子了,我也没有搞懂,如果你想了解一下,课下可以看看这个:HyperLogLog。 常见命令HyperLogLog 命令很少,就三个。
应用场景百万级网页 UV 计数Redis HyperLogLog 优势在于只需要花费 12 KB 内存,就可以计算接近 2^64 个元素的基数,和元素越多就越耗费内存的 Set 和 Hash 类型相比,HyperLogLog 就非常节省空间。 所以,非常适合统计百万级以上的网页 UV 的场景。 在统计 UV 时,你可以用 PFADD 命令(用于向 HyperLogLog 中添加新元素)把访问页面的每个用户都添加到 HyperLogLog 中。
接下来,就可以用 PFCOUNT 命令直接获得 page1 的 UV 值了,这个命令的作用就是返回 HyperLogLog 的统计结果。
不过,有一点需要你注意一下,HyperLogLog 的统计规则是基于概率完成的,所以它给出的统计结果是有一定误差的,标准误算率是 0.81%。 这也就意味着,你使用 HyperLogLog 统计的 UV 是 100 万,但实际的 UV 可能是 101 万。虽然误差率不算大,但是,如果你需要精确统计结果的话,最好还是继续用 Set 或 Hash 类型。 GEORedis GEO 是 Redis 3.2 版本新增的数据类型,主要用于存储地理位置信息,并对存储的信息进行操作。 在日常生活中,我们越来越依赖搜索“附近的餐馆”、在打车软件上叫车,这些都离不开基于位置信息服务(Location-Based Service,LBS)的应用。LBS 应用访问的数据是和人或物关联的一组经纬度信息,而且要能查询相邻的经纬度范围,GEO 就非常适合应用在 LBS 服务的场景中。 内部实现GEO 本身并没有设计新的底层数据结构,而是直接使用了 Sorted Set 集合类型。 GEO 类型使用 GeoHash 编码方法实现了经纬度到 Sorted Set 中元素权重分数的转换,这其中的两个关键机制就是「对二维地图做区间划分」和「对区间进行编码」。一组经纬度落在某个区间后,就用区间的编码值来表示,并把编码值作为 Sorted Set 元素的权重分数。 这样一来,我们就可以把经纬度保存到 Sorted Set 中,利用 Sorted Set 提供的“按权重进行有序范围查找”的特性,实现 LBS 服务中频繁使用的“搜索附近”的需求。 常用命令
应用场景滴滴叫车这里以滴滴叫车的场景为例,介绍下具体如何使用 GEO 命令:GEOADD 和 GEORADIUS 这两个命令。 假设车辆 ID 是 33,经纬度位置是(116.034579,39.030452),我们可以用一个 GEO 集合保存所有车辆的经纬度,集合 key 是 cars:locations。 执行下面的这个命令,就可以把 ID 号为 33 的车辆的当前经纬度位置存入 GEO 集合中:
当用户想要寻找自己附近的网约车时,LBS 应用就可以使用 GEORADIUS 命令。 例如,LBS 应用执行下面的命令时,Redis 会根据输入的用户的经纬度信息(116.054579,39.030452 ),查找以这个经纬度为中心的 5 公里内的车辆信息,并返回给 LBS 应用。
Stream介绍Redis Stream 是 Redis 5.0 版本新增加的数据类型,Redis 专门为消息队列设计的数据类型。 在前面介绍 List 类型实现的消息队列,有两个问题:1. 生产者需要自行实现全局唯一 ID;2. 不能以消费组形式消费数据。 基于 Stream 类型的消息队列就解决上面的问题,它不仅支持自动生成全局唯一 ID,而且支持以消费组形式消费数据。 常见命令Stream 消息队列操作命令:
应用场景消息队列生产者通过 XADD 命令插入一条消息:
插入成功后会返回全局唯一的 ID:“1654254953808-0”。消息的全局唯一 ID 由两部分组成:
消费者通过 XREAD 命令从消息队列中读取消息时,可以指定一个消息 ID,并从这个消息 ID 的下一条消息开始进行读取(注意是输入消息 ID 的下一条信息开始读取,不是查询输入ID的消息)。
如果想要实现阻塞读(当没有数据时,阻塞住),可以调用 XRAED 时设定 block 配置项,实现类似于 BRPOP 的阻塞读取操作。 比如,下面这命令,设置了 block 10000 的配置项,10000 的单位是毫秒,表明 XREAD 在读取最新消息时,如果没有消息到来,XREAD 将阻塞 10000 毫秒(即 10 秒),然后再返回。
前面介绍的这些操作 List 也支持的,接下来看看 Stream 特有的功能。 Stream 可以以使用 XGROUP 创建消费组,创建消费组之后,Stream 可以使用 XREADGROUP 命令让消费组内的消费者读取消息。 创建一个名为 group1 的消费组,这个消费组消费的消息队列是 mymq:
消费组 group1 内的消费者 consumer1 从 mymq 消息队列中读取所有消息的命令如下:
消息队列中的消息一旦被消费组里的一个消费者读取了,就不能再被该消费组内的其他消费者读取了。 比如说,我们执行完刚才的 XREADGROUP 命令后,再执行一次同样的命令,此时读到的就是空值了:
使用消费组的目的是让组内的多个消费者共同分担读取消息,所以,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分布的。 例如,我们执行下列命令,让 group2 中的 consumer1、2、3 各自读取一条消息。
Streams 会自动使用内部队列(也称为 PENDING List)留存消费组里每个消费者读取的消息,直到消费者使用 XACK 命令通知 Streams“消息已经处理完成”。 如果消费者没有成功处理消息,它就不会给 Streams 发送 XACK 命令,消息仍然会留存。此时,消费者可以在重启后,用 XPENDING 命令查看已读取、但尚未确认处理完成的消息。 例如,我们来查看一下 group2 中各个消费者已读取、但尚未确认的消息个数,命令如下:
如果想查看某个消费者具体读取了哪些数据,可以执行下面的命令:
可以看到,consumer2 已读取的消息的 ID 是 1654256265584-0。 一旦消息 1654256265584-0 被 consumer2 处理了,consumer2 就可以使用 XACK 命令通知 Streams,然后这条消息就会被删除。
当我们再使用 XPENDING 命令查看时,就可以看到,consumer2 已经没有已读取、但尚未确认处理的消息了。
好了,基于 Stream 实现的消息队列就说到这里了,小结一下:
一个专业的消息队列,必须要做到两大块:
1、Redis Stream 消息会丢失吗? 使用一个消息队列,其实就分为三大块:生产者、队列中间件、消费者,所以要保证消息就是保证三个环节都不能丢失数据。 Redis Stream 消息队列能不能保证三个环节都不丢失数据?
可以看到,Redis 在队列中间件环节无法保证消息不丢。像 RabbitMQ 或 Kafka 这类专业的队列中间件,在使用时是部署一个集群,生产者在发布消息时,队列中间件通常会写「多个节点」,也就是有多个副本,这样一来,即便其中一个节点挂了,也能保证集群的数据不丢失。 2、Redis Stream 消息可堆积吗? Redis 的数据都存储在内存中,这就意味着一旦发生消息积压,则会导致 Redis 的内存持续增长,如果超过机器内存上限,就会面临被 OOM 的风险。所以 Redis 的 Stream 提供了可以指定队列最大长度的功能,就是为了避免这种情况发生。 但 Kafka、RabbitMQ 专业的消息队列它们的数据都是存储在磁盘上,当消息积压时,无非就是多占用一些磁盘空间。 因此,把 Redis 当作队列来使用时,会面临的 2 个问题:
所以,能不能将 Redis 作为消息队列来使用,关键看你的业务场景:
总结Redis 常见的五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及 Zset(sorted set:有序集合)。 这五种数据类型都由多种数据结构实现的,主要是出于时间和空间的考虑,当数据量小的时候使用更简单的数据结构,有利于节省内存,提高性能。 这五种数据类型与底层数据结构对应关系图如下,左边是 Redis 3.0版本的,也就是《Redis 设计与实现》这本书讲解的版本,现在看还是有点过时了,右边是现在 Github 最新的 Redis 代码的。 可以看到,Redis 数据类型的底层数据结构随着版本的更新也有所不同,比如:
Redis 五种数据类型的应用场景:
Redis 后续版本又支持四种数据类型,它们的应用场景如下:
针对 Redis 是否适合做消息队列,关键看你的业务场景:
参考资料:
系列Redis 文章: |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/16 3:55:55- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |