【死磕Redis系列】三、Redis数据类型及操作

 ------------------------------------------------------------------------------------------------------慢慢来,一切都来得及


目录

一、基础命令

二、string(字符串)类型

三、list(列表、链表)类型

四、hash(哈希、字典、散列)类型

五、set(集合)类型

六、zset(sorted set有序集合)类型

七、容器型数据结构的通用规则


一、基础命令

1.获得符合规则的键名列表
 
KEYS pattern
 
pattern 支持 glob 风格通配符格式,具体规则如表 所示
 
符号                                                                             含义
? 匹配一个字符
* 匹配任意个(包括0个)字符
[] 匹配括号间的任一字符,可以使用"-"符号表示一个范围,如a[a-c]可以匹配"aa"、"ab"和"ac"
\x 匹配字符x,用于转义符号。如要匹配"*"就需要使用\*

注意 KEYS命令需要遍历Redis中的所有键,当键的数量较多时会影响性能,不建议在生产环境中使用。

2.判断一个键是否存在

EXISTS key

如果键存在则返回整数类型1,否则返回0。例如:

3.删除键

DEL key [key …]
 
可以删除一个或多个键,返回值是删除的键的个数。例如:
 
 
4.获得键值的数据类型
 
TYPE key
 
TYPE 命令用来获得键值的数据类型,返回值可能是 string (字符串类型)、 hash (散列
类型)、 list (列表类型)、 set (集合类型)、 zset (有序集合类型)。例如:
 
 
 

二、string(字符串)类型

Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,如图中所示,内部为当前字符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是字符串最大长度为 512M。

 
1.赋值与取值
 
SET key value
 
GET key
 

2. 递增数字

INCR key

前面说过字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时,Redis 提供了一个实用的命令 INCR,其作用是让当前键值递增,并返回递增后的值,自增是有范围的,它的范围是signed long 的最大最小值,超过了这个值,Redis 会报错。用法为
 
 
当要操作的键不存在时会默认键值为0,所以第一次递增后的结果是1。当键值不是整数 时Redis会提示错误:
 
 
3.增加指定的整数
 
INCRBY key incrment
 
INCRBY命令与INCR命令基本一样,只不过前者可以通过increment参数指定一次增加的 数值,如:
 
 
4.减少指定的整数
 
DECR key  (该命令是让键值递减)
 
DECRBY key decrement
 
 
5.向尾部追加值
 
APPEND key value
 
APPEND 作用是向键值的末尾追加 value 。如果键不存在则将该键的值设置为 value ,即
相当于 SET key value 。返回值是追加后字符串的总长度。如:
 
 
6.获取字符串长度
 
STRLEN key
 
STRLEN 命令返回键值的长度,如果键不存在则返回 0 。如:
 
 
7.同时获得/设置多个键值
 
MGET key [key …]
 
MSET key value [key value …]
 
MGET/MSET GET/SET 相似,不过 MGET/MSET 可以同时获得 / 设置多个键的键值。如:
 
 

8.过期

EXPIRE KEY 时间s

可以对 key 设置过期时间,到点自动删除,这个功能常用来控制缓存的失效时间。
 
 
9.set命令扩展
 
setex    等价于 set+expire
 
 
setnx 如果key不存在,就执行set创建;如果key已存在,则set创建失败。
 

三、list(列表、链表)类型

Redis的列表相当于Java语言里面的 LinkedList,注意它是链表而不是数组。这意味着list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为O(n),这点让人非常意外。

1.向列表两端增加元素
 
LPUSH key value [value …]
RPUSH key value [value …]
 
LPUSH 命令用来向列表左边增加元素,返回值表示增加元素后列表的长度。
 

2.从列表两端弹出元素
 
LPOP key
RPOP key
 
