ITPub博客

Redis(2)- 基本数据结构和操作

原创 NoSQL 作者:zhuyiquan90 时间:2018-06-28 18:22:06 0 删除 编辑

Redis的一个特点就是处理基本字符串,还支持多种数据结构,包括Hash,List,Set,SortedSet。本章主要介绍Redis的数据结构和基本操作,并给出一些典型的使用场景。

感谢《Redis 命令参考》中文版对本文的指导!



1. 字符串String

字符串操作是Redis最基础的操作。是二进制安全的。无需担心特殊字符是否可用,没有限制,底层是二进制存储。从内部实现来看,其实String可以看作byte数组,所以Redis的String可以包含任何数据:字符串、序列化对象或文件。

Redis的其他类型List、Set、Sorted Set 、Hash,它们包含的元素本质上都是string类型。

基本结构

一个String类型的key、value最大上限均是512M。其基本结构如下: 
这里写图片描述

基本语法

Redis中字符串的基本操作如下表所示。

操作 语法 说明
APPEND APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。
BITCOUNT BITCOUNT key [start] [end] 计算给定字符串中,被设置为 1 的比特位的数量
BITOP BITOP operation destkey key [key …] 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
DECR DECR key 将 key 中储存的数字值减一。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
DECRBY DECRBY key decrement 将 key 所储存的值减去减量 decrement 。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECRBY 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
GET GET key 返回 key 所关联的字符串值。如果 key 不存在那么返回特殊值 nil 。假如 key 储存的值不是字符串类型,返回一个错误,因为 GET 只能用于处理字符串值。
GETBIT GETBIT key offset 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。当 offset 比字符串值的长度大,或者 key 不存在时,返回 0 。
INCR INCR key 将 key 中储存的数字值增一。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
INCRBY INCRBY key increment 将 key 所储存的值加上增量 increment 。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
INCRBYFLOAT INCRBYFLOAT key increment 为 key 中所储存的值加上浮点数增量 increment
MGET MGET key [key …] 返回所有(一个或多个)给定 key 的值。如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。
MGET MGET key [key …] 返回所有(一个或多个)给定 key 的值。如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。
MSET MSET key value [key value …] 同时设置一个或多个 key-value 对。MSET 是一个原子性(atomic)操作
MSETNX MSETNX key value [key value …] 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。即使只有一个给定 key 已存在, MSETNX 也会拒绝执行所有给定 key 的设置操作。
PSETEX PSETEX key milliseconds value 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
SET SET key value [EX seconds] [PX milliseconds] [NX/XX] 将字符串值 value 关联到 key 。如果 key 已经持有其他值, SET 就覆写旧值,无视类型。对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。
SETBIT SETBIT key offset value 设置偏移量值,对使用大的 offset 的 SETBIT 操作来说,内存分配可能造成 Redis 服务器被阻塞。
SETEX SETEX key seconds value 将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。
SETNX SETNX key value SET if Not Exist
SETRANGE SETRANGE key offset value 用 value 参数覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始。 当生成一个很长的字符串时,Redis 需要分配内存空间,该操作有时候可能会造成服务器阻塞(block)。
STRLEN STRLEN key 返回 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。

举一些例子:

  • MGET & MSET
127.0.0.1:6379> mset date "2016-7-14" time "17:34" weather "rain" OK 127.0.0.1:6379> mget date time weather 1) "2016-7-14" 2) "17:34" 3) "rain"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • SETEX
127.0.0.1:6379> setex date 60 "2016-7-14" OK 127.0.0.1:6379> get date "2016-7-14" 127.0.0.1:6379> ttl date (integer) 46 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • STRLEN
127.0.0.1:6379> strlen nonexist
(integer) 0 127.0.0.1:6379> set date "2016-7-15" OK 127.0.0.1:6379> strlen date (integer) 9 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

使用场景-统计用户上线天数

Bitmap 对于一些特定类型的计算非常有效。

假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 SETBIT 和 BITCOUNT 来实现。

比如说,每当用户在某一天上线的时候,我们就使用 SETBIT ,以用户名作为 key ,将那天所代表的网站的上线日作为 offset 参数,并将这个 offset 上的为设置为 1 。

