您当前的位置:首页 > 电脑百科 > 数据库 > Redis

Redis数据结构和主要命令

时间:2019-05-05 14:48:10  来源:  作者:

redis 是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库、缓存服务或消息服务使用。

Redis 支持多种数据结构,包括字符串、哈希表、链表、集合、有序集合、位图、Hyperloglogs 等。

Redis 具备 LRU 淘汰、事务实现、以及不同级别的硬盘持久化等能力。

支持副本集和通过 Redis Sentinel 实现的高可用方案,同时还支持通过 Redis Cluster 实现的数据自动分片能力。

Redis 的主要功能都基于单线程模型实现,也就是说 Redis 使用一个线程来服务所有的客户端请求,同时 Redis 采用了非阻塞式 IO,并精细地优化各种命令的算法时间复杂度。

这些信息意味着:

Redis 是线程安全的(因为只有一个线程),其所有操作都是原子的,不会因并发产生数据异常。

Redis 的速度非常快(因为使用非阻塞式 IO,且大部分命令的算法时间复杂度都是 O(1))。

使用高耗时的 Redis 命令是很危险的,会占用唯一的一个线程的大量处理时间,导致所有的请求都被拖慢。(例如时间复杂度为 O(N) 的 KEYS 命令,严格禁止在生产环境中使用)

常用命令一:Key

Redis 采用 Key-Value 型的基本数据结构,任何二进制序列都可以作为 Redis 的 Key 使用(例如普通的字符串或一张 JPEG 图片)

关于 Key 的一些注意事项:

不要使用过长的 Key。

例如使用一个 1024 字节的 key 就不是一个好主意,不仅会消耗更多的内存,还会导致查找的效率降低。

Key 短到缺失了可读性也是不好的。

例如”u1000flw” 比起”user:1000:followers” 来说,节省了寥寥的存储空间,却引发了可读性和可维护性上的麻烦。

最好使用统一的规范来设计 Key,比如”object-type:id:attr”,以这一规范设计出的 Key 可能是”user:1000” 或”comment:1234:reply-to”。

Redis 允许的最大 Key 长度是 512MB(对 Value 的长度限制也是 512MB)

常用命令二:String

String 是 Redis 的基础数据类型,Redis 没有 Int、Float、Boolean 等数据类型的概念,所有的基本类型在 Redis 中都以 String 体现。

与 String 相关的常用命令:

SET:为一个 key 设置 value,可以配合 EX/PX 参数指定 key 的有效期,通过 NX/XX 参数针对 key 是否存在的情况进行区别操作,时间复杂度 O(1)

GET:获取某个 key 对应的 value,时间复杂度 O(1)

GETSET:为一个 key 设置 value,并返回该 key 的原 value,时间复杂度 O(1)

MSET:为多个 key 设置 value,时间复杂度 O(N)

MSETNX:同 MSET,如果指定的 key 中有任意一个已存在,则不进行任何操作,时间复杂度 O(N)

MGET:获取多个 key 对应的 value,时间复杂度 O(N)上文提到过,Redis 的基本数据类型只有 String。

但 Redis 可以把 String 作为整型或浮点型数字来使用,主要体现在 INCR、DECR 类的命令上。

INCR:将 key 对应的 value 值自增 1,并返回自增后的值。

只对可以转换为整型的 String 数据起作用。时间复杂度 O(1)

INCRBY:将 key 对应的 value 值自增指定的整型数值,并返回自增后的值。

只对可以转换为整型的 String 数据起作用。时间复杂度 O(1)

DECR/DECRBY:同 INCR/INCRBY,自增改为自减。

INCR/DECR 系列命令要求操作的 value 类型为 String,并可以转换为 64 位带符号的整型数字,否则会返回错误。

也就是说,进行 INCR/DECR 系列命令的 value,必须在 [-2^63 ~ 2^63 - 1] 范围内。

Redis 采用单线程模型,天然是线程安全的,这使得 INCR/DECR 命令可以非常便利的实现高并发场景下的精确控制。

例 1:库存控制

在高并发场景下实现库存余量的精准校验,确保不出现超卖的情况。

设置库存总量:

SET inv:remAIn "100"

库存扣减 + 余量校验:

DECR inv:remain

当 DECR 命令返回值大于等于 0 时,说明库存余量校验通过;

如果返回小于 0 的值,则说明库存已耗尽。

假设同时有 300 个并发请求进行库存扣减,Redis 能够确保这 300 个请求分别得到 99 到 - 200 的返回值,每个请求得到的返回值都是唯一的。