有进有出, LPOP 命令可以从列表左边弹出一个元素。 LPOP 命令执行两步操作:第一步 是将列表左边的元素从列表中移除,第二步是返回被移除的元素值。
 
 
同样, RPOP 命令可以从列表右边弹出一个元素:
 
 
3.获取列表中元素的个数
 
LLEN key    当键不存在时 LLEN 会返回 0
 
 
LLEN 命令的功能类似 SQL 语句 SELECT COUNT(*) FROM table_name ,但是 LLEN 的 时间复杂度为O(1) ,使用时 Redis 会直接读取现成的值,而不需要像部分关系数据库(如使用 InnoDB存储引擎的 MySQL 表)那样需要遍历一遍数据表来统计条目数量。
 
4.获得列表片段
 
LRANGE key start stop
LRANGE 命令是列表类型最常用的命令之一,它能够获得列表中的某一片段。 LRANGE 命令将返回索引从 start stop 之间的所有元素(包含两端的元素)。与大多数人的直觉相 同,Redis 的列表起始索引为 0
 
LRANGE 命令在取得列表片段的同时不会像 LPOP 一样删除该片段。
 
LRANGE 命令也支持负索引,表示从右边开始计算序数,如 "−1" 表示最右边第一个元
素, "-2" 表示最右边第二个元素,依次类推:
 
5.删除列表中指定的值
 
LREM key count value
LREM 命令会删除列表中前 count 个值为 value 的元素,返回值是实际删除的元素个数。根
count 值的不同, LREM 命令的执行方式会略有差异。
1 )当 count > 0 LREM 命令会从列表左边开始删除前 count 个值为 value 的元素。
2 )当 count < 0 LREM 命令会从列表右边开始删除前 |count| 个值为 value 的元素。
3 )当 count = 0 LREM 命令会删除所有值为 value 的元素。
 
 
6.获得/设置指定索引的元素值
 
LINDEX key index
LSET key index value
如果要将列表类型当作数组来用, LINDEX 命令是必不可少的。 LINDEX 命令用来返回
指定索引的元素,索引从 0 开始。
 
 
如果 index 是负数则表示从右边开始计算的索引,最右边元素的索引是 −1

7.只保留列表指定片段
 
LTRIM key start end
LTRIM 命令可以删除指定索引范围之外的所有元素,其指定列表范围的方法和 LRANGE 命令相同。
 
 
8.向列表中插入元素
 
LINSERT key BEFORE|AFTER pivot value
 
LINSERT 命令首先会在列表中从左到右查找值为 pivot 的元素,然后根据第二个参数是 BEFORE还是 AFTER 来决定将 value 插入到该元素的前面还是后面。 LINSERT命令的返回值是插入后列表的元素个数。
 
 
9.将元素从一个列表转到另一个列表
 
RPOPLPUSH source destination
 
RPOPLPUSH 是个很有意思的命令,从名字就可以看出它的功能:先执行 RPOP 命令再
执行 LPUSH 命令。 RPOPLPUSH 命令会先从 source 列表类型键的右边弹出一个元素,然后将
其加入到 destination 列表类型键的左边,并返回这个元素的值,整个过程是原子的。

四、hash(哈希、字典、散列)类型

Redis的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。不同的是,Redis 的字典的值只能是字符串,另外它们 rehash 的方式不一样,因为 Java 的 HashMap 在字典很大时,rehash 是个耗时的操作,需要一次性全部 rehashRedis 为了高性能,不能堵塞服务,所以采用了渐进式 rehash 策略。

提示 除了散列类型,Redis 的其他数据类型同样不支持数据类型嵌套。比如集合类型的 每个元素都只能是字符串,不能是另一个集合或散列表等。

hash 也有缺点,hash 结构的存储消耗要高于单个字符串,到底该使用 hash 还是字符 串,需要根据实际情况再三权衡。

散列类型适合存储对象:使用对象类别和 ID 构成键名,使用字段表示对象的属性,而 字段值则存储属性值。

1.赋值与取值
 
