其他分享
首页 > 其他分享> > 面试中的消息队列考点

面试中的消息队列考点

作者:互联网

辛辛苦苦查了大半天资料,总结出来面试没被问,不能白复习,贴上来~

1.什么是消息队列

生产者先将消息投递一个叫做「队列」的容器中,然后再从这个容器中取出消息,最后再转发给消费者,仅此而已。
是一种FIFO的数据结构

2.消息队列的模型

1.初代 ----队列模型
原始的生产者消费者模型, 多生产者,多消费者,通过缓存队列,通知 去取资源

2.进阶 ----发布-订阅模型
将一份消息数据分发给多个消费者,并且每个消费者都要求收到全量的消息

3.消息队列适用场景

通过消息队列就不会原来一个模块,而是拆分成几个模块

通过消息队列,这些不需要返回的(如写入文件),的操作,将对于的数据给了之后,就立即返回响应,实际的操作放到后台去执行,执行完成再通知

如果一次需要5k个请求,则先放入MQ中,每次请求2k, 这样不会直接请求,导致缓存击穿

4.MQ的成熟方案

早起产品,现在基本没人用

开发语言 erlang 导致不好二次开发,但有人维护,追求性能和稳定性,推荐使用

开发语言java, 阿里出品

大数据用的多

5.消息队列的缺点 与解决方案

搭建集群

如以下几种:

1.消息丢失
原因:
可能由服务器宕机

解决:
确认机制,每一步进行一个ACK应答后处理,类似TCP重传处理

2.消息重复
原因:
多服务监听时,可能某个服务未收到,要求重发,导致消息重复

解决:
1>.设置幂等次接口,相同参数传进来,生产唯一标识,返回的一定是相同结果
强校验:
校验唯一标识是否一同返回,返回则有效

弱校验:
校验唯一标识一定时间内是否存在

2>.乐观锁
3>.记录每条被消费的消息状态

3.消息的顺序
原因:
网络波动,传达到各服务的速率不一致

解决:
设置 发送端的 QUEUE

6.消息队列 分布式队列

7.观察者模式

基于发布-订阅观察者模式
1.类图关系
假装有图,懒得画

2.一个简易的观察者模式

#include <iostream>
#include <vector>
#include <string>
using namespace  std;

#include <iostream>

using namespace std;

/**
    抽象基类
*/ 
class base
{
public:
    virtual void update(string message) = 0;
};
/**
    客户端1
*/ 
class  qqUser : public base
{
public:
     void update(string message) {
         cout << "qq -" << message<< endl;
     }
};
/**
    客户端2
*/ 
class weiXinUser : public base
{
public:
    void update(string message) {
        cout << "weixin -" << message << endl;
    }
};

/**
    服务器
*/ 
class interface{
private:
       vector<base*> baseList;
public:
       void add(base* input){
           baseList.push_back(input);
       }
       void del() {
           baseList.pop_back();
       }
       void notify(string message){
            for(auto i : baseList) {
                i->update(message);
            }
       }
};
int main() {
    interface* mInterface = new interface();
    qqUser* mQQUSER = new qqUser();
    weiXinUser* mweiXinUser = new weiXinUser();
    mInterface->add(mQQUSER);
    mInterface->add(mweiXinUser);

    mInterface->notify("recv string");


}

8.基于Rocket MQ的分布式事务

参考博客:
Rocket MQ分布式事务
1.原因:
一个操作是A价钱 B扣钱, 但是A、B 不在同一个数据库,需要引入消息队列

2.流程:
RocketMq消息中间件把消息分为两个阶段:Prepared阶段和确认阶段Prepared阶段(预备阶段)

进程变为:
1、在扣款之前,先发送预备消息
2、发送预备消息成功后,执行本地扣款事务
3、扣款成功后,再发送确认消息
4、消息端(加钱业务)可以看到确认消息,消费此消息,进行加钱

  1. 可能存在异常:
    异常1:如果发送预备消息失败,下面的流程不会走下去;这个是正常的
    异常2:如果发送预备消息成功,但执行本地事务失败;这个也没有问题,因为此预备消息不会被消费端订阅到,消费端不会执行业务。
    异常3:如果发送预备消息成功,执行本地事务成功,但发送确认消息失败;这个就有问题了,因为用户A扣款成功了,但加钱业务没有订阅到确认消息,无法加钱。这里出现了数据不一致。

针对异常3 RocketMq 会进行【状态回查】,也就是RocketMq会定时遍历commitlog中的预备消息。
对于已发送的事务扣款成功,就补发commit,如果没有 成功就执行rollback

标签:队列,预备,void,发送,面试,考点,消息,message
来源: https://blog.csdn.net/Tyrion9/article/details/119464008