doc: 阅读Shard Pub/Sub相关文档
This commit is contained in:
@@ -177,6 +177,15 @@
|
||||
- [Debugging Eval scripts](#debugging-eval-scripts)
|
||||
- [Execution under low memory conditions](#execution-under-low-memory-conditions)
|
||||
- [Eval flags](#eval-flags)
|
||||
- [Redis Pub/sub](#redis-pubsub)
|
||||
- [Delivery semantics](#delivery-semantics)
|
||||
- [format of pushed messages](#format-of-pushed-messages)
|
||||
- [Database \& Scoping](#database--scoping)
|
||||
- [Example](#example-3)
|
||||
- [Pattern-matching subscriptions](#pattern-matching-subscriptions)
|
||||
- [Messages matching both a pattern and a channel subscription](#messages-matching-both-a-pattern-and-a-channel-subscription)
|
||||
- [the meaning of the subscription count with pattern matching](#the-meaning-of-the-subscription-count-with-pattern-matching)
|
||||
- [Sharded Pub/Sub](#sharded-pubsub)
|
||||
|
||||
|
||||
# redis
|
||||
@@ -2958,5 +2967,136 @@ return x
|
||||
|
||||
另一个不同的区别是,`scripts without #!`可以运行命令来访问`keys belonging to different cluster hash slots`,但是拥有`#!`的将继承默认的flags,故而其不能对`keys belonging to different cluster hash slots`进行访问。
|
||||
|
||||
### Redis Pub/sub
|
||||
在redis中,`SUBSCRIBE,UNSUBSCRIBE,PUBLISH`实现了`Publish/Subscribe消息范式`,其规范如下:
|
||||
- 消息的发送者并未直接将消息发送给特定的接受者
|
||||
- 消息发送者将消息发送给特定的channel,并不知道消息订阅者的情况,甚至不知道消息是否存在订阅者
|
||||
- 消息的订阅者对一个或者多个channel订阅,并且只会接收订阅的消息
|
||||
- 消息的订阅者并无法感知消息的发布者
|
||||
|
||||
上述规范将消息的发布者和订阅者进行了解耦,增强了拓展性,并且允许更加动态且灵活的网络拓扑。
|
||||
|
||||
例如,如果想要对`channel11`和`ch:00`channel进行订阅,client可以发送`SUBSCRIBE`命令:
|
||||
```redis-cli
|
||||
SUBSCRIBE channel11 ch:00
|
||||
```
|
||||
|
||||
其他clients发送到这些channels的消息将会被redis推送给所有订阅这些channels的消息。消息的订阅者将会按照`消息被推送的顺序`来接收消息。
|
||||
|
||||
如果一个client订阅了一个或多个channels,那么其不应该发送任何commands,但其可以对channel进行`SUBSCRIBE`和`UNSUBSCRIBE`。
|
||||
|
||||
对于`subscription`和`unsubscription`操作的回复`以消息的形式被返回`,client只需要读取连续的消息流即可,消息流中的第一个元素代表消息的类型。
|
||||
|
||||
在一个已经订阅的`RESP2`client的上下文中,允许执行的命令为:
|
||||
- `PING`
|
||||
- `PSUBSCRIBE`
|
||||
- `PUNSUBSCRIBE`
|
||||
- `QUIT`
|
||||
- `RESET`
|
||||
- `SSUBSCRIBE`
|
||||
- `SUBSCRIBE`
|
||||
- `SUNSUBSCRIBE`
|
||||
- `UNSUBSCRIBE`
|
||||
|
||||
但是,在使用RESP3时,client在`subscribed`状态下可以发送任何commands。
|
||||
|
||||
当使用`redis-cli`时,如果处于`subscribed`模式下,那么并无法调用`UNSUBSCRIBE`和`PUNSUBSCRIBE`命令,此时`redis-cli`将无法接收任何命令,并且只能通过`Ctrl + C`来退出。
|
||||
|
||||
#### Delivery semantics
|
||||
Redis的`Pub/Sub`机制表现出了`at-most-once`的消息传递语义,其代表消息最多只会被发送一次。一旦消息被redis server发送,不会再重新发送。并且,如果订阅者无法处理该消息(例如网络故障或处理异常),那么该消息将会被永远丢失。
|
||||
|
||||
如果应用需要更强的消息传递保证,需要使用`Redis Stream`。在stream中的消息将会被持久化,并且支持`at-most-once`和`at-least-once`两种传递语义。
|
||||
|
||||
#### format of pushed messages
|
||||
消息是`array-reply with three elements`,其中第一个元素为消息的种类:
|
||||
- `subscribe`: 代表我们成功订阅了channel,channel的名称在第二个element中给出。第三个元素代表目前订阅的channels数量
|
||||
- `unsubscribe`: 代表我们成功取消了对channel的订阅,channel的名称在第二个元素中给出。第三个元素代表目前订阅的channels数量
|
||||
- 当最后一个元素为0时,代表不再订阅任何channel,此时client可以发送任何类型的redis commands,client不再处于`Pub/Sub`状态
|
||||
- `message`: 代表当前message是被其他client通过`PUBLISH`命令发布的消息。第二个元素为`name of the originating channel`,第三个元素则是实际消息的`payload`
|
||||
|
||||
#### Database & Scoping
|
||||
`Pub/Sub`机制和key space没有关联。`Pub/Sub`机制并不会被任何层面干扰,包括database numbers。
|
||||
|
||||
在db 10中发布的消息,仍然可以被db1上的subscriber接收。
|
||||
|
||||
如果需要对channel进行作用域限制,可以为channel name前缀环境名称(test, staging, production...)。
|
||||
|
||||
#### Example
|
||||
对channel进行监听可以使用`SUBSCRIBE`命令
|
||||
```redis-cli
|
||||
127.0.0.1:6379> subscribe first second
|
||||
1) "subscribe"
|
||||
2) "first"
|
||||
3) (integer) 1
|
||||
1) "subscribe"
|
||||
2) "second"
|
||||
3) (integer) 2
|
||||
1) "message"
|
||||
2) "first"
|
||||
3) "fuckyou"
|
||||
1) "message"
|
||||
2) "second"
|
||||
3) "shit"
|
||||
```
|
||||
向channel发送消息可以使用`PUBLISH`命令
|
||||
```redis-cli
|
||||
127.0.0.1:6379> publish first fuckyou
|
||||
(integer) 1
|
||||
127.0.0.1:6379> publish second shit
|
||||
(integer) 1
|
||||
```
|
||||
#### Pattern-matching subscriptions
|
||||
redis pub/sub实现支持pattern matching。clients支持对`glob-style` pattern进行订阅,并接收所有发送到匹配channel的消息。
|
||||
|
||||
例如
|
||||
```redis-cli
|
||||
PSUBSCRIBE news.*
|
||||
```
|
||||
上述指令会订阅所有发送到`news.art.figurative`, `news.music.jazz`等channel的消息。所有`global-style patterns`都有效,也支持多个wildcards。
|
||||
|
||||
```redis-cli
|
||||
PUNSUBSCRIBE news.*
|
||||
```
|
||||
上述命令将会根据pattern对channels进行取消订阅。
|
||||
|
||||
`Messages received as a result of pattern matching`其发送格式将会有所不同,其将包含4个elements:
|
||||
- 消息的type将会是`pmessage`: 这代表该消息通过pattern-matching subscription匹配到的
|
||||
- 第二个元素为original pattern matched
|
||||
- 第三个元素为name of the originating channel
|
||||
- 第四个元素为message payload
|
||||
|
||||
通过`psubscribe`接收到的消息结构如下:
|
||||
```redis-cli
|
||||
127.0.0.1:6379> psubscribe f*
|
||||
1) "psubscribe"
|
||||
2) "f*"
|
||||
3) (integer) 1
|
||||
1) "pmessage"
|
||||
2) "f*"
|
||||
3) "first"
|
||||
4) "suki"
|
||||
```
|
||||
|
||||
#### Messages matching both a pattern and a channel subscription
|
||||
如果client订阅了多个patterns,那么可能多次接收到相同的消息,示例如下所示:
|
||||
```redis-cli
|
||||
SUBSCRIBE foo
|
||||
PSUBSCRIBE f*
|
||||
```
|
||||
|
||||
在上述示例中,如果消息被发送到`foo` channel,那么client将会接收到两条消息:type为`message`的消息和type为`pmessage`的消息。
|
||||
|
||||
#### the meaning of the subscription count with pattern matching
|
||||
在`subscribe, unsubscribe, psubscribe, punsubscribe`消息类型中,消息中最后的元素代表仍然处于活跃状态的订阅数量。该数量代表`total number of channels and patterns the client is still subscribed to`。故而,如果该数量变为0,代表client会退出`Pub/Sub`状态,client取消了对所有channels和patterns的订阅。
|
||||
|
||||
#### Sharded Pub/Sub
|
||||
从reids 7开始,引入了shard channels,其将被分配给slots,且分配的算法和`assign keys to slots`的算法相同。并且,`a shard message must be sent to a node that owns the slot the shard channel is hashed to`。集群将会确保published shard messages将会被转发给shard中所有的节点,故而client在订阅shard channel时,可以连接shard中的任意一个节点,不管是`master responseible for the slot`还是`any of master's replicas`。
|
||||
|
||||
Sharded Pub/Sub能够帮助`Pub/Sub`在集群模式下的拓展。其将消息的传播范围限制在`shard of a cluster`之内。故而,相比于`global Pub/Sub`模式下`每个消息都会被传播到cluster中的所有节点`,`Sharded Pub/Sub`能够减少cluster bus传播的数据量。
|
||||
|
||||
`SSUBSCRIBE, SUNSUBSCRIBE, SPUBLISH`命令能够用于`sharded pub/sub`场景。
|
||||
|
||||
> 在redis的定义中,`a shard is defined as a collection of nodes that serve the same set of slots and that replicate from each other`。
|
||||
|
||||
> 在未引入`Shard Pub/Sub`机制之前,`Pub/Sub`的channel在集群中并不会被hash到slot。此时,`cluster中的每个node独立的维护订阅关系,不同节点之间的订阅并不共享`。并且,发送给某一节点的消息将会广播到整个cluster中所有的nodes。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user