HSET key field value
HGET key field
HMSET key field value [field value …]
HMGET key field [field …]
HGETALL key
 
HSET 命令用来给字段赋值,而 HGET 命令用来获得字段的值。
 
 

HSET 命令的方便之处在于不区分插入和更新操作,这意味着修改数据时不用事先判断 字段是否存在来决定要执行的是插入操作(update)还是更新操作(insert)。当执行的是插 入操作时(即之前字段不存在)HSET命令会返回1,当执行的是更新操作时(即之前字段已 经存在)HSET命令会返回0。更进一步,当键本身不存在时,HSET命令还会自动建立它。

当需要同时设置多个字段的值时,可以使用 HMSET 命令。例如,下面两条语句
HSET key field1 value1
HSET key field2 value2
可以用 HMSET 命令改写成
HMSET key field1 value1 field2 value2
相应地, HMGET 命令可以同时获得多个字段的值。
 
如果想获取键中所有字段和字段值却不知道键中有哪些字段时应该使用 HGETALL 命令
 

2.判断字段是否存在
 
HEXISTS key field
HEXISTS 命令用来判断一个字段是否存在。如果存在则返回 1 ,否则返回 0 (如果键不存
在也会返回 0 )。
 
 
3.当字段不存在时赋值
 
HSETNX key field value
HSETNX 命令与 HSET 命令类似,区别在于如果字段已经存在, HSETNX 命令将不
执行任何操作。
 
4.增加数字
 
HINCRBY key field increment
 
字符串类型的命令 INCRBY HINCRBY 命令与之类似,可以使字段值增加指定的整数。散列类型没有 HINCR 命令,但是可以通过 HINCRBY key field 1来实现。
 
5.删除字段
 
HDEL key field [field …]
HDEL 命令可以删除一个或多个字段,返回值是被删除的字段个数:
6.只获取字段名或字段值
 
HKEYS key
HVALS key
有时仅仅需要获取键中所有字段的名字而不需要字段值,那么可以使用 HKEYS命令,HVALS 命令用来获得键中所有字段值。
 
 
 

五、set(集合)类型

Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL,所以这些操作的时间复杂度都 是O(1)。最方便的是多个集合类型键之间还可以进行并集、交集和差集运算。

1.增加/删除元素
 
SADD key member [member …]
SREM key member [member …] 
 
SADD 命令用来向集合中增加一个或多个元素,如果键不存在则会自动创建。因为在一 个集合中不能有相同的元素,所以如果要加入的元素已经存在于集合中就会忽略这个元素。 本命令的返回值是成功加入的元素数量(忽略的元素不计算在内)。
 
 
2.获得集合中的所有元素
 
SMEMBERS key
SMEMBERS 命令会返回集合中的所有元素
 
 
3.判断元素是否在集合中
 
SISMEMBER key member
 
判断一个元素是否在集合中是一个时间复杂度为 O(1) 的操作,无论集合中有多少个元 素,SISMEMBER 命令始终可以极快地返回结果。当值存在时 SISMEMBER 命令返回 1 ,当值 不存在或键不存在时返回0。
 
 
4.集合间运算
 
SDIFF key [key „]
SINTER key [key „]
SUNION key [key „]
 
1 SDIFF 命令用来对多个集合执行差集运算。集合 A 与集合 B 的差集表示为 A−B ,代表所有属于A 且不属于 B 的元素构成的集合 ,即 A−B ={x | x A x B}
 
 
2 SINTER 命令用来对多个集合执行交集运算。集合 A 与集合 B 的交集表示为 A ∩ B ,代表所有属于A 且属于 B 的元素构成的集合 ,即 A ∩ B ={x | x A x ∈B}
 
3 SUNION 命令用来对多个集合执行并集运算。集合 A 与集合 B 的并集表示为 A B , 代表所有属于A 或属于 B 的元素构成的集合, A B ={x | x A x B}
 
 
 
5.获得集合中元素个数
 