举个例子,如果今天是网站上线的第 100 天,而用户 peter 在今天阅览过网站,那么执行命令 SETBIT peter 100 1 ;如果明天 peter 也继续阅览网站,那么执行命令 SETBIT peter 101 1 ,以此类推。

当要计算 peter 总共以来的上线次数时,就使用 BITCOUNT 命令:执行 BITCOUNT peter ,得出的结果就是 peter 上线的总天数。

2. 列表List

list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。这使得list既可以用作栈,也可以用作队列

基本结构

这里写图片描述

基本语法

操作 语法 说明
BLPOP BLPOP key [key …] timeout BLPOP 是列表的阻塞式(blocking)弹出原语.它是 LPOP 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被 BLPOP 命令阻塞.
BRPOP BRPOP key [key …] timeout 它是 RPOP 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被 BRPOP 命令阻塞.
BRPOPLPUSH BRPOPLPUSH source destination timeout BRPOPLPUSH 是 RPOPLPUSH 的阻塞版本,当给定列表 source 不为空时, BRPOPLPUSH 的表现和 RPOPLPUSH 一样。当列表 source 为空时, BRPOPLPUSH 命令将阻塞连接,直到等待超时,或有另一个客户端对 source 执行 LPUSH 或 RPUSH 命令为止。
LINDEX LINDEX key index 返回列表 key 中,下标为 index 的元素。
LINSERT LINSERT key BEFORE/AFTER pivot value 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。当 pivot 不存在于列表 key 时,不执行任何操作。当 key 不存在时, key 被视为空列表,不执行任何操作。如果 key 不是列表类型,返回一个错误。
LLEN LLEN key 返回列表 key 的长度。
LPOP LPOP key 移除并返回列表 key 的头元素。
LPUSH LPUSH key value [value …] 将一个或多个值 value 插入到列表 key 的表头
LPUSHX LPUSHX key value 将值 value 插入到列表 key 的表头,当且仅当 key 存在并且是一个列表
LRANGE LRANGE key start stop 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定
LREM LREM key count value 根据参数 count 的值,移除列表中与参数 value 相等的元素
LSET LSET key index value 将列表 key 下标为 index 的元素的值设置为 value
LTRIM LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。举个例子,执行命令 LTRIM list 0 2 ,表示只保留列表 list 的前三个元素,其余元素全部删除。
RPOP RPOP key 移除并返回列表 key 的尾元素
RPOPLPUSH RPOPLPUSH source destination 命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作:将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。
RPUSH RPUSH key value [value …] 将一个或多个值 value 插入到列表 key 的表尾(最右边)
RPUSHX RPUSHX key value 将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表。和 RPUSH 命令相反,当 key 不存在时, RPUSHX 命令什么也不做。

举一些例子:

127.0.0.1:6379> lpush stack "a" "b" "c" (integer) 3 127.0.0.1:6379> rpop stack "a"
  • 1
  • 2
  • 3
  • 4
  • 队列
127.0.0.1:6379> lpush queue "a" "b" "c" (integer) 3 127.0.0.1:6379> lpop queue "c" 
  • 1
  • 2
  • 3
  • 4
  • 5
  • BLPOP
127.0.0.1:6379> exists job
(integer) 0 127.0.0.1:6379> blpop job 5 #一直阻塞到5s超时 (nil)
(5.03s)
  • 1
  • 2
  • 3
  • 4
  • 5
  • LINDEX
127.0.0.1:6379> lpush myjob "my" "job" "is" "iter" (integer) 4 127.0.0.1:6379> lindex myjob -1 "my"
  • 1
  • 2
  • 3
  • 4

使用场景-事件提醒

有时候,为了等待一个新元素到达数据中,需要使用轮询的方式对数据进行探查。

另一种更好的方式是,使用系统提供的阻塞原语,在新元素到达时立即进行处理,而新元素还没到达时,就一直阻塞住,避免轮询占用资源。

对于 Redis ,我们似乎需要一个阻塞版的 SPOP 命令,但实际上,使用 BLPOP 或者 BRPOP 就能很好地解决这个问题。

使用元素的客户端(消费者)可以执行类似以下的代码:

LOOP forever
    WHILE SPOP(key) returns elements ... process elements ... END
    BRPOP helper_key
END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

