Redis 常用命令

Redis

Redis简介

  • Redis 是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库、缓存服务或消息服务使用。
  • Redis支持多种数据结构,包括字符串、哈希表、链表、集合、有序集合、位图、Hyperloglogs 等。
  • Redis具备LRU淘汰、事务实现、以及不同级别的硬盘持久化等能力,并且支持副本集和通RedisSentinel实现的高可用方案,同时还支持通过RedisCluster实现的数据自动分片能力。
  • Redis:持久化功能、发布订阅功能、事务功能、过期键功能、复制、集群

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

  • Redis 是线程安全的(因为只有一个线程),其所有操作都是原子的,不会因并发产生数据异常
  • Redis 的速度非常快(因为使用非阻塞式 IO,且大部分命令的算法时间复杂度都是 O(1))
    使用高耗时的 Redis 命令是很危险的,会占用唯一的一个线程的大量处理时间,导致所有的请求都被拖慢。(例如时间复杂度为 O(N) 的 KEYS 命令,严格禁止在生产环境中使用)

本文只对 Redis 命令进行扼要的介绍,且只列出了较常用的命令。如果想要了解完整的 Redis 命令集,或了解某个命令的详细使用方法,请参考官方文档:https://redis.io/commands

使用redis有哪些好处

  • 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
  • 支持丰富数据类型,支持string,list,set,sorted set,hash

### Redis 基本数据类型

Redis类型含义
String字符串
Hash字典
List列表
Set集合
Sorted set有序集合
Pub/Sub订阅
Transactions事物
字符串

Redis 字符串是一个字节序列。 在 Redis 中字符串是二进制安全的,这意味着它们没有任何
特殊终端字符来确定长度,所以可以存储任何长度为 512 兆的字符串。String 是 Redis 的基础数据类型,Redis 没有 Int、Float、Boolean 等数据类型的概念,所有的基本类型在 Redis 中都以 String 体现。

127.0.0.1:6379> set key1 key1_test
OK
127.0.0.1:6379> get key1
"key1_test"
应用场景

String是最常用的一种数据类型,普通的key/value存储都可以归为此类;

实现方式

String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr、decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。

与 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 命令可以非常便利的实现高并发场景下的精确控制。

哈希

Redis哈希是键值对的集合。Redis哈希是字符串字段和字符串值之间的映射,所以它们用来表示对象。
Hash 的优点包括:

  • 可以实现二元查找,如” 查找 ID 为 1000 的用户的年龄”
  • 比起将整个对象序列化后作为 String 存储的方法,Hash 能够有效地减少网络传输的消耗
  • 当使用 Hash 维护一个集合时,提供了比 List 效率高得多的随机访问命令
应用场景

我们要存储一个用户信息对象数据,其中包括用户ID、用户姓名、年龄和生日,通过用户ID我们希望获取该用户的姓名或者年龄或者生日

实现方式

Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。Key是用户ID, value是一个Map。这个Map的key是成员的属性名,value是属性值。这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据。

与 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)
127.0.0.1:6379> hset h1 name name_test
(integer) 0
127.0.0.1:6379> hset h1 age 18
(integer) 0
127.0.0.1:6379> hget h1 name
"name_test"
127.0.0.1:6379> hgetall h1
1) "name"
2) "name_test"
3) "age"
4) "18"
应谨慎使用的 Hash 相关命令
  • HGETALL:返回指定 Hash 中所有的 field-value 对。返回结果为数组,数组中 field 和 value 交替出现。时间复杂度 O(N)
  • HKEYS/HVALS:返回指定 Hash 中所有的 field/value,时间复杂度 O(N)

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

列表

Redis 列表是简单的字符串列表,通过插入顺序排序。可以使用 LPUSH/RPUSH/LPOP/RPOP 等命令添加一个元素到 Redis 列表的头部或尾部. 其时间复杂度较高(O(N))

应用场景

Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现;

实现方式

Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

与 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 中有对象可以出队时再返回。针对阻塞类的命令,此处不做详细探讨,请参考官方文档 中”Blocking operations on lists” 一节。

集合

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

应用场景

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的;

实现方式

set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

与 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 上进行。

排序集合

Redis Sorted Set 是有序的、不可重复的 String 集合。Sorted Set 中的每个元素都需要指派一个分数 (score),Sorted Set 会根据 score 对元素进行升序排序。如果多个 member 拥有相同的 score,则以字典序进行升序排序。Sorted Set 非常适合用于实现排名。

应用场景

Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。

实现方式

Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

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 命令),以实现游标式的遍历。

Redis订阅发布模式

Redis订阅和发布实现了通讯系统,发件人(在 Redis 中的术语称为发布者)发送邮件,而接
收器(订户)接收它们。信息传输的链路称为通道。Redis 一个客户端可以订阅任意数量的通

订阅发布主要命令:

  • SUBSCRIBE: 订阅一个主题
  • PUBLISH:向主题发布消息
 127.0.0.1:6379> SUBSCRIBE redis
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redis"
3) (integer) 1
1) "message"
2) "redis"
3) "okokokok"
127.0.0.1:6379> PUBLISH redis okokokok
(integer) 1
Redis事务

Redis事务允许一组命令在单一步骤中执行。事务有两个属性,说明如下:

  • 在一个事务中的所有命令作为单个独立的操作顺序执行。在Redis事务中的执行过程中而
    另一客户机发出的请求,这是不可以的;
  • Redis事务是原子的。原子意味着要么所有的命令都执行,要么都不执行;

Redis 事务由指令 MULTI 发起的,之后传递需要在事务中和整个事务中,最后由 EXEC 命令
执行所有命令的列表

127.0.0.1:6379> WATCH name
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set name name1
QUEUED
127.0.0.1:6379> get name
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> EXEC
(nil)

Redis的持久化

一文看懂Redis的持久化原理

常见面试题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CoLiuRs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值