redis 数据结构及常见命令

一、概述

Redis有5种数据结构,本文整理下数据结构都是什么,包含了什么常用命令,以及能用这些数据结构处理哪些类型的特性和数据。

目前为止,我们所知道的Redis构成仅包括命令、关键字和值,还没有接触到关于数据结构的具体概念。当我们使用set命令时,Redis是怎么知道我们是在使用哪个数据结构?其解决方法是,每个命令都相对应于一种特定的数据结构。例如,当你使用set命令,你就是将值存储到一个字符串数据结构里。而当你使用hset命令,你就是将值存储到一个散列数据结构里。考虑到Redis的关键字集很小,这样的机制具有相当的可管理性。

二、字符串 String

在Redis里,字符串是最基本最常用的数据结构。

  • 常用字符串命令如下

1. SET、GET

太简单不说了

2. GETRANGE

获取存储在指定 key 中字符串的子字符串
在这里插入图片描述

3. GETSET

将给定 key 的值设为 value ,并返回 key 的旧值

4. GETBIT、SETBIT

都是位操作
GETBIT key offset value 对 key 所储存的字符串值,获取指定偏移量上的位(bit),SETBIT就是清除或者设置了
这玩意有啥用呢,这可有大用了:
具体场景如下:
腾讯10亿用户,要几个毫秒内查询到某个用户是否在线,你能怎么做?千万别说给每个用户建立一个key,然后挨个记(你可以算一下需要的内存会很恐怖,而且这种类似的需求很多,腾讯光这个得多花多少钱。。)
原理是:
redis内构建一个足够长的数组,每个数组元素只能是0和1两个值,然后这个数组的下标index用来表示我们上面例子里面的用户id(必须是数字哈),那么很显然,这个几亿长的大数组就能通过下标和元素值(0和1)来构建一个记忆系统,就能实现上述场景。用到的命令是:setbit、getbit、bitcount

先来说说setbit、getbit、bitcount这三个指令的用法:
在学习这几个命令之前,我们得先了解下redis中字符串的存储方式,redis中的字符串都是以二进制的方式进行存储的,比如说我执行如下命令:
在这里插入图片描述
我们知道 ‘a’ 的ASCII码是 97。转换为二进制是:01100001。我们BIT相关命令都是对这个二进制数据进行操作

GETBIT
GETBIT命令可以返回key对应的value在offset(偏移)处的bit值,以上文提到的kk为例,a对应的二进制数据是01100001,所以当offset为0时,对应的bit值为0;offset为1时,对应的bit值为1;offset为2时,对应的bit值为1;offset为3时,对应的bit值为0,依此类推….,如下:
在这里插入图片描述
通过上述结果,可以看到offset从0到7,就是01100001,也就是说offset是从左往右计数的,也就是从高位往低位。当超过位数时,结果是0

BITCOUNT
BITCOUNT可以用来统计这个二进制数据中1的个数,如下:
在这里插入图片描述
官网上有一个非常有意思的案例:用户上线次数统计。节选部分原文如下:
在这里插入图片描述
SETBIT
我们通过SETBIT 命令将 andy中的 ‘a’ 变成 ‘b’ 应该怎么变呢?
也就是将 01100001 变成 01100010 (b的ASCII码是98),这个很简单啦,也就是将’a’中的offset 6从0变成1,将offset 7 从1变成0。如下图:
在这里插入图片描述
大家可能也发现了,每次SETBIT完毕之后,有一个(integer) 0或者(integer)1的返回值,这个是在你进行SETBIT 之前,该offset位的比特值。

另外使用 BITPOS 指令可以用来获取二进制位串中第一个1或者0的位置,如下:
在这里插入图片描述

5. MGET、MSET

读取、设置一个或多个key的值
在这里插入图片描述

6. SETEX、PSETEX

SETEX key seconds value
为指定的 key 设置值及其过期时间。如果 key 已经存在, SETEX 命令将会替换旧的值。
PSETEX也一样,但是以毫秒为单位

7. SETNX、MSETNX

只有key不存在的时候才会设置key的值,存在的话不覆盖
同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在

8. SETRANGE

SETRANGE key offset value 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始

9. STRLEN

返回 key 所储存的字符串值的长度

10. INCR、INCRBY、INCRBYFLOAT

把key中存储的数字的值加一
INCRBY key increment将 key 所储存的值加上给定的增量值(increment)
INCRBYFLOAT key increment将 key 所储存的值加上给定的浮点增量值(increment)

11.DECR、DECRBY

上面是加,这里就是减了

12. APPEND

APPEND key value
如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾,如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样

Redis的字符串数据结构比我当初所想的要有用许多。又能存储对象又能计数。还能用来做缓存用。

三、哈希表 Hash

