常识
- 一个消息队列可以被多个消费者组订阅,一条消息只有被所有订阅它的消费者组消费了,才算被消费成功。 验证
package main
import (
"context"
"fmt"
"github.com/apache/rocketmq-client-go/v2"
"github.com/apache/rocketmq-client-go/v2/consumer"
"github.com/apache/rocketmq-client-go/v2/primitive"
"os"
"rocketMQ_demo/common"
"time"
)
func main() {
c := make(chan struct{})
go startC1(c)
go startC2(c)
<-c
<-c
}
func startC1(ch chan struct{}) {
c, _ := rocketmq.NewPushConsumer(
consumer.WithGroupName("consumer_group_01"),
consumer.WithNameServer(primitive.NamesrvAddr{common.NameServerAddress}),
consumer.WithConsumerModel(consumer.Clustering),
consumer.WithConsumeFromWhere(consumer.ConsumeFromLastOffset),
)
//订阅topic为test的消息
err := c.Subscribe("test", consumer.MessageSelector{},
func(ctx context.Context,
msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
for _, msg := range msgs {
fmt.Printf("c1 subscribe callback: %v \n", msg)
}
return consumer.ConsumeSuccess, nil
})
if err != nil {
fmt.Println(err.Error())
}
// Note: start after subscribe
err = c.Start()
if err != nil {
fmt.Println(err.Error())
os.Exit(-1)
}
time.Sleep(time.Minute)
err = c.Shutdown()
if err != nil {
fmt.Printf("shundown Consumer c1 error: %s", err.Error())
}
ch <- struct{}{}
}
func startC2(ch chan struct{}) {
c, _ := rocketmq.NewPushConsumer(
consumer.WithGroupName("consumer_group_02"),
consumer.WithNameServer(primitive.NamesrvAddr{common.NameServerAddress}),
consumer.WithConsumerModel(consumer.Clustering),
consumer.WithConsumeFromWhere(consumer.ConsumeFromLastOffset),
)
//订阅topic为test的消息
err := c.Subscribe("test", consumer.MessageSelector{},
func(ctx context.Context,
msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
for _, msg := range msgs {
fmt.Printf("c2 subscribe callback: %v \n", msg)
}
return consumer.ConsumeSuccess, nil
})
if err != nil {
fmt.Println(err.Error())
}
// Note: start after subscribe
err = c.Start()
if err != nil {
fmt.Println(err.Error())
os.Exit(-1)
}
time.Sleep(time.Minute)
err = c.Shutdown()
if err != nil {
fmt.Printf("shundown Consumer c2 error: %s", err.Error())
}
ch <- struct{}{}
}
- 订阅关系的一致性指的是,同一个消费者组(Group ID相同)下所有Consumer实例所订阅的Topic与 Tag及对消息的处理逻辑必须完全一致。否则,消息消费的逻辑就会混乱,甚至导致消息丢失。
- 顺序消息的实现是让producer在发送消息时选择特定的queue来实现的。
example:订单的消息,订单的状态有: 待付款 -> 已支付 -> 已发货 -> 已签收 -> ...,对于同一订单,系统在逻辑上要按合理的状态去处理,所以producer只要把orderID相同的order都发到特定的queue,这样就可以保证consumer在同一个queue拉取到的message的order的状态顺序肯定是合理的。
- 一级分类:topic; 二级分类:tag。 最小粒度:用户属性,producer发送message时为message添加自定义的用户属性,consumer订阅时可用sql去筛选(筛选用户属性)符合要求的message。