MQ技术点---未完待续

优点:

1:解耦

业务场景:A系统做数据修改,需要通知WEB端服务,APP服务,搜索服务,A系统向MQ中生产一条消息(sub/pub模式),多个系统对当前MQ队列订阅,后期不同系统按照自身业务,从MQ中消费消息,完成自身业务。这样对A系统完成解耦,不需要考虑调用其他多个系统,代码层面会简单很多。

2:异步

好处:异步化可以大幅度提升高延时系统的性能。
业务场景:A系统,因为业务需要,需要同时调用B、C、D三个系统,这样整个接口的调用时间为ABCD4个系统的耗时之和,使用异步化操作,只需要A系统把消息发送到对应系统的MQ队列即可,整个接口的调用时间只是A系统的耗时。

3:削峰填谷

业务场景:不使用MQ,系统访问高峰期,系统处于高并发阶段,系统会被打死。比如中午大量人开始点外卖,但是到了下午,请求又开始回到很低的请求。
使用MQ,大量用户请求100W,系统的处理请求为2000/s请求,远低于用户请求,大量的用户请求写入MQ中,系统从MQ中按照顺序拉取请求,保证系统不会挂掉。

缺点:

  1. 系统可用性降低,多了MQ环节,如果MQ所在机器宕机,A系统就无法发送消息到MQ中,即使BCD系统正常,也无法消费MQ中的消息,系统就不可用,崩溃。

  2. 系统要考虑的问题变多,进而导致系统复杂性变高。

    (1)消息重复消费/幂等性
    	MQ出现消息重复属于正常情况。
    	以kafka为例:
    		由于消费者是定期提交offset,而不是每次提交offset(重点,原因),这就导致消费者机器重启,而此时,消息已经被消费,但是还没来得及提交offset,重启完成,kafka不知道已经消费了,会继续按照之前的offset开始,推送后面的消息给消费者,此时就存在了消息的重复消费。
    	解决方法,防止重复消费,保证幂等性:(必须按照实际业务思考如何保证幂等性)
    		1):musql插入的话,插入之前先查询是否存在,存在则更新,不存在则插入。
    		2):redis的话,直接set即可,redis的set具有天然幂等性。
    		3):复杂一点的业余,则可以基于唯一键约束,每次消费,先根据唯一键查询。
    
    (2)消息丢失
    		rabbitMQ:
    		1)生产者弄丢了消息,比如网络原因
    			解决方案1:rabbitMQ支持消息的事务,消息会同步阻塞,造成MQ吞吐量降			低,影响性能。
    					2:生产者设置channel为confirm模式(常用模式),异步模式, 	 不会阻塞。
    
    		2)消息在MQ中,消息还没有来得及消费,MQ机器宕机,内存中的消息就弄丢了
    			解决方案:
    					消息持久化到磁盘中,即使MQ机器挂掉,重启服务,也可以从磁盘中恢复queue,恢复queue中的数据。
    					还有一点风险会丢失数据,那就是虽然开启了持久化,数据还没来得及持久化到磁盘,MQ所在的机器就挂掉了。
    					两步操作:
    					1)创建queue的时候,设置为持久化
    					2)发送消息的时候,deliveryMode设置为2
    
    		3)消费者消费到了消息,但是还没来得及消费,自己就挂掉了,MQ以为消费者已经消费了。消费者机器重启,MQ会继续提供后面的消息,消费者当时消费的那条消息已经丢失了。
    			这种情况,只存在消费者打开了autoAck模式,消费者接收到消息,就返回给MQ,表示自己已经消费正常,但是此时消费者所在机器宕机了,那消息就丢失了。
    			解决方案:
    					消费者关闭autoAck模式
    
    		kafka:
    		1)消费端弄丢消息
    			消费者自动提交offset,kafka以为已经成功消费了消息,但是此时消费者宕机了,当前消息丢失,重启服务,kafka会从开始发送新的消息给消费者。和rabbitMQ类似
    			解决方案:
    				关闭消费者自动提交offset
    
    		2)kafka自己丢失数据
    			kafka的leader宕机,副本数据还没来得及同步数据到follower,剩下的follower重新选举leader,此时消息已经丢失,新的leader中没有当前消息。
    			解决方案:
    				1)kafka端,设置replication.factor > 1   多副本
    				2)kafka端,min.insync.replicas > 1 至少保证leader和一个follower保持联系
    				3)生产者端,acks=all,保证每条数据都写入成功
    							 retries=MAX,写入失败,无限重试。
    
    		3)kafka的生产者
    			按照上述情况,不存在数量丢失,按照上述配置,kafka全链路都不会数据丢失。					 
    
    (3)消息顺序乱序
    		// TODO
    
    (4)消息积压
    		// TODO
    
  3. 一致性问题:
    正常情况,是系统A向BCD系统,发送请求,BCD系统都会执行成功,结果,BC系统执行正常,D系统执行失败,这种情况,则当前请求就是失败的,如何操作?

MQ的技术选型:
中小型公司,使用rabbitMQ,吞吐量达到万级别,功能完备,开源提供的管理界面完备,社区活跃。
中大型公司,选择rocketMQ,吞吐量达到几十万级别,分布式,扩展方便,社区稳定,支撑大规模的topic数量,阿里出品,有保障。
大数据相关的,不管公司规模,全部使用kafka,用于大数据领域的实时计算,日志采集。


MQ如何保证高可用:
rabbitMQ:
1:单机模式
2:集群模式:
运行原理:MQ所在的queue数据是存放在集群中的某台机器上,其他机器上则存放queue的元数据,用户请求某个queue,访问任意集群中的机器,MQ会查找元数据,找到queue存放的机器,通过内部请求,拿到queue,转发给消费方,进而消费消息。
特点:只是提高了MQ的吞吐量,没有高可用,不是分布式的。
缺点:1)rabbitMQ内部产生大量的数据传输。
2)没有任何高可用而言,如果queue所在的节点宕机,那么当前的这个queue的数据就会丢失了,无法消费。
3:镜像集群模式:
运行原理:queue同步到所有机器上,好处是一台机器宕机,不影响系统使用,缺点是机器性能开销大,同步所有消息,导致网络带宽压力和消耗很重。还有就是没有扩展性可言,新增机器,也会同步所有的消息。针对这个,可以在rabbitMQ的管理界面,新增策略,同步指定数量的节点。

kafka:
	生产者生产的消息,会被存放在kafka中,多台机器中的topic的partition中,并且在其他机器中有replica至少一个副本,类似于solr集群高可用的方案。在这些副本中,会通过选举,选举出一个leader,所有的消息的读写都是通过leader来进行的。此时,即使一台机器宕机,也不影响消息的读写,如果宕机机器正好是leader,则其他副本重新选举,产生一个leader,其他继续为保持副本身份。
	leader写数据时,leader将数据写入本地磁盘,其他follower会主动从leader来pull(拉)数据,follower同步完成数据,会向leader发送ack(回复),leader接受到全部的follower的ack之后,才会向生产者返回写入成功。必须所有的follower同步成功,这个消息才是写入成功,否则无法被消费者读到。
	目前该高可用方案的类似技术:solr,ES,zookeeper
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值