訂閱一致性的可能情況以及處理方案
訂閱關係一致指的是同一個消費者 Group ID 下所有 Consumer 實例的處理邏輯必須完全一致。一旦訂閱關係不一致,消息消費的邏輯就會混亂,甚至導致消息丟失
保持訂閱關係一致意味着同一個消費者 Group ID 下所有的實例需在以下兩方面均保持一致
訂閱的 Topic 必須一致
訂閱的 Topic 中的 Tag 必須一致
錯誤情況:
- 同一個 Group ID 下的兩個實例訂閱的 Topic 不一致
- 同一個 Group ID 下訂閱 Topic 的 Tag 不一致。Consumer 實例 1 訂閱了 TagA,而 Consumer 實例 2 未指定 Tag
- 同一個 Group ID 下訂閱 Topic 個數不一致/同一個 Group ID 下訂閱 Topic 的 Tag 不一致
我的錯誤:同一個Group和同一個Topic, 由於tag不同。 所以採取了兩個消費者實例去分別消費消息,然後控制檯會出現
/**
* 錯誤處理方式
*/
/**
* tag消息訂閱
* @param merchantPersonalService
* @return
*/
@Bean(initMethod = "start",destroyMethod = "shutdown")
public ConsumerBean getMerchantBindingBankCardConsumer(MerchantPersonalService merchantPersonalService){
ConsumerBean consumerBean = new ConsumerBean();
Properties properties = new Properties();
properties.put(PropertyKeyConst.GROUP_ID, merchantBankCardGroupId);
// AccessKey 阿里雲身份驗證,在阿里雲服務器管理控制檯創建
properties.put(PropertyKeyConst.AccessKey, accessKey);
// SecretKey 阿里雲身份驗證,在阿里雲服務器管理控制檯創建
properties.put(PropertyKeyConst.SecretKey, secretKey);
// 設置 TCP 接入域名,進入控制檯的實例管理頁面的“獲取接入點信息”區域查看
properties.put(PropertyKeyConst.NAMESRV_ADDR, namesrvAddr);
consumerBean.setProperties(properties);
//組裝訂閱者消息
Map<Subscription, MessageListener> map = new HashMap<Subscription, MessageListener>();
Subscription subscription = new Subscription();
//綁定商戶銀行卡信息mq的topic和tag
subscription.setTopic(merchantBankCardTopic);
subscription.setExpression(merchantBankCardBindTag);
map.put(subscription, new AddBindingBankCardConsumerListener());
consumerBean.setSubscriptionTable(map);
return consumerBean;
}
/**
* tag2消息訂閱
* @param merchantPersonalService
* @return
*/
@Bean(initMethod = "start",destroyMethod = "shutdown")
public ConsumerBean getMerchantBankUntyingConsumer(MerchantPersonalService merchantPersonalService){
ConsumerBean consumerBean = new ConsumerBean();
Properties properties = new Properties();
properties.put(PropertyKeyConst.GROUP_ID, merchantBankCardGroupId);
// AccessKey 阿里雲身份驗證,在阿里雲服務器管理控制檯創建
properties.put(PropertyKeyConst.AccessKey, accessKey);
// SecretKey 阿里雲身份驗證,在阿里雲服務器管理控制檯創建
properties.put(PropertyKeyConst.SecretKey, secretKey);
// 設置 TCP 接入域名,進入控制檯的實例管理頁面的“獲取接入點信息”區域查看
properties.put(PropertyKeyConst.NAMESRV_ADDR, namesrvAddr);
consumerBean.setProperties(properties);
//組裝訂閱者消息
Map<Subscription, MessageListener> map = new HashMap<Subscription, MessageListener>();
Subscription subscription = new Subscription();
//解綁商戶銀行卡信息mq的topic和tag
subscription.setTopic(merchantBankCardTopic);
subscription.setExpression(merchantBankCardUntyingTag);
map.put(subscription, new UntyingBankCardConsumerListener());
consumerBean.setSubscriptionTable(map);
return consumerBean;
}
/**
* 正確處理方式
*/
/**
* 同一個Group和同一個Topic, tag不同的消息訂閱()
* @param
* @return
*/
@Bean(initMethod = "start",destroyMethod = "shutdown")
public ConsumerBean getMerchantBindingBankCardConsumer(){
ConsumerBean consumerBean = new ConsumerBean();
Properties properties = new Properties();
properties.put(PropertyKeyConst.GROUP_ID, merchantBankCardGroupId);
// AccessKey 阿里雲身份驗證,在阿里雲服務器管理控制檯創建
properties.put(PropertyKeyConst.AccessKey, accessKey);
// SecretKey 阿里雲身份驗證,在阿里雲服務器管理控制檯創建
properties.put(PropertyKeyConst.SecretKey, secretKey);
// 設置 TCP 接入域名,進入控制檯的實例管理頁面的“獲取接入點信息”區域查看
properties.put(PropertyKeyConst.NAMESRV_ADDR, namesrvAddr);
consumerBean.setProperties(properties);
//組裝訂閱者消息
Map<Subscription, MessageListener> map = new HashMap<>();
Subscription subscription = new Subscription();
//綁定商戶銀行卡信息mq的topic和tag
subscription.setTopic(merchantBankCardTopic);
subscription.setExpression(merchantBankCardBindTag+ "||" + merchantBankCardUntyingTag);
map.put(subscription, addBindingBankCardConsumerListener);
consumerBean.setSubscriptionTable(map);
return consumerBean;
}