我们已经知道把Redis称为一种关键字-值型存储是不太准确的,hash数据结构是一个很好的例证。你会看到,在很多方面里,散列数据结构很像字符串数据结构。两者显著的区别在于,散列数据结构提供了一个额外的间接层:一个字段(Field)

  • 哈希结构常用的命令有

1.HSET、HGET

HSET KEY_NAME FIELD VALUE 为哈希表中的字段赋值,如果字段有了就覆盖
HGET就是读取
在这里插入图片描述

2. HDEL

删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略
在这里插入图片描述

3. HEXISTS

查看哈希表 key 中,指定的字段是否存在

4. HGETALL

HGETALL key 获取在哈希表中指定 key 的所有字段和值

5. HINCRBY、HINCRBYFLOAT

HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment
HINCRBYFLOAT key field increment 为哈希表 key 中的指定字段的浮点数值加上增量 increment

6. HKEYS、HVALS

HKEYS key 获取所有哈希表中的字段
HVALS key 获取所有值

7. HLEN

HLEN key 获取哈希表中字段的数量

8.HMGET、HMSET

获取、设置多个字段的值
在这里插入图片描述

9. HSETNX

HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值

10. HSCAN

当我们需要遍历Redis所有key或者指定模式的key时,首先想到的是KEYS命令,但是如果redis数据非常大,并且key也非常多的情况下,查询的时候很可能会很慢,造成整个redis阻塞,那么有什么办法解决呢?就是scan和hscan

SCAN cursor [MATCH pattern] [COUNT count]
HSCAN key cursor [MATCH pattern] [COUNT count]

SCAN命令是一个基于游标的迭代器, 这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程, 当SCAN命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束,HSCAN同SCAN命令相同。
在这里插入图片描述
more: http://www.redis.cn/commands/scan.html

哈希表数据结构比普通的字符串数据结构具有更多的可操作性。我们可以使用一个哈希表数据结构去获得更精确的描述,是存储一个用户,而不是一个序列化对象。从而得到的好处是能够提取、更新和删除具体的数据片段,而不必去获取或写入整个值。

对于散列数据结构,可以从一个经过明确定义的对象的角度来考虑,例如一个用户,关键之处在于要理解他们是如何工作的。从性能上的原因来看,这是正确的,更具粒度化的控制可能会相当有用。

四、列表 lists

对于一个给定的关键字,列表数据结构让你可以存储和处理一组值。你可以添加一个值到列表里、获取列表的第一个值或最后一个值以及用给定的索引来处理值。列表数据结构维护了值的顺序,提供了基于索引的高效操作。

  • 列表常用命令

1. LPUSH、LPUSHX、RPUSH、RPUSHX

LPUSH 将一个或多个值插入到列表头部,如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。 当 key 存在但不是列表类型时,返回一个错误。
LPUSHX 将一个值插入到已存在的列表头部,列表不存在时操作无效。
RPUSH 将一个或多个值插入到列表尾部
RPUSHX 将一个值插入到已存在的列表尾部(最右边)。如果列表不存在,操作无效。

2. LPOP 、RPOP

LPOP、RPOP key移出并获取列表的第一个、最后一个元素

3. BLPOP、BRPOP

BLPOP key1 [key2 ] timeout 移出并获取列表的第一个、最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

4. RPOPLPUSH、BRPOPLPUSH

RPOPLPUSH SOURCE_KEY_NAME DESTINATION_KEY_NAME 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
BRPOPLPUSH LIST1 ANOTHER_LIST TIMEOUT 从列表中取出最后一个元素,并插入到另外一个列表的头部; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

5. LINDEX

LINDEX key index 通过索引获取列表中的元素

6. LINSERT

LINSERT key BEFORE|AFTER pivot value 在列表的pivot元素前或者后插入元素

7. LLEN

LLEN key 获取列表长度

8. LRANGE

LRANGE key start stop 获取列表指定范围内的元素

9.LREM

LREM key count value
Redis Lrem 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
COUNT 的值可以是以下几种:
count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
count = 0 : 移除表中所有与 VALUE 相等的值。

10. LSET

LSET key index value 通过索引设置列表元素的值

11. LTRIM

LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除

对于存储和索引关键字的功能,并不是只有列表数据结构这种方式。值可以是任意的东西,
我们可以使用列表数据结构去存储日志,也可以用来跟踪用户浏览网站时的路径或者使用列表数据结构去跟踪用户的排队活动。

五、集合 Sets

集合数据结构常常被用来存储只能唯一存在的值,并提供了许多的基于集合的操作,例如并集。集合数据结构没有对值进行排序,但是其提供了高效的基于值的操作。使用集合数据结构的典型用例是朋友名单的实现:
在这里插入图片描述
不管一个用户有多少个朋友,我们都能高效地(O(1)时间复杂度)识别出用户X是不是用户Y的朋友:

