前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【数据库干货】Redis 数据结构和主要命令

【数据库干货】Redis 数据结构和主要命令

作者头像
老九君
发布2019-05-13 17:38:48
4300
发布2019-05-13 17:38:48
举报
文章被收录于专栏:老九学堂老九学堂

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 中的配置

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老九学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Redis 是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库、缓存服务或消息服务使用。
    • 例 1:库存控制
      • 例 2:自增序列生成
        • Redis Sorted Set 是有序的、不可重复的 String 集合。
          • Sorted Set 中的每个元素都需要指派一个分数 (score),Sorted Set 会根据 score 对元素进行升序排序。
            • 如果多个 member 拥有相同的 score,则以字典序进行升序排序。
            相关产品与服务
            云数据库 Redis
            腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档