绝对不会找出现两个请求得到一样的返回值的情况。

例 2:自增序列生成

实现类似于 RDBMS 的 Sequence 功能,生成一系列唯一的序列号

设置序列起始值:

SET sequence "10000"

获取一个序列值:

INCR sequence

直接将返回值作为序列使用即可。

获取一批(如 100 个)序列值:

INCRBY sequence 100

假设返回值为 N,那么 [N - 99 ~ N] 的数值都是可用的序列值。

当多个客户端同时向 Redis 申请自增序列时,Redis 能够确保每个客户端得到的序列值或序列范围都是全局唯一的。

绝对不会出现不同客户端得到了重复的序列值的情况。

常用命令三:List

Redis 的 List 是链表型的数据结构,可以使用 LPUSH/RPUSH/LPOP/RPOP 等命令在 List 的两端执行插入元素和弹出元素的操作。

虽然 List 也支持在特定 index 上插入和读取元素的功能,但其时间复杂度较高(O(N)),应小心使用。

与 List 相关的常用命令:

LPUSH:向指定 List 的左侧(即头部)插入 1 个或多个元素,返回插入后的 List 长度。时间复杂度 O(N),N 为插入元素的数量

RPUSH:同 LPUSH,向指定 List 的右侧(即尾部)插入 1 或多个元素

LPOP:从指定 List 的左侧(即头部)移除一个元素并返回,时间复杂度 O(1)

RPOP:同 LPOP,从指定 List 的右侧(即尾部)移除 1 个元素并返回

LPUSHX/RPUSHX:与 LPUSH/RPUSH 类似,区别在于,

LPUSHX/RPUSHX 操作的 key 如果不存在,则不会进行任何操作

LLEN:返回指定 List 的长度,时间复杂度 O(1)

LRANGE:返回指定 List 中指定范围的元素(双端包含,即 LRANGE key 0 10 会返回 11 个元素),时间复杂度 O(N)。

应尽可能控制一次获取的元素数量,一次获取过大范围的 List 元素会导致延迟。

同时对长度不可预知的 List,避免使用 LRANGE key 0 -1 这样的完整遍历操作。

应谨慎使用的 List 相关命令:

LINDEX:返回指定 List 指定 index 上的元素,如果 index 越界,返回 nil。

index 数值是回环的,即 - 1 代表 List 最后一个位置,-2 代表 List 倒数第二个位置。时间复杂度 O(N)

LSET:将指定 List 指定 index 上的元素设置为 value,如果 index 越界则返回错误,时间复杂度 O(N)。

如果操作的是头 / 尾部的元素,则时间复杂度为 O(1)

LINSERT:向指定 List 中指定元素之前 / 之后插入一个新元素,并返回操作后的 List 长度。

如果指定的元素不存在,返回 - 1。如果指定 key 不存在,不会进行任何操作,时间复杂度 O(N)

由于 Redis 的 List 是链表结构的,上述的三个命令的算法效率较低,需要对 List 进行遍历。

命令的耗时无法预估,在 List 长度大的情况下耗时会明显增加,应谨慎使用。

换句话说,Redis 的 List 实际是设计来用于实现队列,而不是用于实现类似 ArrayList 这样的列表的。

如果你不是想要实现一个双端出入的队列,那么请尽量不要使用 Redis 的 List 数据结构。

为了更好支持队列的特性,Redis 还提供了一系列阻塞式的操作命令,如 BLPOP/BRPOP 等,能够实现类似于 BlockingQueue 的能力。

即在 List 为空时,阻塞该连接,直到 List 中有对象可以出队时再返回。

常用命令四:Hash

Hash 即哈希表,Redis 的 Hash 和传统的哈希表一样,是一种 field-value 型的数据结构,可以理解成将 HashMap 搬入 Redis。

Hash 非常适合用于表现对象类型的数据,用 Hash 中的 field 对应对象的 field 即可。

Hash 的优点包括:

可以实现二元查找,如” 查找 ID 为 1000 的用户的年龄”

比起将整个对象序列化后作为 String 存储的方法,Hash 能够有效地减少网络传输的消耗。

当使用 Hash 维护一个集合时,提供了比 List 效率高得多的随机访问命令

与 Hash 相关的常用命令:

HSET:将 key 对应的 Hash 中的 field 设置为 value。如果该 Hash 不存在,会自动创建一个。时间复杂度 O(1)

