阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

KV型内存数据库Redis

182次阅读
没有评论

共计 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
  • 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.0e73e590e-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命令应在事务开始前执行,用于监视某个键的值是否改变。若在执行 WATCHEXEC指令中间,任意一个被监视的键发生改变或被删除那么事务将中止执行,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 命令处理大集合时可能阻塞数据库数秒之久,这在生产环境下是无法介绍的。

SCANSSCAN 命令可用分页迭代的方式遍历大数据集,每次迭代仅返回少量数据不会阻塞服务器:

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 ...]

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计13136字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中