事务中的 BLPOP
BLPOP可以用于流水线(pipeline,发送多个命令并且批量读取回复),特别是当它是流水线里的最后一个命令的时候,这种设定更加有意义。
在一个 [MULTI]/ [EXEC]块里面使用 [BLPOP]没有很大意义,因为它要求整个服务器被阻塞以保证块执行时的原子性,这就阻止了其他客户端执行一个 push 操作。 因此,事务里的 [BLPOP]会在 list 为空的时候返回一个 nil 值,这跟超时(timeout)的时候发生的一样。
如果你喜欢科幻小说,那么想象一下时间是以无限的速度在 MULTI / EXEC 块中流逝……
返回值
多批量回复(multi-bulk-reply): 具体来说:
- 当没有元素的时候会弹出一个 nil 的多批量值,并且 timeout 过期。
- 当有元素弹出时会返回一个双元素的多批量值,其中第一个元素是弹出元素的 key,第二个元素是 value。
例子
redis> DEL list1 list2 (integer) 0 redis> RPUSH list1 a b c (integer) 3 redis> BLPOP list1 list2 0 1) "list1" 2) "a"
可靠的队列
当 [BLPOP]返回一个元素给客户端的时候,它也从 list 中把该元素移除。这意味着该元素就只存在于客户端的上下文中:如果客户端在处理这个返回元素的过程崩溃了,那么这个元素就永远丢失了。
在一些我们希望是更可靠的消息传递系统中的应用上,这可能会导致一些问题。在这种时候,请查看 [BRPOPLPUSH]命令,这是 [BLPOP] 的一个变形,它会在把返回元素传给客户端之前先把该元素加入到一个目标 list 中。
模式:事件提醒
用来阻塞 list 的操作有可能是不同的阻塞原语。 比如在某些应用里,你也许会为了等待新元素进入 Redis Set 而阻塞队列,直到有个新元素加入到 Set 中,这样就可以在不轮询的情况下获得元素。 这就要求要有一个 SPOP 的阻塞版本,而这事实上并不可用。但是我们可以通过阻塞 list 操作轻易完成这个任务。
消费者会做的:
LOOP forever WHILE SPOP(key) returns elements ... process elements ... END BRPOP helper_key END
而在生产者这角度我们可以这样简单地使用:
MULTI SADD key element LPUSH helper_key x EXEC
5 set结构
适用于无序的集合
点赞点踩,抽奖,已读,共同好友
1. sadd key member [member …]
**时间复杂度:**O(N)
添加一个或多个指定的member元素到集合的 key中.指定的一个或者多个元素member 如果已经在集合key中存在则忽略.
如果集合key 不存在,则新建集合key,并添加member元素到集合key中.
##2. scard
**时间复杂度:**O(1)
返回集合存储的key的基数 (集合元素的数量)
如果key不存在,则返回 0
##3. smembers key
**时间复杂度:**O(N)
返回key集合所有的元素.
该命令的作用与使用一个参数的SINTER 命令作用相同.
4. sdiff key [key …]
**时间复杂度:**O(N)
返回一个集合与给定集合的差集的元素
不存在的key认为是空集.
##5. sinner key [key …]
**时间复杂度:**O(N*M)
返回指定所有的集合的成员的交集.
###返回值
array-reply: 结果集成员的列表.
##6. sunion key [key …]
**时间复杂度:**O(N) where N is the total number of elements in all given sets.
返回给定的多个集合的并集中的所有成员.
不存在的key可以认为是空的集合.
###返回值
array-reply:并集的成员列表
##7. srandmember key [count]
**时间复杂度:**Without the count argument O(1), otherwise O(N) where N is the absolute value of the passed count
仅提供key参数,那么随机返回key集合中的一个元素.
Redis 2.6开始, 可以接受 count 参数,如果count是整数且小于元素的个数,返回含有 count 个不同的元素的数组,如果count是个整数且大于集合中元素的个数时,仅返回整个集合的所有元素,当count是负数,则会返回一个包含count的绝对值的个数元素的数组,如果count的绝对值大于元素的个数,则返回的结果集里会出现一个元素出现多次的情况.
仅提供key参数时,该命令作用类似于SPOP命令, 不同的是SPOP命令会将被选择的随机元素从集合中移除, 而SRANDMEMBER仅仅是返回该随记元素,而不做任何操作.
返回值
bulk-string-reply: 不使用count 参数的情况下该命令返回随机的元素,如果key不存在则返回nil.
array-reply: 使用count参数,则返回一个随机的元素数组,如果key不存在则返回一个空的数组.
8. sismember key member
**时间复杂度:**O(1)
返回成员 member 是否是存储的集合 key的成员.
返回值
integer-reply,详细说明
是则返回1
不是或者key不存在,则返回0
##9. srem key member [member …]
**时间复杂度:**O(N)
在key集合中移除指定的元素.
不是key集合中的元素则忽略
如果key集合不存在则被视为一个空的集合,该命令返回0.
如果key的类型不是一个集合,则返回错误.
返回值
integer-reply:从集合中移除元素的个数,不包括不存在的成员
##10. spop key [count]
时间复杂度:O(1)
从键的set值存储中移除并返回count个随机元素
sorted set
1. zadd key [NX|XX] [CH] [INCR] score member [score member …]
将所有指定成员添加到键为key有序集合(sorted set)里
2. zcard key
**时间复杂度:**O(1)
返回key的有序集元素个数
###返回值
integer-reply: key存在的时候,返回有序集的元素个数,否则返回0
3. zscoer key member
**时间复杂度:**O(1)
返回有序集key中,成员member的score值。
如果member元素不是有序集key的成员,或key不存在,返回nil。
返回值
bulk-string-reply: member成员的score值(double型浮点数),以字符串形式表示
4. zcount key min max
**时间复杂度:**O(log(N)) with N being the number of elements in the sorted set.
返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员。
返回值
integer-reply: 指定分数范围的元素个数
5. zrank key member
**时间复杂度:**O(log(N))
返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。排名以0为底,也就是说,score值最小的成员排名为0。
使用ZREVRANK命令可以获得成员按score值递减(从大到小)排列的排名。
返回值
- 如果member是有序集key的成员,返回integer-reply:member的排名。
- 如果member不是有序集key的成员,返回bulk-string-reply:
nil
。
6. zincrby key increment member
**时间复杂度:**O(log(N)) where N is the number of elements in the sorted set.
为有序集key的成员member的score值加上增量increment。如果key中不存在member,就在key中添加一个member,score是increment(就好像它之前的score是0.0)。如果key不存在,就创建一个只含有指定member成员的有序集合。
当key不是有序集类型时,返回一个错误。
score值必须是字符串表示的整数值或双精度浮点数,并且能接受double精度的浮点数。也有可能给一个负数来减少score的值。
返回值
[Bulk string reply](http://www.redis.cn/topics/protocol#Bulk string reply): member成员的新score值,以字符串形式表示
7. zrange key start stop [WITHSCORES]
8. ZREVRANGE
ZREVRANGE key start stop [WITHSCORES]
返回sorted set key中,指定区间内的成员。其中成员的位置按score值递减(从大到小)来排列。具有相同score值的成员按字典序的反序排列。 除了成员按score值递减的次序排列这一点外,[ZREVRANGE]命令的其他方面和[ZRANGE]命令一样。
返回值
例:
redis> ZADD myzset 1 "one" (integer) 1 redis> ZADD myzset 2 "two" (integer) 1 redis> ZADD myzset 3 "three" (integer) 1 redis> ZREVRANGE myzset 0 -1 1) "three" 2) "two" 3) "one" redis> ZREVRANGE myzset 2 3 1) "one" redis> ZREVRANGE myzset -2 -1 1) "two" 2) "one" redis>
monitor
调试命令,返回服务器处理的每一个命令,能帮助了解在数据库上发生了什么操作,可通过redis-cli和telnet命令使用。
Stream
XADD
插入消息,保证有序,可以自动生成全局唯一ID
XREAD
读取消息,可以按ID读取数据
XREADGROUP
按消费组形式读取消息
XPENDING和XACK
- XPENDING命令可以用来查询每个消费组内所有消费者已读取但尚未确认的消息
- XACK命令用于向消息队列确认消息处理已完成
6 Redis 复制
PSYNC
2.8.0 起可用。
从主机启动复制流。
PSYNC 命令由 Redis 从节点调用,用于从主副本启动复制流。
wait
此命令阻塞当前客户端,直到所有以前的写命令都成功的传输和指定的slaves确认。如果超时,指定以毫秒为单位,即使指定的slaves还没有到达,命令任然返回。
命令始终返回之前写命令发送的slaves的数量,无论是在指定slaves的情况还是达到超时。
注意点:
当’WAIT’返回时,所有之前的写命令保证接收由WAIT返回的slaves的数量。
如果命令呗当做事务的一部分发送,该命令不阻塞,而是只尽快返回先前写命令的slaves的数量。
如果timeout是0那意味着永远阻塞。
由于WAIT返回的是在失败和成功的情况下的slaves的数量。客户端应该检查返回的slaves的数量是等于或更大的复制水平。
一致性(Consistency and WAIT)
WAIT 不能保证Redis强一致:尽管同步复制是复制状态机的一个部分,但是还需要其他条件。不过,在sentinel和Redis群集故障转移中,WAIT 能够增强数据的安全性。
如果写操作已经被传送给一个或多个slave节点,当master发生故障我们极大概率(不保证100%)提升一个受到写命令的slave节点为master:不管是Sentinel还是Redis Cluster 都会尝试选slave节点中最优(日志最新)的节点,提升为master。
尽管是选择最优节点,但是仍然会有丢失一个同步写操作可能行。
实现细节
因为引入了部分同步,Redis slave节点在ping主节点时会携带已经处理的复制偏移量。 这被用在多个地方:
- 检测超时的slaves
- 断开连接后的部分复制
- 实现WAIT
- 在WAIT实现的案例中,当客户端执行完一个写命令后,针对每一个复制客户端,Redis会为其记录写命令产生的复制偏移量。当执行命令WAIT时,Redis会检测 slaves节点是否已确认完成该操作或更新的操作。
返回值
integer-reply: 当前连接的写操作会产生日志偏移,该命令会返回已处理至该偏移量的slaves的个数。
例子
> SET foo bar OK > WAIT 1 0 (integer) 1 > WAIT 2 1000 (integer) 1
在例子中,第一次调用WAIT并没有使用超时设置,并且设置写命令传输到一个slave节点,返回成功。第二次使用时,我们设置了超时值并要求写命令传输到两个节点。 因为只有一个slave节点有效,1秒后WAIT解除阻塞并返回1–传输成功的slave节点数。