共计 13136 个字符,预计需要花费 33 分钟才能阅读完成。
Redis 是开源的高性能内存 Key-Value 数据库, 可以提供事务和持久化支持, 并提供了 TTL(time to life)服务。
Redis 采用单线程数据操作 + 非阻塞 IO 的模型,非阻塞 IO 提供了较高的 IO 性能,单线程操作保证了单条指令的原子性。
Redis 使用简单灵活性能优异,常被用作缓存,分布式锁或者消息队列。
非特殊说明,本文以 Redis 3.0 为标准进行介绍。
- Redis 数据结构
- string
- SET
- GET
- MGET
- MSET
- MSETNX
- TYPE
- INCR,DECR
- INCRBY,DECRBY
- INCRBYFLOAT
- key
- DEL
- KEYS
- EXISTS
- RENAME
- RENAMENX
- EXPIRE
- EXPIREAT
- TTL
- PERSIST
- list
- LPUSH
- RPUSH
- LLEN
- LRANGE
- LINDEX
- LINSERT
- LREM
- LTRIM
- LSET
- LPOP, RPOP
- set
- SADD
- SSCARD
- SMEMBERS
- SISMEMBER
- SREM
- SINTER, SUNION, SDIFF
- SINTERSTORE, SUNIONSTORE, SDIFFSTORE
- SPOP
- SRANDMEMBER
- hash
- HSET
- HSETNX
- HGET
- HMSET
- HMGET
- HDEL
- HLEN
- HEXISTS
- HKEYS
- HVALS
- HGETALL
- HINCRBY, HINCRBYFLOAT
- zset
- ZADD
- ZREM
- ZCARD
- ZCOUNT
- ZRANGE, ZREVRANGE
- ZRANGEBYSCORE, ZREVRANGEBYSCORE
- ZRANK, ZREVRANK
- ZINCRBY
- string
- Redis 应用进阶
- 事务
- pipeline
- 发布订阅
- SCAN
- HyperLogLog
Ubuntu 系统可以用包管理器安装 Redis 服务:
sudo apt-get install redis-server
并安装客户端:
sudo apt-get install redis-tools
进入 Redis 客户端
redis-cli
登录远程 Redis 服务
redis-cli -h host -p port -a password
Redis 数据结构
通常情况下,在 Redis 中若 key 或 field 不存在则会作为空集合处理 (写操作会将先初始化为空集合) 不会抛出错误,若 key 指向了其它类型则会出现错误。
Redis 中的线性集合 (list 和 zset) 的下标以 0 为底,且支持负数下标。即 0 指向第一个元素,1 指向第二个元素,- 1 指向最后一个元素,- 2 指向倒数第二个元素。
线性集合通常用 start 和 stop 参数表示一个子序列,序列为闭区间即包含 start 和 stop 指向的元素(这点与很多编程语言不同)。
string
string 是 Redis 中的基本类型。除了增删改查之外,Redis 提供了 STRLEN,APPEND 等简单字符串操作。
Redis 没有专用的整数类型,所以 key 内储存的 string 可以被解释为十进制 64 位有符号整数进行计算。
字符串也可以解释为双精度浮点数,在作为浮点数时计算结果时最大保留 17 位小数,自动去除小数部分尾随的 0,必要时还会将浮点数改为整数 (比如 3.0 会被保存成 3)。浮点数可以使用像2.0e7
、3e5
、90e-2
这样的指数符号来表示。
string 的算术操作可以让我们方便的实现锁和计数器等功能。
SET
SET key value [EX seconds] [PX milliseconds] [NX|XX]
SET one 1
SET one 1 XX
SET two 2 NX
将 key 指向字符串值 value,若不存在 key 则新建键值对,若 key 存在默认情况下会覆盖旧值,无视旧值的类型。
SET 设置成功会返回 OK,失败会返回 nil。
SET key value NX
只有在 key 不存在时才会设置,若 key 已存在则不进行任何操作。
SET key value XX
只有 key 存在时才会设置,若 key 不存在则不进行任何操作。
SET key value EX second
: 设置键的过期时间为 second 秒。
SET key value PX millisecond
: 设置键的过期时间为 millisecond 毫秒。
因为 SET 命令可以通过参数来实现 SETNX、SETEX 和 PSETEX 三个命令的效果,Redis 官方称可能在将来的版本中废弃并最终移除 SETNX、SETEX 和 PSETEX 这三个命令。
GET
GET key
GET one
返回 key 所关联的字符串值,若 key 不存在返回 nil, 若 key 指向其它数据类型则会返回一个错误信息。
MGET
MGET key [key key ...]
返回所有 (一个或多个) 给定 key 的值。若其中有某个 key 不存在或指向其它类型,那么这个 key 返回 nil。
MSET
MSET key value [key value ...]
MSET one 1 two 2
同时设置一个或多个 key-value 对, 如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值。该命令不会返回错误信息,总是返回 OK。
和其它指令一样,该操作是原子性的。
MSETNX
MSETNX key value [key value ...]
MSET one 1 two 2
同时设置一个或多个 key-value 对, 如果某个给定 key 已经存在,那么 MSETNX
不会设置任何一个 key-value。
该操作是原子性的,要么全部设置要么全不被设置。
TYPE
TYPE key
返回 key 指向的类型:
- none: key 不存在
- string: 字符串
- list: 列表
- set: 集合
- zset: 有序集
- hash: 哈希表
INCR,DECR
INCR key
DECR key
INCR 命令将 key 中储存的数字值增 1, 若 key 不存在则先被初始化为 0,然后再执行操作。返回操作后 key 指向的值。
若值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
类似地有 DECR 命令,用于将存储的数字减 1。
INCRBY,DECRBY
INCRBY key value
INCRBY count 2
DECRBY count 3
将 key 所储存的值加上增量 value, 返回操作后的值。value 可以为 0 或负值。
若值包含错误的类型,或字符串类型的值不能表示为整数,那么返回一个错误。
类似地有 DECRBY 用于将存储的数字减去给定值。
INCRBYFLOAT
INCRBYFLOAT key value
INCRBYFLOAT one 1.23
将 key 所储存的值加上浮点增量 value, 返回操作后的值。value 可以为 0 或负值。
若值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
目前版本的 Redis 中没有 DECRBYFLOAT 指令,可以使用加负数进行减运算。
key
本节介绍对 key 通用的操作。
DEL
DEL key [key ...]
DEL one two
删除给定的一个或多个 key, 不存在的 key 将会忽略返回被删除的 key 的数量。
KEYS
KEYS pattern
KEYS *
查找所有符合给定模式 pattern 的 key:
KEYS *
: 匹配数据库中所有 key。KEYS h?llo
: 匹配 hello,hallo 和 hxllo 等。KEYS h*llo
: 匹配 hllo 和 heeeeello 等。KEYS h[ae]llo
: 匹配 hello 和 hallo,但不匹配 hillo。
EXISTS
EXISTS key
EXISTS one
检查给定 key 是否存在, 若存在返回 1,否则返回 0。
RENAME
RENAME key newkey
RENAME one ONE
将 key 改名为 newkey, 当 newkey 已经存在时,RENAME 命令将覆盖旧值。成功时返回 OK,失败时返回一个错误。
当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。
RENAMENX
RENAMENX key newkey
RENAMENX one ONE
当 newkey 不存在时,将 key 改名为 newkey。成功时返回 1,若 newkey 已存在返回 0。
EXPIRE
EXPIRE key seconds
EXPIRE one 1000
为给定 key 设置生存时间(TTL),当 key 过期时(生存时间为 0),它会被自动删除。
使用 SET 命令等覆盖一个键值对将会移除 TTL, 但是 INCR,LPUSH,HSET 等命令不会修改生存时间。
RENAME 命令不会修改生存时间,若 RENAME key key2
命令使得 key 覆盖了带有 TTL 的 key2, 那么新的 key2 的生存时间设置和原来的 key 相同。
PEXPIRE 命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间。
EXPIREAT
EXPIREAT key timestamp
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。
不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳。
PEXPIREAT 和 EXPIREAT 命令类似,但它的参数是以毫秒为单位的 unix 时间戳。
TTL
TTL key
以秒为单位,返回给定 key 的剩余生存时间,当 key 不存在时,返回 -2,当 key 存在但没有设置剩余生存时间时,返回 -1。
PTTL 命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间。
PERSIST
PERSIST key
移除给定 key 的生存时间设置,使其成为永久的 key。
当生存时间移除成功时,返回 1。如果 key 不存在或 key 没有设置生存时间,返回 0。
list
列表 (list) 是一个线性容器,可以根据下标访问元素。
Redis 中 list 的元素只能是字符串,不支持其它类型。
LPUSH
LPUSH key value1 value2
LPUSH arr a b c
将一个或多个值 value 插入到列表 key 的头部(左侧),返回操作后列表的长度。
如果 key 不存在,将会创建一个空列表并执行 LPUSH 操作,当 key 存在但不是列表类型时,返回一个错误。
对空列表 arr
执行 LPUSH arr a b c
指令后,arr
的内容为 c b a
。相当于原子性的执行了LPUSH arr a
, LPUSH arr b
, LPUSH arr c
三条指令。
RPUSH
RPUSH key value1 value2
RPUSH arr a b c
将一个或多个值 value 插入到列表 key 的尾部(左侧),返回操作后列表的长度。
如果 key 不存在,将会创建一个空列表并执行 RPUSH 操作,当 key 存在但不是列表类型时,返回一个错误。
对空列表 arr
执行 RPUSH arr a b c
指令后,arr
的内容为 a b c
。相当于原子性的执行了RPUSH arr a
, RPUSH arr b
, RPUSH arr c
三条指令。
LLEN
LLEN key
返回列表的长度,若 key 不存在返回 0,若 key 指向其它类型则返回一个错误。
LRANGE
LRANGE key start stop
LRANGE arr 0 -1
返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。
下标以 0 为底,即 0 表示列表中的第一个元素,1 表示第二个元素。也可以使用负数下标,- 1 表示最后一个元素,- 2 表示倒数第二个元素。
stop 下标也在 LRANGE 命令的取值范围之内 (闭区间),LRANGE arr 0 2
会返回下标为 0,1,2 的三个元素。
超出范围的下标值不会引起错误,如果 start 比列表的最大下标还要大那么返回一个空列表,如果 stop 下标比最大下标还要大,stop 的值将被设为最大下标。
LINDEX
LINDEX key index
返回列表 key 中,下标为 index 的元素。若 index 超出范围或者 key 指向空列表 (key 不存在) 则会返回 nil, 若 key 指向其它类型则返回错误。
下标以 0 为底,即 0 表示列表中的第一个元素,1 表示第二个元素。也可以使用负数下标,- 1 表示最后一个元素,- 2 表示倒数第二个元素。
LINSERT
LINSERT key BEFORE|AFTER pivot value
RPUSH arr "World"
LINSERT arr BEFORE "World" "HELLO"
将值 value 插入到列表 key 中,位于值 pivot 之前或之后。当 pivot 不存在于列表 key 时,不执行任何操作。当 key 不存在时,key 被视为空列表,不执行任何操作。
如果命令执行成功,返回插入操作完成之后列表的长度。如果没有找到 pivot 返回 -1,如果 key 不存在或为空列表,返回 0。
LREM
LREM key count value
根据参数 count 的值,移除列表中与参数 value 相等的元素,返回被移除元素的数量。
count 的值可以是以下几种:
- count > 0: 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count。
- count < 0: 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
- count = 0: 移除表中所有与 value 相等的值。
LTRIM
LTRIM key start stop
让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除, start 和 stop 指定区间的规则与 LRANGE 相同。
若删除成功或 key 不存在则返回 OK,若 key 指向其它类型则返回错误。
LSET
LSET key index value
将列表 key 中下标为 index 的元素的值设置为 value,下标以 0 为底,可以使用负数下标。
当 index 参数超出范围,或对一个空列表 (key 不存在或指向其它类型) 进行 LSET 时,返回一个错误。
LPOP, RPOP
LPOP key
移除并返回列表 key 的头元素, key 不存在时返回 nil。key 指向其它类型时返回错误。
类似地有 RPOP
命令,移除并返回列表 key 的尾元素。
set
集合 (set) 是一种无序容器,不存在重复元素,可以用于判断元素是否存在或者进行交并差运算。
Redis 中集合的元素类型只能是字符串,不支持其它类型。
SADD
SADD key member [member ...]
将一个或多个 member 元素加入到集合 key 当中,返回添加到集合中新元素的数量,已经存在于集合的元素将被忽略。
若 key 不存在先初始化一个空集合然后添加成员,若 key 指向了非集合类型则会产生错误。
SSCARD
SSCARD key
返回集合中元素的数量,key 不存在时返回 0,key 指向其它类型时返回一个错误。
SMEMBERS
SMEMBERS key
返回 key 指向的集合中的所有成员,若 key 不存在返回空集,若 key 指向其它类型则返回一个错误。
SISMEMBER
SISMEMBER key member
判断 member 元素是否集合 key 的成员, 若元素是集合的成员返回 1,若元素不是集合的成员或者集合不存在则返回 0。
若 key 指向其它类型则返回一个错误。
SREM
SREM key member [member ...]
移除集合中的一个或多个元素,不存在的元素会被忽略,返回被成功移除的元素的个数。
若 key 不存在则作为空集处理,返回 0。若 key 指向其它类型则返回一个错误。
SINTER, SUNION, SDIFF
SINTER key [key ...]
SUNION key [key ...]
SDIFF key [key ...]
返回给定集合的交集 (SINTER),并集(SUNION) 和差集(SDIFF),若 key 不存在则作为空集处理,若 key 指向其它类型则返回一个错误。
SINTERSTORE, SUNIONSTORE, SDIFFSTORE
SINTER dest key [key ...]
SUNION dest key [key ...]
SDIFF dest key [key ...]
计算给定集合的交集 (SINTERSTORE),并集(SUNIONSTORE) 和差集(SDIFFSTORE),并将结果存入 dest 集合,若 dest 集合已存在则将其覆盖。
若 key 不存在则作为空集处理,若 key 指向其它类型则返回一个错误。
dest 可以是某个参与计算的 key,dest 可以指向其它类型,计算结束后 dest 中的值会被覆盖。
SPOP
SPOP key
SPOP
移除并返回集合中的一个随机元素,当 key 不存在或 key 是空集时返回 nil,若 key 指向其它类型则返回一个错误。
SRANDMEMBER
SRANDMEMBER key [count]
若只提供了 key 参数,那么返回集合中的一个随机元素。
当 key 不存在或 key 是空集时返回 nil,若 key 指向其它类型则返回一个错误。
若提供了 count 参数:
- 若 count 为正数,且小于集合基数,那么返回一个包含 count 个元素的数组,数组中的元素各不相同。
- 若 count 大于等于集合中元素数,那么返回整个集合。
- 若 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。
hash
哈希表 (hash) 是 key-value 结构, key 和 value 的类型为字符串。
HSET
HSET key field value
将哈希表 key 中的域 field 的值设为 value。
如果 key 不存在,将创建一个新的哈希表并进行 HSET
操作。如果域 field 已经存在于哈希表中,旧值将被覆盖。
若 HSET
设置了一个新域则返回 1,若覆盖了一个已有的域则返回 0。
HSETNX
HSETNX key field value
将哈希表 key 中的域 field 的值设为 value。
如果 key 不存在,将创建一个新的哈希表并进行 HSET 操作。如果域 field 已经存在于哈希表中,则不进行任何操作。
若 HSETNX
设置了一个新域则返回 1,若域已经存在则返回 0。
HGET
HGET key field
返回哈希表 key 中指定域 field 的值,若哈希表 key 不存在或其域 field 不存在则返回 nil。
HMSET
HMSET key field value [field value ...]
同时将多个 field-value(域 - 值)对设置到哈希表 key 中。若 field 已存在则会被覆盖。
若 key 不存在,则创建一个空哈希表并执行 HMSET 操作
HMGET
HMGET key field [field ...]
返回哈希表 key 中一个或多个给定域的值,若 field 不存在则返回 nil。
若 key 不存在则作为空哈希表处理,每个 field 都会返回一个 nil 值。
HDEL
HDEL key field [field ...]
删除哈希表 key 中一个或多个指定域,不存在的域将被忽略,返回实际被删除域的数目。
HLEN
HLEN key
返回哈希表 key 中域的数量,若 key 不存在则返回 0。
HEXISTS
HEXISTS key field
判断哈希表 key 中域 field 是否存在,若存在返回 1。若哈希表 key 不存在或其中不存在域 field 则返回 0。
HKEYS
HKEYS key
以列表的形式返回哈希表 key 中所有域的名称。
HVALS
HVALS key
返回哈希表 key 中所有域的值。
HGETALL
HGETALL key
以列表的形式返回哈希表 key 中所有的键和值,前一个元素为键其后的元素为它的值。
> HMSET hash a 1 b 2
OK
> HGETALL hash
1) "a"
2) "1"
3) "b"
4) "2"
HINCRBY, HINCRBYFLOAT
HINCRBY key field increment
为哈希表 key 中的域 field 的值加上增量 increment, 增量可以为负数进行减法操作。
若哈希表中不存在域 field 则现将该域初始化为 0,然后进行加法操作。
若哈希表 key 不存在,则将创建一个空哈希表,然后按上一条规则执行。
若 key 指向其它类型或域的值不能解释为整数则返回一个错误。
类似地,HINCRBYFLOAT
可以进行浮点数运算。
zset
有序集合 (SortedSet, zset) 是一种特殊的集合类型,它不允许重复元素,可以根据每个元素的 score 进行排序。
ZADD
ZADD key [NX|XX] [FH] [INCR] score member [[score member] [score member] ...]
将一个或多个 member 元素及其 score 值加入到有序集 key 当中, 若元素已经在集合中则更新它的 score,score 值可以是整数值或浮点数。
返回新添加的元素的数量,不包括被更新的元素的数量。
当 key 存在但不是有序集类型时,返回一个错误。
ZADD 命令支持一些选项:
-
NX: 不更新存在的成员,仅添加新成员
-
XX: 不添加新成员,仅更新存在的成员
-
CH: 修改返回值为发生变化的成员总数,原始是返回新添加成员的总数(CH=changed)
-
INCR: 对成员的值进行增加操作而不是设置操作,等同于
ZINCRBY
命令
ZREM
ZREM key member [member ...]
移除有序集 key 中的一个或多个成员,不存在的成员将被忽略, 返回实际被移除的元素数量。
当 key 存在但不是有序集类型时,返回一个错误。
ZCARD
ZCARD key
返回有序集 key 中元素的数目,若 key 不存在则返回 0,若 key 指向其它类型则返回一个错误。
ZCOUNT
ZCOUNT key min max
返回有序集 key 中,score 值在 min 和 max 之间 (包括等于 min 或 max) 的元素数量。
ZRANGE, ZREVRANGE
ZRANGE key start stop [WITHSCORES]
返回有序集 key 中,指定区间内的成员。start 和 stop 用于指定元素的排名,它们以 0 为底且支持负下标,指定的是闭区间。
即 0 代表集合中 score 最小的元素,- 1 代表最大的元素。
其中成员的位置按 score 值递增 (从小到大) 来排序, 具有相同 score 值的成员按字典序来排列。
ZRANGE key 0 -1
可以返回集合中所有元素递增排列的序列。
若 start 的值大于集合中元素的个数 或者 start 大于 stop 值 则返回一个空列表;若 stop 大于集合中元素的个数则当做该集合的最大下标处理。
默认情况下 ZRANGE 命令仅返回元素,若添加了 WITHSCORES 选项则会将 score 一并返回。返回列表中元素和 score 成对出现,前一个为元素后一个为 score。
> zrange z 0 -1
1) "a"
2) "b"
3) "c"
> zrange z 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "5"
类似地,ZREVRANGE 指令按照 score 递减排序(从大到小)。
ZRANGEBYSCORE, ZREVRANGEBYSCORE
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集 key 中 score 在 min 和 max(包括等于 min 和 max)之间的的元素,按照 score 值递增排列。
默认情况下 ZRANGEBYSCORE
命令仅返回元素,若添加了 WITHSCORES 选项则会将 score 一并返回。返回列表中元素和 score 成对出现,前一个为元素后一个为 score。
可选的 LIMIT 参数指定返回结果的数量及区间,类似于 SQL 中的SELECT offset, count
,offset 为跳过元素的数量,count 为返回元素的最大数量。
类似地,ZREVRANGEBYSCORE
命令可以按照 score 值递减排列。
ZRANK, ZREVRANK
ZRANK key member
返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增 (从小到大) 顺序排列。
排名以 0 为底,score 值最小的成员排名为 0。
使用 ZREVRANK 命令可以获得成员按 score 值递减 (从大到小) 排列的排名。
ZINCRBY
ZINCRBY key increment member
为有序集 key 的成员 member 的 score 值加上增量 increment,increment 可以为负值,可以为整数或者浮点数��
当 key 不存在,或 member 不是 key 的成员时,ZINCRBY
会初始化空集合,或者将成员初始化为 0。
当 key 指向其它类型时,则会返回一个错误。
Redis 应用进阶
事务
127.0.0.1:6379> RPUSH a 1 2 3
QUEUED
127.0.0.1:6379> LRANGE a 0 -1
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 3
2) 1) "1"
2) "2"
3) "3"
Redis 提供了事务机制,支持原子性地执行多条指令。
MULTI
命令进入事务模式,其后的命令进入队列缓存,直到 EXEC
命令执行队列中的命令,或者 DISCARD
命令放弃事务执行。
EXEC
命令会以列表的形式返回事务中所有命令的返回值。
若事务的指令队列中存在语法错误则整个事务都会放弃执行。若队列中某条指令出现了运行时错误(如哈希指令操作了列表),Redis 会继续执行事务中的后续指令。
Redis 保证在事务的原子性,事务执行期间不会有其它客户端的指令插入。
Redis 事务不支持回滚必须由使用者保证一致性。
因为 Redis 是单线程执行的,总是能保证事务的隔离性。Redis 事务不提供额外的持久化机制,持久性由持久化配置决定。
WATCH
命令应在事务开始前执行,用于监视某个键的值是否改变。若在执行 WATCH
和EXEC
指令中间,任意一个被监视的键发生改变或被删除那么事务将中止执行,EXEC 命令会返回 nil。
127.0.0.1:6379> WATCH lock
OK
# 若此时其它客户端修改了 lock 的值,那么事务不会开始执行。127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET b 1
QUEUED
127.0.0.1:6379> GET b
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "1"
WATCH
的监视到 EXEC
开始执行事务为止,因此 WATCH
不会阻止在事务中修改被监视的键。
127.0.0.1:6379> WATCH lock
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET lock 1
QUEUED
127.0.0.1:6379> GET lock
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "1"
WATCH
命令主要用于保证事务开始执行时的状态正确,典型的 ” 秒杀 ” 应用中,多个客户端首先使用 WATCH 命令监视锁,随后执行购买事务。
在 WATCH
命令和事务执行之间若有其它客户端成功执行事务,使得锁发生变化则当前客户端无法执行事务,即抢购失败。
示例(伪代码):
> SET remains 100
> SET empty 0
> WATCH empty
# 此时可能已有其它客户端抢先执行事务
> MULTI
> DECR remains
> if (remains == 0): SET empty 1 # 修改锁,阻止其它客户端抢购
# 此处还应有写购买记录和修改余额等操作
> EXEC
UNWATCH
命令用于取消 WATCH
命令对所有 key 的监视。
pipeline
Redis 采用请求 / 响应式协议进行与服务端的交互,通常情况下一次请求只包含一条指令。
pipeline 模式可以一次请求执行多条指令,减少 IO 的开销。
这里给出一个 Python 客户端使用 pipeline 的示例:
>>> connect = redis.Redis(host='127.0.0.1', port=6379)
>>> pipe = connect.pipeline(transaction=False)
>>> pipe.set("x", "1")
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> pipe.set("y", "2")
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> pipe.execute()
[True, True]
pipeline 不是原子性的,执行过程中可能会有来自其他客户端的指令执行。不要使用 pipeline 发送多条 SET/GET 指令代替 MSET/MGET。
pipeline 会占据整个连接,在完成前无法执行其它指令。客户端应配置好连接池防止被 pipeline 阻塞。
发布订阅
Redis 的发布订阅模式允许客户端监听某些频道,发布者在该频道上发布消息后,消息会被推送到订阅了该频道的客户端。
发布订阅模式允许服务端主动通知客户端,无需客户端轮询状态变化,因此 Redis 可以实现消息队列的功能。
首先打开一个客户端订阅 chat 频道:
SUBSCRIBE chat
打开另一个客户端发布一条消息:
127.0.0.1:6379> PUBLISH chat "Hi there"
(integer) 1
PUBLISH 命令的返回值是接收到该消息的订阅者的数量。
订阅了该频道的客户端会受到消息推送:
127.0.0.1:6379> SUBSCRIBE chat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "chat"
3) (integer) 1
1) "message"
2) "chat"
3) "Hi there"
UNSUBSCRIBE 命令用于取消订阅的频道:
UNSUBSCRIBE [channel [channel ...]]
PSUBSCRIBE 和 PUNSUBSCRIBE 可以使用模式匹配来订阅和取消订阅频道。
PSUBSCRIBE pattern [pattern ...]
PUNSUBSCRIBE [pattern [pattern ...]]
SCAN
KEYS
命令处理大数据库或者 SMEMBERS
命令处理大集合时可能阻塞数据库数秒之久,这在生产环境下是无法介绍的。
SCAN
和 SSCAN
命令可用分页迭代的方式遍历大数据集,每次迭代仅返回少量数据不会阻塞服务器:
SCAN cursor [MATCH pattern] [COUNT count]
127.0.0.1:6379> SCAN 0
1) "20"
2) 1) "1125677473485562817"
2) "5537448729649573447"
3) "2854796168938416843"
4) "7439346733403784473"
5) "-6333572342266574627"
6) "-9080851294203022766"
7) "1125677473485562817"
8) "820904952218043889"
9) "1125677473485562827"
10) "1125677473485562837"
127.0.0.1:6379> SCAN 20
1) "0"
2) 1) "1125677473485562817"
2) "-1053519331922297522"
3) "7439346733403784473"
4) "-2594669955628668552"
5) "-4053026386633294784"
6) "7439346733403784473"
7) "-1053519331922297522"
8) "2649406091729268560"
9) "7439346733403784473"
10) "1053519331903186673"
SCAN
命令的返回值包含两部分,第一部分为下次迭代的游标,第二部分为本次迭代取得的键。
SCAN cursor MATCH pattern
可以像 KEYS
命令一样使用通配符筛选需要迭代的键。SCAN cursor COUNT count
可以设置每次迭代返回键的数量。
使用 0 作为游标表示开始一次新的迭代,当 SCAN
命令返回的游标为 0 时表示本次迭代已经结束。
SCAN
命令保证在整个迭代期间一直存在于数据库中的键一定会被返回。如果一个元素是在迭代过程中被添加到数据集的,又或者是在迭代过程中从数据集中被删除的,那么这个元素可能会被返回,也可能不会,这是未定义的。
SCAN
命令可能会将一个键返回多次,由应用程序处理重复的元素。
Redis 中提供了几个类似的命令用于遍历大集合:
SSCAN
: 遍历集合(set)HSCAN
: 遍历哈希表(hash)ZSCAN
: 遍历有序集合(zset), 包括元素成员和元素分值
127.0.0.1:6379> zadd z 1 a 2 b 3 c
(integer) 0
127.0.0.1:6379> zscan z 0
1) "0"
2) 1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "3"
HyperLogLog
一个集合中不重复元素的个数称为集合的基数,如集合 {a, b, c} 的基数为 3。
HyperLogLog 是一种估计大集合基数的算法,Redis 封装了该算法:
PFADD
命令将元素添加到 HyperLogLog 中:
PFADD key element [element ...]
PFCOUNT
命令返回基数估计值,当给定了多个 key 时则返回它们基数之和(不是并集的基数):
PFCOUNT key [key ...]
PFMERGE
命令将多个 HyperLogLog 合并,destKey 的基数即为 sourceKey 并集的基数:
PFMERGE destkey sourcekey [sourcekey ...]