sismember friends:leto jessica
sismember friends:leto vladimir

甚至可以在一个新的关键字里存储结果:

sinterstore friends:leto_duncan friends:leto friends:duncan
  • 有时候需要对值的属性进行标记和跟踪处理,但不能通过简单的复制操作完成,集合数据结构是解决此类问题的最好方法之一。

当然,对于那些需要运用集合操作的地方(例如交集和并集),集合数据结构就是最好的选择。

  • 集合常用命令

1. SADD

SADD key member1 [member2] 向集合添加一个或多个成员

2. SCARD

SCARD key 获取集合的成员数

3. SDIFF

SDIFF key1 [key2] 返回给定所有集合的差集
在这里插入图片描述

4. SDIFFSTORE

SDIFFSTORE destination key1 [key2]
将给定集合之间的差集存储在指定的集合中。如果指定的集合 key 已存在,则会被覆盖。

5. SINTER

SINTER key1 [key2]
返回给定所有集合的交集

6. SINTERSTORE

SINTERSTORE destination key1 [key2] 返回给定所有集合的交集并存储在 destination 中

7. SISMEMBER

SISMEMBER key member 判断 member 元素是否是集合 key 的成员

8. SMEMBERS

SMEMBERS key 返回集合中的所有成员

9. SMOVE

SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合

10. SPOP

移除并返回集合中的一个随机元素

11. SRANDMEMBER

SRANDMEMBER key [count] 返回集合中一个或多个随机数

12. SREM

SREM key member1 [member2]
移除集合中一个或多个,不存在的成员元素会被忽略。

13. SUNION

返回所有给定集合的并集
在这里插入图片描述

14. SUNIONSTORE

SUNIONSTORE destination key1 [key2] 所有给定集合的并集存储在 destination 集合中

15. SSCAN

SSCAN key cursor [MATCH pattern] [COUNT count]
迭代集合中的元素,迭代具体作用可以参考:http://www.redis.cn/commands/scan.html
在这里插入图片描述

六、 有序集合(Sorted Sets)

有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。

  • 最常见的应用案例是用来实现排行榜系统。

对于一些基于整数排序,且能以标记来进行有效操作的东西,使用有序集合数据结构来处理应该都是不错的选择。

  • 有序集合常用命令

1. ZADD

向有序集合添加一个或多个成员,或者更新已存在成员的分数

2. ZCARD

获取有序集合的成员数

3. ZCOUNT

ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
在这里插入图片描述

4. ZINCRBY

ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment

5. ZINTERSTORE

ZINTERSTORE destination numkeys key [key …] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中,numkeys代表后面有几个key
在这里插入图片描述

6. ZLEXCOUNT

ZLEXCOUNT key min max在有序集合中计算指定字典区间内成员数量
在这里插入图片描述

7. ZRANGE

ZRANGE key start stop [WITHSCORES] 返回有序集中,指定区间内的成员。

其中成员的位置按分数值递增(从小到大)来排序。
具有相同分数值的成员按字典序(lexicographical order )来排列。
下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。
你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。带WITHSCORES参数就显示分数值,不带就只显示元素值
在这里插入图片描述

8. ZRANGEBYLEX

ZRANGEBYLEX key min max [LIMIT offset count] 通过字典区间返回有序集合的成员
在这里插入图片描述

9. ZRANGEBYSCORE

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员

10. ZRANK

ZRANK key member 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。

11. ZREM

ZREM key member [member …] 移除有序集合中的一个或多个成员

12. ZREMRANGEBYLEX

ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员

13. ZREMRANGEBYRANK

ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员

14. ZREMRANGEBYSCORE

ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员

15. ZREVRANGE

ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到底

16. ZREVRANGEBYSCORE

ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分数区间内的成员,分数从高到低排序

17. ZREVRANK

ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序

18. ZSCORE

ZSCORE key member 返回有序集中,成员的分数值

19. ZUNIONSTORE

ZUNIONSTORE destination numkeys key [key …] 计算给定的一个或多个有序集的并集,并存储在新的 key 中

20. ZSCAN

ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)
迭代具体作用可以参考:http://www.redis.cn/commands/scan.html

七、小结

对于Redis的5种数据结构,我们进行了高层次的概述。一件有趣的事情是,相对于最初构建时的想法,你经常能用Redis创造出一些更具实效的事情。对于字符串数据结构和分类集合数据结构的使用,很有可能存在一些构建方法是还没有人想到的。当你理解了那些常用的应用案例后,你将发现Redis对于许多类型的问题,都是很理想的选择。还有,不要因为Redis展示了5种数据结构和相应的各种方法,就认为你必须要把所有的东西都用上。只使用一些命令去构建一个特性是很常见的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章