添加元素的客户端(消费者)则执行以下代码:

MULTI
    SADD key element LPUSH helper_key x
EXEC
  • 1
  • 2
  • 3
  • 4

3. 哈希表Hash

存储的是一个field与value的映射表,即存储的是一个Map,每一条数据可以看做是key-field-value的格式,field-value对应的是Map的一个键值对。

基本结构

这里写图片描述

基本语法

操作 语法 说明
HDEL HDEL key field [field …] 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略
HEXISTS HEXISTS key field 查看哈希表 key 中,给定域 field 是否存在
HGET HGET key field 返回哈希表 key 中给定域 field 的值。
HGETALL HGETALL key 返回哈希表 key 中,所有的域和值
HINCRBY HINCRBY key field increment 为哈希表 key 中的域 field 的值加上增量 increment
HINCRBYFLOAT HINCRBYFLOAT key field increment 为哈希表 key 中的域 field 加上浮点数增量 increment
HKEYS HKEYS key 返回哈希表 key 中的所有域Field
HLEN HLEN key 返回哈希表 key 中域的数量
HMGET HMGET key field [field …] 返回哈希表 key 中,一个或多个给定域的值
HMSET HMSET key field value [field value …] 同时将多个 field-value (域-值)对设置到哈希表 key 中
HSET HSET key field value 将哈希表 key 中的域 field 的值设为 value
HSETNX HSETNX key field value 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。
HVALS HVALS key 返回哈希表 key 中所有域的值
HSCAN SCAN key cursor [MATCH pattern] [COUNT count] SCAN 命令及其相关的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代(incrementally iterate)一集元素(a collection of elements)

举个例子

127.0.0.1:6379> hmset hash hashfield1 value1 hashfield2 value2
OK 127.0.0.1:6379> hget hash hashfield2 "value2" 127.0.0.1:6379> hkeys hash 1) "hashfield1" 2) "hashfield2" 127.0.0.1:6379> hlen hash (integer) 2 127.0.0.1:6379> hvals hash 1) "value1" 2) "value2" 127.0.0.1:6379> hgetall hash 1) "hashfield1" 2) "value1" 3) "hashfield2" 4) "value2"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

使用场景-存储社交关系

比如新浪的关注列表, 粉丝列表都是由hash实现的。

4. 集合Set

set是string类型的无序集合,集合中最大可以包含(2的32次方-1)个元素。set可以看做是value为空的hash结构,所以不会出现重复的元素。set提供集合的并集(union)、交集(intersection)、差集(difference)的方法,通过这些操作可以很容易的实现sns中的好友推荐和blog的tag功能。

基本结构

这里写图片描述

基本语法

操作 语法 说明
SADD SADD key member [member …] 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略.
SCARD SCARD key 返回集合 key 的基数(集合中元素的数量).
SDIFF SDIFF key [key …] 返回一个集合的全部成员,该集合是所有给定集合之间的差集.
SDIFFSTORE SDIFFSTORE destination key [key …] 这个命令的作用和 SDIFF 类似,但它将结果保存到 destination 集合,而不是简单地返回结果集.
SINTER SINTER key [key …] 返回一个集合的全部成员,该集合是所有给定集合的交集.
SINTERSTORE SINTERSTORE destination key [key …] 这个命令类似于 SINTER 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集.
SISMEMBER SISMEMBER key member 判断 member 元素是否集合 key 的成员.
SMEMBERS SMEMBERS key 返回集合 key 中的所有成员.
SMOVE SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合.
SPOP SPOP key 移除并返回集合中的一个随机元素.
SRANDMEMBER SRANDMEMBER key [count] 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值.
SREM SREM key member [member …] 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略.
SUNION SUNION key [key …] 返回一个集合的全部成员,该集合是所有给定集合的并集.
SUNIONSTORE SUNIONSTORE destination key [key …] 这个命令类似于 SUNION 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集.
SSCAN SSCAN key cursor [MATCH pattern] [COUNT count] 详细信息请参考 SCAN 命令.

举一些例子

  • 差集
