MQ使用问题

一、如何保证消息的幂等性?

业务系统在收、发MQ消息时都启用了确认机制,所以返回发送成功的消息至少会被消费一次(at-least-once), 需要消费端业务逻辑满足幂等性。
幂等性是指,同一个消息被消费多次产生的结果与只消费一次的结果是相同的。x为某集合内的任意数, 如果满足f(x)=f(f(x)), 那么我们称f运算为具有幂等性。
举个例子,下面的 Example 类的 close() 方法就是幂等的。

解决办法:

1、mq接收生产者传来的消息:

mq为每一个消息生成全局唯一与业务无关的id,当mq接收到消息时,会先根据该id判断消息是否重复发送,mq再决定是否接收该消息。

2、消费者消费mq中的消息:

也可利用mq的该id来判断,或者可按自己的规则生成一个全局唯一id,每次消费消息时用该id先判断该消息是否已消费过

幂等字段一般由多个字段组合,如请求流水号+用户号+金额+业务类型(视业务情况而定),保证唯一性。


二、如何保障生产者不丢消息?

使用同步发送(confirm)模式, RabbitMQ会回传一个ack消息,没有收到Ack则重发。
异步发送会抢占MQ集群的大部分资源,只允许使用同步发送。
VMS api 默认就是使用同步发送 SendMode sendMode = SendMode.SYNC;

三、如何保障RabbitMQ不丢消息?

生产者在发送MQ消息时,将消息的durable属性值设置为 true, 保证消息持久化。
WMS api 默认使用了 durable = true; 用于消息的持久化。
MessageWrap msg = new MessageWrap(buf);
msg.addRoutingKey(exchangeCommand.getRoutingKey()).durable(true);

四、如何保障消费者不丢消息?
使用手动确认(ACK)方式消费(consume)消息, 避免自动确认在异常情况下丢失消息。
VMS api 默认是手动提交方式(boolean autoCommit = false;),采用默认方式即可。


五、消息发送的大小规定
VMS api 默认允许发送不超过 921600字节大小的消息,规范要求MQ消息最大不要超过4M字节大小。如果最大需要发送4M字节的消息,需要在producer.start();之前,
设定最大消息为4M,如下:
producer.slaOption().setMessageMaxSize(1024 * 1024 * 4);

六、如何避免大量的消息积压?

在业务系统设计阶段,需要对即将接收的消息量的大小有个预估,

对于一些消息量很大的队列,消费端需要有开关控制将消息快速写入磁盘。

比如:当某个队列消息出现大量积压时,可以通过开关将消息先写入本地磁盘,后续再做补偿操作,从日志获取消息进行消费处理。
保证消息能够快速接收,不会因为消费慢而导致出现大量消息堆积在MQ。

七、API接口、MQ、计划任务如何抉择?

MQ如何避免被滥用?

原则:如果能使用API同步处理接口就能够解决问题的,就尽量不使用异步处理方式,MQ等异步处理方式,会增加系统的复杂度,会造成暂时的不一致性,要考虑重发、不一致等诸多问题,整体上是降低开发效率的。

建议MQ主要用于"异步通知"、"应用解耦"和部分情况下的"流量削峰"场景。
1、对于一些定时触发的任务,不要使用MQ消息方式来进行触发。
2、对一些能快速响应且结果不影响主流程的调用,可以直接采用API接口方式调用,不要使用MQ方式进行交互。

你可能感兴趣的:(java,RabbitMq)