HGET:返回指定 Hash 中 field 字段的值,时间复杂度 O(1)

HMSET/HMGET:同 HSET 和 HGET,可以批量操作同一个 key 下的多个 field,时间复杂度:O(N),N 为一次操作的 field 数量

HSETNX:同 HSET,但如 field 已经存在,HSETNX 不会进行任何操作,时间复杂度 O(1)

HEXISTS:判断指定 Hash 中 field 是否存在,存在返回 1,不存在返回 0,时间复杂度 O(1)

HDEL:删除指定 Hash 中的 field(1 个或多个),时间复杂度:O(N),N 为操作的 field 数量

HINCRBY:同 INCRBY 命令,对指定 Hash 中的一个 field 进行 INCRBY,时间复杂度 O(1)

应谨慎使用的 Hash 相关命令:

HGETALL:返回指定 Hash 中所有的 field-value 对。

返回结果为数组,数组中 field 和 value 交替出现。时间复杂度 O(N)

HKEYS/HVALS:返回指定 Hash 中所有的 field/value,时间复杂度 O(N)

上述三个命令都会对 Hash 进行完整遍历,Hash 中的 field 数量与命令的耗时线性相关,对于尺寸不可预知的 Hash,应严格避免使用上面三个命令,而改为使用 HSCAN 命令进行游标式的遍历。

常用命令五:Set

Redis Set 是无序的,不可重复的 String 集合。

与 Set 相关的常用命令:

SADD:向指定 Set 中添加 1 个或多个 member,如果指定 Set 不存在,会自动创建一个。时间复杂度 O(N),N 为添加的 member 个数

SREM:从指定 Set 中移除 1 个或多个 member,时间复杂度 O(N),N 为移除的 member 个数

SRANDMEMBER:从指定 Set 中随机返回 1 个或多个 member,时间复杂度 O(N),N 为返回的 member 个数

SPOP:从指定 Set 中随机移除并返回 count 个 member,时间复杂度 O(N),N 为移除的 member 个数

SCARD:返回指定 Set 中的 member 个数,时间复杂度 O(1)

SISMEMBER:判断指定的 value 是否存在于指定 Set 中,时间复杂度 O(1)

SMOVE:将指定 member 从一个 Set 移至另一个 Set

慎用的 Set 相关命令:

SMEMBERS:返回指定 Hash 中所有的 member,时间复杂度 O(N)

SUNION/SUNIONSTORE:计算多个 Set 的并集并返回 / 存储至另一个 Set中,时间复杂度 O(N),N 为参与计算的所有集合的总 member 数。

SINTER/SINTERSTORE:计算多个 Set 的交集并返回 / 存储至另一个 Set 中,时间复杂度 O(N),N 为参与计算的所有集合的总 member 数。

SDIFF/SDIFFSTORE:计算 1 个 Set 与 1 或多个 Set 的差集并返回 / 存储至另一个 Set 中,时间复杂度 O(N),N 为参与计算的所有集合的总 member 数。

上述几个命令涉及的计算量大,应谨慎使用,特别是在参与计算的 Set 尺寸不可知的情况下,应严格避免使用。

可以考虑通过 SSCAN 命令遍历获取相关 Set 的全部 member。

如果需要做并集 / 交集 / 差集计算,可以在客户端进行,或在不服务实时查询请求的 Slave 上进行。

常用命令六:Sorted Set

Redis Sorted Set 是有序的、不可重复的 String 集合。

Sorted Set 中的每个元素都需要指派一个分数 (score),Sorted Set 会根据 score 对元素进行升序排序。

如果多个 member 拥有相同的 score,则以字典序进行升序排序。

Sorted Set 非常适合用于实现排名。

Sorted Set 的主要命令:

ZADD:向指定 Sorted Set 中添加 1 个或多个 member,时间复杂度 O(Mlog(N)),M 为添加的 member 数量,N 为 Sorted Set 中的 member 数量

ZREM:从指定 Sorted Set 中删除 1 个或多个 member,时间复杂度 O(Mlog(N)),M 为删除的 member 数量,N 为 Sorted Set 中的 member 数量

ZCOUNT:返回指定 Sorted Set 中指定 score 范围内的 member 数量,时间复杂度:O(log(N))

ZCARD:返回指定 Sorted Set 中的 member 数量,时间复杂度 O(1)

ZSCORE:返回指定 Sorted Set 中指定 member 的 score,时间复杂度 O(1)