127.0.0.1:6379> sadd set1 "a1" "a2" "a3" (integer) 3 127.0.0.1:6379> sadd set2 "a1" "a3" "a4" (integer) 3 127.0.0.1:6379> sdiff set1 set2 1) "a2" 127.0.0.1:6379> sdiffstore set set1 set2
(integer) 1 127.0.0.1:6379> smembers set 1) "a2" 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 并集
127.0.0.1:6379> sadd set1 "a1" "a2" "a3" (integer) 3 127.0.0.1:6379> sadd set2 "a1" "a3" "a4" (integer) 3 127.0.0.1:6379> sunion set1 set2 1) "a4" 2) "a1" 3) "a3" 4) "a2" 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 交集
127.0.0.1:6379> sadd set1 "a1" "a2" "a3" (integer) 3 127.0.0.1:6379> sadd set2 "a1" "a3" "a4" (integer) 3 127.0.0.1:6379> smembers set 1) "a2" 127.0.0.1:6379> sinter set1 set2 1) "a3" 2) "a1" 127.0.0.1:6379> sinterstore set set1 set2
(integer) 2 127.0.0.1:6379> smembers set 1) "a1" 2) "a3" 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

使用场景-共同好友

  • 共同好友、二度好友
  • 利用唯一性,可以统计访问网站的所有独立 IP
  • 好友推荐的时候,根据 tag 求交集,大于某个 threshold 就可以推荐

5. 有序集合SortedSet

和set一样sorted set也是string类型元素的集合,不同的是每个元素都会关联一个double类型的score,所以sorted set是一个有序的集合。

基本结构

这里写图片描述

基本语法

操作 语法 说明
ZADD ZADD key score member [[score member] [score member] …] 将一个或多个 member 元素及其 score 值加入到有序集 key 当中.
ZCARD ZCARD key 返回有序集 key 的基数.
ZCOUNT ZCOUNT key min max 返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量.
ZINCRBY ZINCRBY key increment member 为有序集 key 的成员 member 的 score 值加上增量 increment.
ZRANGE ZRANGE key start stop [WITHSCORES] 返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序.
ZRANGEBYSCORE ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
ZRANK ZRANK key member 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。
ZREMRANGEBYRANK ZREMRANGEBYRANK key start stop 移除有序集 key 中,指定排名(rank)区间内的所有成员。
ZREMRANGEBYSCORE ZREMRANGEBYSCORE key min max 移除有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。
ZREVRANGEBYSCORE ZREVRANGE key start stop [WITHSCORES] 返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。
ZREVRANK ZREVRANK key member 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。
ZSCORE ZSCORE key member 返回有序集 key 中,成员 member 的 score 值。
ZUNIONSTORE ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM/MIN/MAX] 计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并将该并集(结果集)储存到 destination 。默认情况下,结果集中某个成员的 score 值是所有给定集下该成员 score 值之 和。
ZINTERSTORE ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM/MIN/MAX] 计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。默认情况下,结果集中某个成员的 score 值是所有给定集下该成员 score 值之和.
ZSCAN ZSCAN key cursor [MATCH pattern] [COUNT count] 详细信息请参考 SCAN 命令.

举一些例子

127.0.0.1:6379> zadd salary 2500 jack
(integer) 1 127.0.0.1:6379> zadd salary 500 tom
(integer) 1 127.0.0.1:6379> zadd salary 1500 bob
(integer) 1 127.0.0.1:6379> zrangebyscore salary 500 2500 1) "tom" 2) "bob" 3) "jack" 127.0.0.1:6379> zrange salary 1 3 1) "bob" 2) "jack" 127.0.0.1:6379> zrange salary 0 3 1) "tom" 2) "bob" 3) "jack" 127.0.0.1:6379> zrevrange salary 0 3 withscores 1) "jack" 2) "2500" 3) "bob" 4) "1500" 5) "tom" 6) "500"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

使用场景-用户得分排行榜

和Sets相比,Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,比如一个存储全班同学成绩的 Sorted Sets,其集合 value 可以是同学的学号,而 score 就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。另外还可以用 Sorted Sets 来做带权重的队列,比如普通消息的 score 为1,重要消息的 score 为2,然后工作线程可以选择按 score 的倒序来获取工作任务。让重要的任务优先执行。 
带有权重的元素,比如一个游戏的用户得分排行榜

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31541037/viewspace-2157000/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-06-07

  • 博文量
    21
  • 访问量
    4188