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
代码语言:javascript复制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
代码语言:javascript复制GET key
GET one
返回key所关联的字符串值,若key不存在返回nil, 若key指向其它数据类型则会返回一个错误信息。
MGET
代码语言:javascript复制MGET key [key key ...]
返回所有(一个或多个)给定key的值。若其中有某个key不存在或指向其它类型,那么这个key返回nil。
MSET
代码语言:javascript复制MSET key value [key value ...]
MSET one 1 two 2
同时设置一个或多个key-value对, 如果某个给定key已经存在,那么MSET会用新值覆盖原来的旧值。该命令不会返回错误信息,总是返回OK。
和其它指令一样,该操作是原子性的。
MSETNX
代码语言:javascript复制MSETNX key value [key value ...]
MSET one 1 two 2
同时设置一个或多个key-value对, 如果某个给定key已经存在,那么MSETNX
不会设置任何一个key-value。
该操作是原子性的,要么全部设置要么全不被设置。
TYPE
代码语言:javascript复制TYPE key
返回key指向的类型:
- none: key不存在
- string: 字符串
- list: 列表
- set: 集合
- zset: 有序集
- hash: 哈希表
INCR,DECR
代码语言:javascript复制INCR key
DECR key
INCR命令将key中储存的数字值增1, 若key不存在则先被初始化为0,然后再执行操作。 返回操作后key指向的值。
若值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
类似地有DECR命令,用于将存储的数字减1。
INCRBY,DECRBY
代码语言:javascript复制INCRBY key value
INCRBY count 2
DECRBY count 3
将key所储存的值加上增量value, 返回操作后的值。value可以为0或负值。
若值包含错误的类型,或字符串类型的值不能表示为整数,那么返回一个错误。
类似地有DECRBY用于将存储的数字减去给定值。
INCRBYFLOAT
代码语言:javascript复制INCRBYFLOAT key value
INCRBYFLOAT one 1.23
将key所储存的值加上浮点增量value, 返回操作后的值。value可以为0或负值。
若值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
目前版本的Redis中没有DECRBYFLOAT指令,可以使用加负数进行减运算。
key
本节介绍对key通用的操作。
DEL
代码语言:javascript复制DEL key [key ...]
DEL one two
删除给定的一个或多个key, 不存在的key将会忽略返回被删除的key的数量。
KEYS
代码语言:javascript复制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
代码语言:javascript复制EXISTS key
EXISTS one
检查给定key是否存在, 若存在返回 1,否则返回 0。
RENAME
代码语言:javascript复制RENAME key newkey
RENAME one ONE
将key改名为newkey, 当newkey已经存在时,RENAME命令将覆盖旧值。成功时返回OK,失败时返回一个错误。
当key和newkey相同,或者key不存在时,返回一个错误。
RENAMENX
代码语言:javascript复制RENAMENX key newkey
RENAMENX one ONE
当newkey不存在时, 将key改名为newkey。成功时返回1,若newkey已存在返回0。
EXPIRE
代码语言:javascript复制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
代码语言:javascript复制EXPIREAT key timestamp
EXPIREAT的作用和EXPIRE类似,都用于为key设置生存时间。
不同在于EXPIREAT命令接受的时间参数是UNIX时间戳。
PEXPIREAT和EXPIREAT命令类似,但它的参数是以毫秒为单位的unix时间戳。
TTL
代码语言:javascript复制TTL key
以秒为单位,返回给定 key 的剩余生存时间,当key不存在时,返回-2, 当key存在但没有设置剩余生存时间时,返回-1。
PTTL命令类似于TTL命令,但它以毫秒为单位返回key的剩余生存时间。
PERSIST
代码语言:javascript复制PERSIST key
移除给定key的生存时间设置,使其成为永久的key。
当生存时间移除成功时,返回1。如果key不存在或key没有设置生存时间,返回0。
list
列表(list)是一个线性容器,可以根据下标访问元素。
Redis中list的元素只能是字符串,不支持其它类型。
LPUSH
代码语言:javascript复制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
代码语言:javascript复制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
代码语言:javascript复制LLEN key
返回列表的长度,若key不存在返回0, 若key指向其它类型则返回一个错误。
LRANGE
代码语言:javascript复制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
代码语言:javascript复制LINDEX key index
返回列表key中,下标为index的元素。若index超出范围或者key指向空列表(key不存在)则会返回nil, 若key指向其它类型则返回错误。
下标以0为底,即0表示列表中的第一个元素, 1表示第二个元素。也可以使用负数下标,-1表示最后一个元素, -2表示倒数第二个元素。
LINSERT
代码语言:javascript复制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
代码语言:javascript复制LREM key count value
根据参数count的值,移除列表中与参数value相等的元素,返回被移除元素的数量。
count的值可以是以下几种:
- count > 0: 从表头开始向表尾搜索,移除与value相等的元素,数量为count。
- count < 0: 从表尾开始向表头搜索,移除与value相等的元素,数量为count的绝对值。
- count = 0: 移除表中所有与value相等的值。
LTRIM
代码语言:javascript复制LTRIM key start stop
让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除, start和stop指定区间的规则与LRANGE相同。
若删除成功或key不存在则返回OK,若key指向其它类型则返回错误。
LSET
代码语言:javascript复制LSET key index value
将列表key中下标为index的元素的值设置为value,下标以0为底,可以使用负数下标。
当index参数超出范围,或对一个空列表(key不存在或指向其它类型)进行LSET时,返回一个错误。
LPOP, RPOP
代码语言:javascript复制LPOP key
移除并返回列表key的头元素, key不存在时返回nil。key指向其它类型时返回错误。
类似地有RPOP
命令,移除并返回列表key的尾元素。
set
集合(set)是一种无序容器,不存在重复元素,可以用于判断元素是否存在或者进行交并差运算。
Redis中集合的元素类型只能是字符串,不支持其它类型。
SADD
代码语言:javascript复制SADD key member [member ...]
将一个或多个member元素加入到集合key当中,返回添加到集合中新元素的数量,已经存在于集合的元素将被忽略。
若key不存在先初始化一个空集合然后添加成员,若key指向了非集合类型则会产生错误。
SSCARD
代码语言:javascript复制SSCARD key
返回集合中元素的数量,key不存在时返回0,key指向其它类型时返回一个错误。
SMEMBERS
代码语言:javascript复制SMEMBERS key
返回key指向的集合中的所有成员,若key不存在返回空集,若key指向其它类型则返回一个错误。
SISMEMBER
代码语言:javascript复制SISMEMBER key member
判断member元素是否集合key的成员, 若元素是集合的成员返回1,若元素不是集合的成员或者集合不存在则返回0。
若key指向其它类型则返回一个错误。
SREM
代码语言:javascript复制SREM key member [member ...]
移除集合中的一个或多个元素,不存在的元素会被忽略,返回被成功移除的元素的个数。
若key不存在则作为空集处理,返回0。若key指向其它类型则返回一个错误。
SINTER, SUNION, SDIFF
代码语言:javascript复制SINTER key [key ...]
SUNION key [key ...]
SDIFF key [key ...]
返回给定集合的交集(SINTER),并集(SUNION)和差集(SDIFF),若key不存在则作为空集处理,若key指向其它类型则返回一个错误。
SINTERSTORE, SUNIONSTORE, SDIFFSTORE
代码语言:javascript复制SINTER dest key [key ...]
SUNION dest key [key ...]
SDIFF dest key [key ...]
计算给定集合的交集(SINTERSTORE),并集(SUNIONSTORE)和差集(SDIFFSTORE),并将结果存入dest集合,若dest集合已存在则将其覆盖。
若key不存在则作为空集处理,若key指向其它类型则返回一个错误。
dest可以是某个参与计算的key,dest可以指向其它类型,计算结束后dest中的值会被覆盖。
SPOP
代码语言:javascript复制SPOP key
SPOP
移除并返回集合中的一个随机元素,当key不存在或key是空集时返回nil,若key指向其它类型则返回一个错误。
SRANDMEMBER
代码语言:javascript复制SRANDMEMBER key [count]
若只提供了key参数,那么返回集合中的一个随机元素。
当key不存在或key是空集时返回nil,若key指向其它类型则返回一个错误。
若提供了count参数:
- 若count 为正数,且小于集合基数,那么返回一个包含count个元素的数组,数组中的元素各不相同。
- 若count 大于等于集合中元素数,那么返回整个集合。
- 若count为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为count的绝对值。
hash
哈希表(hash)是key-value结构, key和value的类型为字符串。
HSET
代码语言:javascript复制HSET key field value
将哈希表key中的域field的值设为value。
如果key不存在, 将创建一个新的哈希表并进行HSET
操作。如果域field已经存在于哈希表中,旧值将被覆盖。
若HSET
设置了一个新域则返回1,若覆盖了一个已有的域则返回0。
HSETNX
代码语言:javascript复制HSETNX key field value
将哈希表key中的域field的值设为value。
如果key不存在, 将创建一个新的哈希表并进行HSET操作。如果域field已经存在于哈希表中,则不进行任何操作。
若HSETNX
设置了一个新域则返回1,若域已经存在则返回0。
HGET
代码语言:javascript复制HGET key field
返回哈希表key中指定域field的值,若哈希表key不存在或其域field不存在则返回nil。
HMSET
代码语言:javascript复制HMSET key field value [field value ...]
同时将多个field-value(域-值)对设置到哈希表key中。若field已存在则会被覆盖。
若key不存在,则创建一个空哈希表并执行HMSET操作
HMGET
代码语言:javascript复制HMGET key field [field ...]
返回哈希表key中一个或多个给定域的值,若field不存在则返回nil。
若key不存在则作为空哈希表处理,每个field都会返回一个nil值。
HDEL
代码语言:javascript复制HDEL key field [field ...]
删除哈希表key中一个或多个指定域,不存在的域将被忽略,返回实际被删除域的数目。
HLEN
代码语言:javascript复制HLEN key
返回哈希表key中域的数量,若key不存在则返回0。
HEXISTS
代码语言:javascript复制HEXISTS key field
判断哈希表key中域field是否存在,若存在返回1。若哈希表key不存在或其中不存在域field则返回0。
HKEYS
代码语言:javascript复制HKEYS key
以列表的形式返回哈希表key中所有域的名称。
HVALS
代码语言:javascript复制HVALS key
返回哈希表key中所有域的值。
HGETALL
代码语言:javascript复制HGETALL key
以列表的形式返回哈希表key中所有的键和值,前一个元素为键其后的元素为它的值。
代码语言:javascript复制> HMSET hash a 1 b 2
OK
> HGETALL hash
1) "a"
2) "1"
3) "b"
4) "2"
HINCRBY, HINCRBYFLOAT
代码语言:javascript复制HINCRBY key field increment
为哈希表key中的域field的值加上增量increment, 增量可以为负数进行减法操作。
若哈希表中不存在域field则现将该域初始化为0,然后进行加法操作。
若哈希表key不存在,则将创建一个空哈希表,然后按上一条规则执行。
若key指向其它类型或域的值不能解释为整数则返回一个错误。
类似地,HINCRBYFLOAT
可以进行浮点数运算。
zset
有序集合(SortedSet, zset)是一种特殊的集合类型,它不允许重复元素,可以根据每个元素的score进行排序。
ZADD
代码语言:javascript复制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
代码语言:javascript复制ZREM key member [member ...]
移除有序集 key 中的一个或多个成员,不存在的成员将被忽略, 返回实际被移除的元素数量。
当 key 存在但不是有序集类型时,返回一个错误。
ZCARD
代码语言:javascript复制ZCARD key
返回有序集key中元素的数目,若key不存在则返回0,若key指向其它类型则返回一个错误。
ZCOUNT
代码语言:javascript复制ZCOUNT key min max
返回有序集key中,score值在min和max之间(包括等于min或max)的元素数量。
ZRANGE, ZREVRANGE
代码语言:javascript复制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。
代码语言:javascript复制> 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
代码语言:javascript复制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
代码语言:javascript复制ZRANK key member
返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。
排名以0为底,score值最小的成员排名为0。
使用 ZREVRANK 命令可以获得成员按 score 值递减(从大到小)排列的排名。
ZINCRBY
代码语言:javascript复制ZINCRBY key increment member
为有序集key的成员member的score值加上增量increment,increment可以为负值,可以为整数或者浮点数��
当key不存在,或 member不是key的成员时,ZINCRBY
会初始化空集合,或者将成员初始化为0。
当key指向其它类型时,则会返回一个错误。
Redis应用进阶
事务
代码语言:javascript复制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
命令和事务执行之间若有其它客户端成功执行事务,使得锁发生变化则当前客户端无法执行事务,即抢购失败。
示例(伪代码):
代码语言:javascript复制> 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的示例:
代码语言:javascript复制>>> 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频道:
代码语言:javascript复制SUBSCRIBE chat
打开另一个客户端发布一条消息:
代码语言:javascript复制127.0.0.1:6379> PUBLISH chat "Hi there"
(integer) 1
PUBLISH命令的返回值是接收到该消息的订阅者的数量。
订阅了该频道的客户端会受到消息推送:
代码语言:javascript复制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命令用于取消订阅的频道:
代码语言:javascript复制UNSUBSCRIBE [channel [channel ...]]
PSUBSCRIBE和PUNSUBSCRIBE可以使用模式匹配来订阅和取消订阅频道。
代码语言:javascript复制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 ...]