SCARD key
SCARD 命令用来获得集合中的元素个数
 
 
6.进行集合运算并将结果存储
 
SDIFFSTORE destination key [key …]
SINTERSTORE destination key [key …]
SUNIONSTORE destination key [key …]
 
SDIFFSTORE 命令和 SDIFF 命令功能一样,唯一的区别就是前者不会直接返回运算结果, 而是将结果存储在destination 键中。
SDIFFSTORE 命令常用于需要进行多步集合运算的场景中,如需要先计算差集再将结果和其他键计算交集。
SINTERSTORE SUNIONSTORE 命令与之类似,不再赘述。
 
7.随机获得集合中的元素
 
SRANDMEMBER key [count]
SRANDMEMBER 命令用来随机从集合中获取一个元素
 
还可以传递 count 参数来一次随机获得多个元素,根据 count 的正负不同,具体表现也不 同。
1 )当 count 为正数时, SRANDMEMBER 会随机从集合里获得 count 个不重复的元素。
        如果 count 的值大于集合中的元素个数,则 SRANDMEMBER 会返回集合中的全部元素。
2 )当 count 为负数时, SRANDMEMBER 会随机从集合里获得 |count| 个的元素,这些元 素有可能相同。
8.从集合中弹出一个元素
 
SPOP key
由于集合类型的元素是无序的,所以SPOP从集合中随机选择一个元素弹出。
 
 

六、zset(sorted set有序集合)类型

zset 类似于 Java SortedSet HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。它的内部实现用的是一种叫着「跳跃列表」的数据结构。

有序集合类型在某些方面和列表类型有些相似:
 
1 )二者都是有序的。
2 )二者都可以获得某一范围的元素。
 
 但是二者有着很大的区别,这使得它们的应用场景也是不同的:
 
1 )列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,所以它更加适          合实现如“ 新鲜事 日志 这样很少访问中间元素的应用。
2 )有序集合类型是使用散列表和跳跃表( Skip list )实现的,所以即使读取位于中间部分的数据速度也很快(时间复杂度是              O(log(N)) )。
3 )列表中不能简单地调整某个元素的位置,但是有序集合可以(通过更改这个元素 的分数)。
4 )有序集合要比列表类型更耗费内存。
 
 
1.增加元素
 
ZADD key score member [score member …]
ZADD 命令用来向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。ZADD命令的返回值是新加入到集合中的元素个数(不包含之前已经存在的元素),分数不仅可以是整数,还支持双精度浮点数。
 
 
2.获得元素的分数
 
ZSCORE key member
 
 
3.获得排名在某个范围的元素列表
 
ZRANGE key start stop [WITHSCORES]
ZREVRANGE key start stop [WITHSCORES]
 
ZRANGE 命令会按照元素分数从小到大的顺序返回索引从 start stop 之间的所有元素 (包含两端的元素)。ZRANGE 命令与 LRANGE 命令十分相似,如索引都是从 0 开始,负数代表从后向前查找(−1 表示最后一个元素)。
 
 
如果需要同时获得元素的分数的话可以在 ZRANGE 命令的尾部加上 WITHSCORES 参 数,这时返回的数据格式就从“ 元素 1, 元素 2, „, 元素 n” 变为了 元素 1, 分数 1, 元素 2, 分数 2, „, 元素n, 分数 n
 
 
ZRANGE 命令的时间复杂度为 O(log n+m) (其中 n 为有序集合的基数, m 为返回的元素 个数)。
如果两个元素的分数相同, Redis 会按照字典顺序(即 "0"<"9"<"A"<"Z"<"a"<"z" 这样的顺 序)来进行排列。再进一步,如果元素的值是中文怎么处理呢?答案是取决于中文的编码方 式,如使用UTF-8 编码。
 
ZREVRANGE 命令和 ZRANGE 的唯一不同在于 ZREVRANGE 命令是按照元素分数从大到 小的顺序给出结果的。
 
