SpringBootはredisでrabbitMQにべき乗等性を作り、重複消費を防止する
2357 ワード
皆さん、こんにちは.今日はredisでMQの重複消費を防ぐ方法を共有します.MQを使うと、2つの大きな困惑があります.
1つは、メッセージが失われないことを確保すること(メッセージが高可用性)2、メッセージの重複消費を防止することである.
メッセージが失われないように、MQのcallbackを使用して、メッセージが正常に送信されたかどうか、スイッチとキューに送信されたかどうかを確認できます.しかし、メッセージの重複消費については、ネット上で多くの資料を調べたところ、大体次の2つの点が分かった.1つは、データベースのプライマリ・キー(insertの場合、プライマリ・キーは重複できない)2つ、redisのset操作(set同じkeyは直接上書きする)
以上の2点は確かにメッセージの重複消費を解決することができますが、消費者が挿入した操作だけに適用されます.私の消費者には他の人を呼び出すインターフェースがあり、他の人のインターフェースには挿入があります(私が伝えたデータは彼のメインキーではありませんので、上の第1点は明らかに使えません).上の第1点を使うと私の側のデータは重複しませんが、相手のインターフェースのデータは大量に重複します.そしてredisのsetNTメソッドを思いついた.**setNT:**指定したキーが存在しない場合、キーに指定した値を設定します.設定に成功し、1を返します.設定に失敗し、0を返します.SpringbootのredisTemplateで返されるのはtrueとfalse、すなわち成功true、失敗falseであり、実際にはメッセージのmessageIdをkeyとしてredisに格納し、メッセージが消費されるか否かを判断することができる.すると次のようなコードがあります.
IDが存在する場合はfasleを返し、存在しない場合はそのIDをkeyとしてredisに格納し、trueを返す.これでrabbitMQの重複消費の問題を完璧に解決しました
setNT設定keyはキャッシュ時間がない、すなわち永遠に期限切れであるため、業務実行後にリソース の占有を避けるために期限切れ時間を設定する. MQが設定した手動ACKモードの場合、エラーまたはTTLが古い場合、keyをデッドメッセージキューで削除する必要がある.
1つは、メッセージが失われないことを確保すること(メッセージが高可用性)2、メッセージの重複消費を防止することである.
メッセージが失われないように、MQのcallbackを使用して、メッセージが正常に送信されたかどうか、スイッチとキューに送信されたかどうかを確認できます.しかし、メッセージの重複消費については、ネット上で多くの資料を調べたところ、大体次の2つの点が分かった.1つは、データベースのプライマリ・キー(insertの場合、プライマリ・キーは重複できない)2つ、redisのset操作(set同じkeyは直接上書きする)
以上の2点は確かにメッセージの重複消費を解決することができますが、消費者が挿入した操作だけに適用されます.私の消費者には他の人を呼び出すインターフェースがあり、他の人のインターフェースには挿入があります(私が伝えたデータは彼のメインキーではありませんので、上の第1点は明らかに使えません).上の第1点を使うと私の側のデータは重複しませんが、相手のインターフェースのデータは大量に重複します.そしてredisのsetNTメソッドを思いついた.**setNT:**指定したキーが存在しない場合、キーに指定した値を設定します.設定に成功し、1を返します.設定に失敗し、0を返します.SpringbootのredisTemplateで返されるのはtrueとfalse、すなわち成功true、失敗falseであり、実際にはメッセージのmessageIdをkeyとしてredisに格納し、メッセージが消費されるか否かを判断することができる.すると次のようなコードがあります.
return (boolean)redisTemplate.execute((RedisCallback) action->{
return action.setNX(messageID.getBytes(),messageID.getBytes());
});
IDが存在する場合はfasleを返し、存在しない場合はそのIDをkeyとしてredisに格納し、trueを返す.これでrabbitMQの重複消費の問題を完璧に解決しました