ZRANK/ZREVRANK:返回指定 member 在 Sorted Set 中的排名,ZRANK 返回按升序排序的排名,ZREVRANK 则返回按降序排序的排名。

时间复杂度 O(log(N))

ZINCRBY:同 INCRBY,对指定 Sorted Set 中的指定 member 的 score 进行自增,时间复杂度 O(log(N))

慎用的 Sorted Set 相关命令:

ZRANGE/ZREVRANGE:返回指定 Sorted Set 中指定排名范围内的所有 member。

ZRANGE 为按 score 升序排序,ZREVRANGE 为按 score 降序排序,时间复杂度

O(log(N)+M),M 为本次返回的 member 数

ZRANGEBYSCORE/ZREVRANGEBYSCORE:返回指定 Sorted Set 中指定 score 范围内的所有 member,返回结果以升序 / 降序排序。

min 和 max 可以指定为 - inf 和 + inf,代表返回所有的 member。时间复杂度 O(log(N)+M)

ZREMRANGEBYRANK/ZREMRANGEBYSCORE:移除 Sorted Set 中指定排名范围 / 指定 score 范围内的所有 member。时间复杂度 O(log(N)+M)

上述几个命令,应尽量避免传递 [0 -1] 或 [-inf +inf] 这样的参数,来对 Sorted Set 做一次性的完整遍历,特别是在 Sorted Set 的尺寸不可预知的情况下。

可以通过 ZSCAN 命令来进行游标式的遍历,或通过 LIMIT 参数来限制返回 member 的数量(适用于 ZRANGEBYSCORE 和 ZREVRANGEBYSCORE 命令),以实现游标式的遍历。

常用命令七:Bitmap 和 HyperLogLog

Redis 的这两种数据结构相较之前的并不常用,在 Redis 中不是一种实际的数据类型,而是一种将 String 作为 Bitmap 使用的方法。

可以理解为将 String 转换为 bit 数组。使用 Bitmap 来存储 true/false 类型的简单数据极为节省空间。

HyperLogLogs 是一种主要用于数量统计的数据结构,它和 Set 类似,维护一个不可重复的 String 集合。

但是 HyperLogLogs 并不维护具体的 member 内容,只维护 member 的个数。

也就是说,HyperLogLogs 只能用于计算一个集合中不重复的元素数量,所以它比 Set 要节省很多内存空间。

其他常用命令

EXISTS:判断指定的 key 是否存在,返回 1 代表存在,0 代表不存在,时间复杂度 O(1)

DEL:删除指定的 key 及其对应的 value,时间复杂度 O(N),N 为删除的 key 数量

EXPIRE/PEXPIRE:为一个 key 设置有效期,单位为秒或毫秒,时间复杂度 O(1)

TTL/PTTL:返回一个 key 剩余的有效时间,单位为秒或毫秒,时间复杂度 O(1)

RENAME/RENAMENX:将 key 重命名为 newkey。使用 RENAME 时,如果 newkey 已经存在,其值会被覆盖;使用 RENAMENX 时,如果 newkey 已经存在,则不会进行任何操作,时间复杂度 O(1)

TYPE:返回指定 key 的类型,string, list, set, zset, hash。时间复杂度 O(1)

CONFIG GET:获得 Redis 某配置项的当前值,可以使用 * 通配符,时间复杂度 O(1)

CONFIG SET:为 Redis 某个配置项设置新值,时间复杂度 O(1)

CONFIG REWRITE:让 Redis 重新加载 redis.conf 中的配置

来源:kelgon
 



