按照发送的特点分

1.同步发送

a.同步发送, 线程阻塞, 投递completes阻塞结束
b.如果发哦是哪个失败, 会在默认的超时时间3秒内进行重试, 最多重试2次
c.投递completes不代表投递成功, 要check SendResult来判断是否投递成功
d.SendResult里面有发送状态的枚举, SendResult同步的消息投递有一个返回值
e.retry的实现原理: 只有ack的SendResult=SEND_OK才会通知retry(SendResult=SEND_OK只代表消息成功写入了MQ当中, 并不代表该消息成功被Consumer消费了)

  1. public enum SendStatus {
  2. SEND_OK,
  3. FLUSH_DISK_TIMEOUT,
  4. FLUSH_SLAVE_TIMEOUT,
  5. SLAVE_NOT_AVAIABLE
  6. }

2.异步发送

a.异步调用的话, 当前线程一定要等待异步线程回调结束再关闭producer, 因为是异步的, 不会阻塞, 提前关闭producer会导致未回调链接就断开了
b.异步消息不会retry, 投递失败回调onException()方法, 只有同步消息才会retry
c.异步发送一般用于链路耗时教程, 对RT相应时间较为敏感的业务场景, 例如用户上传视频后通知启动转码服务, 转码完成后通知推送转码结果等

3.单向发送

a.消息不可靠, 性能高, 只负责往服务器发送一条消息, 不会重试也不关心是否发送成功
b.此方式发送消息的过程耗时非常短, 一般在微妙级别
总结

发送方式 发送TPS 发送结果反馈 可靠性
同步发送 不丢失
异步发送 不丢失
单向发送 最快 可能丢失

按照使用功能特点分

1.普通消息

普通消息是我们在业务开发中用到最多的消息类型, 生产者需要关注消息发送成功即可, 消费者消费到消息即可, 不需要保证消息的顺序, 所以消息可以大规模的并发的发送和消费, 吞吐量很高, 适合大部分场景

2.顺序消息

顺序消息分为分区顺序消息和全局顺序消息, 全局顺序消息比较容易理解, 也就是哪条消息先进入, 那条消息就会被先消费, 符合我们的FIFO, 很多时候全局顺序消息的实现代价很大, 所以就出现了分区顺序消息

3.延时消息(可用于订单超时库存归还)

延时的机制是在服务端实现的, 也就是Broker收到了消息, 但是经过一段时间以后才发送, 服务器按照1~N定义了如下级别: “1s 5s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”; 若要发送定时消息, 在应用层初始化Message消息对象之后, 调用Message.serDelayTimeLevel(int level)方法来设置延迟级别, 按照顺序取相应的延迟级别, 例如level=2, 则延迟为5秒
a.发送消息的时候如果消息设置了DelayTimeLevel, 那么该消息会被丢到scheduleMessageService.SCHDULE_TOPIC这个Topic里面
b.根据DeleyTimeLevel选择对应的queue
c.再把真是的topic和queue信息封存起来, set到msg里面
d.然后每个SCHDULE_TOPIC_XXXX的每个DelayTimeLevelQueue, 有定时任务去刷新, 是否有投递的消息
e.每10s定时持久化发送进度

4.事务消息