实战:如何防止mq消费方消息重复消费
如果因为网络延迟等原因,mq无法及时接收到消费方的应答,导致mq重试。(计算机网络)。在重试过程中造成重复消费的问题解决思路:
1)如果消费方是做数据库操作,那么可以把消息的id,在重试的情况下,会触发主键冲突,从而避免数据出现脏数据。(也可以先用消息id或其他唯一标识去查找表是否存在数据,存在,不插入;不存在,插入)
2)如果消费方不是做数据库操作,可以借助第三方应用,如redis,来记录消费记录。每次消息被消费完成的时候,把当前消息的id作为key存入redis,每次消费前,先去redis查询有没有该消费记录
理论概述
rocketmq是消息中间件,是一种队列,先进先出。
主要实现异步功能生产者使用封装rocketmq的sendMsg发送消息到消息中间件完成了发送消息的过程。
消费者从mq中获取消息,进行消费。生产者和消费者之间是低耦合的,独立的完成自己的任务。
完成了异步和解耦。
WHY?
解决了什么问题
之前如果一个订单服务分别调用支付服务、物流服务、库存服务等等里面的方法,如果说其中一个服务挂了,那么整个业务就无法执行的--------一般非核心业务。
那么mq实现解耦功能,让核心业务和非核心业务解耦,让各个服务解耦。这样即使一些比如物流服务挂了,支付业务还是能正常执行,后面对物流服务做一个补偿机制。
流量削峰,rockmq天生为高并发的秒杀服务的。没有使用mq的普通情况,多少请求就会到A系统,如果秒杀每秒5000次请求过去了,这个时候mysql说我最大只能每秒200请求,多了我受不了,系统接口直接查询慢或者卡住了直到超时。那么所有人都卡在这里,无法选出前200秒秒杀成功的用户。并且太多的请求堆积在A系统,最终可能导致A系统的崩溃。
而mq来了,你生产者可以生产出每秒5000次,5000次消息到mq了,mq本身是高并发请求接受率比较高的系统,可以解决高峰问题,生产者任务完成了,你没有事了。而我消费者一个服务一秒只能最大消费200请求,拉取消息200,先来的先消费,我这一秒只消费200,其他的消息你再等一等,我现在没空。知道所有消息消费完毕。
秒杀请求可以请求过来,但是要先到的200个我让你这一秒秒杀成功,后来的库存还有就可以消费,库存没有就秒杀结束。
保证了A系统的稳定性,“用时间换空间”。
维护性良好生产者业务改动的较少,一般改不同消费者去消费消息。很方便做到一些消息业务删除,增加,修改。
没有使用mq的以前模式,那么改动可能消费者服务改一下,生产者服务改一下,严格意义没有所谓的生产者、消费者一说。
补充:集群:多个服务器服务一个任务
微服务:一个服务对应一个任务,是分布式的一种方式。
rocketmq组成
rocketmq: accessKey: LTAI4FzV************ secretKey: UzhGN************************* nameSrvAddr: localhost:8100;localhost:8100 consumerGroups: - groupId: GID-******** consumers: - topic: TOPIC-***** tag: DING-**** beanName: one**************Listener - groupId: GID-*********** consumers: - topic: TOPIC-***** tag: AD-******* beanName: user*********Listener
Group:分组,对消费者用处较大,比如分为物流组、库存组,每个消费者消费自己所在的组,互不干扰,相对独立进行。
Topic:主题,一类消息的主题或分类,电商可能衣服是个主题、鞋子是主题;也有根据业务服务来定义的,比如报告服务一类主题、采集服务一类主题、品牌服务一类主题。
消费队列:topic可以生成一条消息队列,也可以多条消息队列。
一个queue被一个consumer消费,并且messageQueue1---->consumer1,messageQueue2---->consumer2
提高了消费并发度。
tag:topic基础在还可以在分类,比如topic是手机,tag可以进一步细分苹果手机。
可以让指定消费者只消费苹果手机。
普通消息的发送
同步发送
确保发送成功,一些重要的消息,短信通知,应用消息通知,发送消息后,需要同步响应后再次发送消息。
异步发送
发送数据量大,对响应速度敏感的场景。
发送消息后不用等响应,接着可以发送消息。不会阻塞发送消息线程
单向发送
速度快,对可靠性要求不高
由于在 oneway 方式发送消息时没有请求应答处理,一旦出现消息发送失败,则会因为没有重试而导致数据丢失。
若数据不可丢,建议选用同步或异步发送方式。
普通消息
有集群消费和广播消费两种
集群消费用的多些,保证数据完整性。
全局消息
一个生产者-----》一个消费者
先进先出
部分顺序消息
一个生产者----->多个消费者
每个消费者对应消费不同的QueueX
所以称局部按照先进先出的原则来的。
延时消息
18个等级
message.setDelayTimeLevel(3);
定时
应用在付款关闭倒计时等
还有批量消息、过滤消息等操作。
来一个消费一个
普通消息属性关系
Offset:偏移量