Tags:Redis 数据结构   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
聊一聊Redis之数据结构
基本数据结构简单动态字符串Redis中的字符串使用“简单动态字符串”(SDS)表示,无论是字符串值还是键底层都采用“简单动态字符串”。 free:未使用空间大小; len:字符串长度; buf...【详细内容】
2020-03-07  Search: Redis 数据结构  点击:(319)  评论:(0)  加入收藏
redis各类型数据结构和底层实现源码分析
一、简介和应用Redis是一个由ANSI C语言编写,性能优秀、支持网络、可持久化的K-K内存数据库,并提供多种语言的API。它常用的类型主要是 String、List、Hash、Set、ZSet 这5种...【详细内容】
2020-03-02  Search: Redis 数据结构  点击:(340)  评论:(0)  加入收藏
Redis数据结构和通用命令
Redis的数据结构Redis支持多种不同的数据结构,包括5种基础数据结构和几种比较复杂的数据,这些数据结构可以满足不同的应用场景。 五种基础数据结构 String:字符串,是构建其他数...【详细内容】
2019-09-02  Search: Redis 数据结构  点击:(866)  评论:(0)  加入收藏
Redis的3个高级数据结构
平常我们我接触最多的是5个入门级数据结构:String,Hash,List,Set,Sorted Set。本文介绍3个高级数据结构:Bitmaps,Hyperloglogs,GEO。...【详细内容】
2019-08-27  Search: Redis 数据结构  点击:(826)  评论:(0)  加入收藏
Redis数据结构和主要命令
Redis 是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库、缓存服务或消息服务使用。Redis 支持多种数据结构,包括字符串、哈希表、链表、集合、有序集合、位图、Hype...【详细内容】
2019-05-05  Search: Redis 数据结构  点击:(1901)  评论:(0)  加入收藏
▌简易百科推荐
兄弟,王者荣耀的段位排行榜是通过Redis实现的?
在王者荣耀中,我们会打排位赛,而且大家最关注的往往都是你的段位,还有在好友中的排名。作为程序员的你,是否思考过这个段位排行榜是怎么实现的?了解它的实现原理,会不会对上分有所...【详细内容】
2024-04-15    dbaplus社群  Tags:Redis   点击:(3)  评论:(0)  加入收藏
16个Redis常见使用场景总结
来源:blog.csdn.net/qq_39938758/article/details/105577370目录 缓存 数据共享分布式 分布式锁 全局ID 计数器 限流 位统计 购物车 用户消息时间线timeline 消息...【详细内容】
2024-04-11    书圈  Tags:Redis   点击:(8)  评论:(0)  加入收藏
Linux获取Redis 性能指标方法
一、监控指标Ø 性能指标:PerformanceØ 内存指标: MemoryØ 基本活动指标:Basic activityØ 持久性指标: PersistenceØ 错误指标:Error二、监...【详细内容】
2024-04-11  上海天正信息科技有限    Tags:Redis   点击:(10)  评论:(0)  加入收藏
Redis与缓存一致性问题
缓存一致性问题是在使用缓存系统,如Redis时经常遇到的问题。当数据在原始数据源(如数据库)中发生变化时,如何确保缓存中的数据与数据源保持一致,是开发者需要关注的关键问题。一...【详细内容】
2024-04-11  后端Q    Tags:Redis   点击:(8)  评论:(0)  加入收藏
Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证
Redis 官方于21日宣布修改开源协议 —— 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause...【详细内容】
2024-03-27  dbaplus社群    Tags:Redis   点击:(23)  评论:(0)  加入收藏
Redis“叛逃”开源,得罪了几乎所有人
内存数据库供应商Redis近日在开源界砸下了一块“巨石”。Redis即将转向双许可模式,并实施更为严格的许可条款。官方对此次变更的公告直截了当:从Redis 7.4版本开始,Redis将在Re...【详细内容】
2024-03-25    51CTO  Tags:Redis   点击:(13)  评论:(0)  加入收藏
如何使用 Redis 实现消息队列
Redis不仅是一个强大的内存数据存储系统,它还可以用作一个高效的消息队列。消息队列是应用程序间或应用程序内部进行异步通信的一种方式,它允许数据生产者将消息放入队列中,然...【详细内容】
2024-03-22  后端Q  微信公众号  Tags:Redis   点击:(22)  评论:(0)  加入收藏
Redis不再 “开源”
Redis 官方今日宣布修改开源协议 —— 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause 开...【详细内容】
2024-03-21  OSC开源社区    Tags:Redis   点击:(14)  评论:(0)  加入收藏
在Redis中如何实现分布式锁的防死锁机制?
在Redis中实现分布式锁是一个常见的需求,可以通过使用Redlock算法来防止死锁。Redlock算法是一种基于多个独立Redis实例的分布式锁实现方案,它通过协调多个Redis实例之间的锁...【详细内容】
2024-02-20  编程技术汇    Tags:Redis   点击:(50)  评论:(0)  加入收藏
手动撸一个 Redis 分布式锁
大家好呀,我是楼仔。今天第一天开工,收拾心情,又要开始好好学习,好好工作了。对于使用 Java 的小伙伴,其实我们完全不用手动撸一个分布式锁,直接使用 Redisson 就行。但是因为这些...【详细内容】
2024-02-19  楼仔  微信公众号  Tags:Redis   点击:(47)  评论:(0)  加入收藏
站内最新
站内热门
站内头条