4.获得指定分数范围的元素
 
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
 
ZRANGEBYSCORE 命令参数虽然多,但是都很好理解。该命令按照元素分数从小到大的顺序返回分数在min max 之间(包含 min max )的元素。
 
 
如果希望分数范围不包含端点值,可以在分数前加上 “(” 符号。
5.增加某个元素的分数
 
ZINCRBY key increment member
ZINCRBY 命令可以增加一个元素的分数,返回值是更改后的分数。如果指定的元素不存在,Redis 在执行命令前会先建立它并将它的分数赋为 0 再执行操作。
 
6.获得集合中元素的数量
 
ZCARD key
 
7.获得指定分数范围内的元素个数
 
ZCOUNT key min max
 
8.删除一个或多个元素
 
ZREM key member [member …]
ZREM 命令的返回值是成功删除的元素数量(不包含本来就不存在的元素)。
 
9.按照排名范围删除元素
 
ZREMRANGEBYRANK key start stop
ZREMRANGEBYRANK 命令按照元素分数从小到大的顺序(即索引 0 表示最小的值) 删除处在指定排名范围内的所有元素,并返回删除的元素数量。
 
10.按照分数范围删除元素
 
ZREMRANGEBYSCORE key min max
ZREMRANGEBYSCORE 命令会删除指定分数范围内的所有元素,参数 min max 的特性 和ZRANGEBYSCORE 命令中的一样。返回值是删除的元素数量。
 
11.获得元素的排名
 
ZRANK key member
ZREVRANK key member
ZRANK 命令会按照元素分数从小到大的顺序获得指定的元素的排名(从 0 开始,即分数 最小的元素排名为0),ZREVRANK 命令则相反(分数最大的元素排名为 0 )。
 
12.计算有序集合的交集
 
ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]]
[AGGREGATE
SUM|MIN|MAX]
 
ZINTERSTORE 命令用来计算多个有序集合的交集并将结果存储在 destination 键中(同样 以有序集合类型存储),返回值为destination 键中的元素个数。
 
destination键中元素的分数是由 AGGREGATE 参数决定的:
 
1 )当 AGGREGATE SUM 时(也就是默认值), destination 键中元素的分数是每个参与计算的集合中该元素分数的和。
2 )当 AGGREGATE MIN 时, destination 键中元素的分数是每个参与计算的集合中该元素分数的最小值。
3 )当 AGGREGATE MAX 时, destination 键中元素的分数是每个参与计算的集合中该元素分数的最大值。
 
ZINTERSTORE 命令还能够通过 WEIGHTS 参数设置每个集合的权重,每个集合在参与计算时元素的分数会被乘上该集合的权重。
 
另外还有一个命令与 ZINTERSTORE 命令的用法一样,名为 ZUNIONSTORE ,它的作用是计算集合间的并集

 

七、容器型数据结构的通用规则

list/set/hash/zset 这四种数据结构是容器型数据结构,它们共享下面两条通用规则:
 
1 create if not exists

如果容器不存在,那就创建一个,再进行操作。比如 rpush 操作刚开始是没有列表的, Redis 就会自动创建一个,然后再 rpush 进去新元素。

2 drop if no elements

如果容器里元素没有了,那么立即删除元素,释放内存。这意味着 lpop 操作到最后一 个元素,列表就消失了。

过期时间

Redis 所有的数据结构都可以设置过期时间,时间到了,Redis 会自动删除相应的对象。 需要注意的是过期是以对象为单位,比如一个 hash 结构的过期是整个 hash 对象的过期, 而不是其中的某个子 key。 还有一个需要特别注意的地方是如果一个字符串已经设置了过期时间,然后你调用了 set 方法修改了它,它的过期时间会消失。

发布了22 篇原创文章 · 获赞 10 · 访问量 6125

猜你喜欢

转载自blog.csdn.net/qq_28681387/article/details/105420036
今日推荐