美文网首页
为什么说使用MQ会更优雅?

为什么说使用MQ会更优雅?

作者: zjp999988 | 来源:发表于2020-04-14 23:52 被阅读0次

    我们来讨论MQ,首先我们需要问下自己我们为什么要使用MQ?MQ为我们解决了哪些问题?
    日常应用解决的是我们系统耦合的问题,如下举出外面场景 订单和派送系统

    image.png

    使用RPC 也会存在一些耦合一方系统修改或者调整,另一方也要跟着调整;

    image.png

    通过队列传递消息,双方都是可以做到异步处理,且无耦合

    加入公司决定自研MQ,那么如果你是架构设计组成员的话,你会从哪些方面考虑去设计一款高性能高可用的MQ呢?

    1.首先是协议
    因为任何通过网络收发数据,肯定是要协议的指定;
    比如说浏览器的http协议,只不过http协议有点重量级了,消息头以及消息体字节数较大
    不适用与轻量级的MQ消息传递;且http是短连接,不适合业务量较大的mq场景,此时频繁建立链接也是比较耗时的;
    因此需要知道何时的协议,市面上的协议比如MQTT amqp,OpenWire...

    2.消息的存取和持久化(刷盘规则)

    我们分析一下消息存储时机,以及存储的规则
    1.可以这样优化 消息总是先在内存-->缓存到指定大小再写到磁盘文件
    2.如果保证消息正常写入,使用确认重试机制,如果生产者发送消息,mq没有收到消息会重试;
    3.如何保证写入与读取的高效(不使用jvm内存,直接使用os的内存)


    image.png

    如图如果我们会多出2次拷贝,既浪费性能又浪费空间;

    3.消息的分发策略
    1.消息发送到哪个mq,消费者是主动pull还是mq push
    2.消息收发确认机制(保证mq收到消息,消费者正确收到消息)

    4.mq的高可用
    我们的mq server如何高可用
    从以下几个角度
    1.能不能有备份
    1.1可以一主多从,同步模式可以有异步或者同步 类似于db的数据冗余备份


    image.png

    1.2 多主多从的集群模式

    image.png

    2 分片和副本

    image.png

    原本一份数据现在分成3分,分布在不同server示例上,每个分片也有自己的副本,及时当前分片主节点挂了,也会选出在其他节点的salve1节点作为新的节点保证了高可用;slave和master保持异步或者同步数据;

    这样的设计比如ES或者Mongo都会有看到;

    4.如何做到支持高并发
    1.首先网络通讯使用Nio的异步通讯,支持海量数据处理(很多中间件也是使用前面文章的netty作为高性能的通信框架);
    2.合适的数据刷盘机制,使用合适的索引机制,类似于mysql索引;
    3.读写的零拷贝,不使用jvm内存
    4.动态方便的扩容

    至此以上是总结的mq的一些通用设计点;下面我们来看下具体的MQ的设计架构,我们会拿Rabbitmq和Kafka作为对比,并总结一下MQ设计的一些共通的设计要点;

    kafka架构


    image.png

    架构图中涉及到涉及概念
    broker : server实例,多个实例组成集群
    topic: 类似于传统mq的队列
    partion: 分区相当于将topic的一整份大数据分成多个分区存储在多个实例上;
    replica: pation数据的冗余副本,分布在其他节点实例;
    consumer:消息发送者采用pull推送
    consumer group:消费分组 一个partion只能被consumer group的一个消费者消费;
    producer:采用push推送到broker上

    kafka消息的分发策略:

    具体发送哪个topic和partion的,由生产者决定;
    具体的消息格式类似于key _value格式
    轮询:
    如果key为null,会采用轮休的策略发送到对应partion;
    hash:
    如果key不为null,采用hash策略;
    所以在一个partition内要保证消息的有序性,需要设置指定的key;

    kafka消息的持久化策略:

    普遍任务写文件比内存慢很多;但如果采用顺序读写,可以达到
    百兆/s,甚至比内存还快,但如果是随机读写的话只能达到100kb/s;
    所以kafka采用顺序读写的文件流;
    1.kafka数据存储从os 内存->磁盘,没有采用jvm内存中转,
    1.原因是先写到jvm在写到os内存,会多一次拷贝,且内存空间会多一倍以上
    2.jvm gc机制,很难保证消息正确写出;

    我们看下具体消息格式


    image.png

    我们看到一个partition消息文件分为log和index文件;都是以offerset(每条消息都会分片对应的消息id)
    所以我们只要根据index就可以以最快的速度查询到消息文件

    消息格式如下
    消息长度: 4 bytes (value: 1 + 4 + n)
    版本号: 1 byte
    CRC校验码: 4 bytes
    具体的消息: n bytes

    image.png

    总结以上:
    kafka高效的原因
    1.协议:简易的消息格式类似于mqtt和amqp;没有复杂的消息传输格式;
    网络基于netty消息传递,使用零拷贝机制,实现消息的高效传输;
    2.分发策略
    采用发布确认机制(ack机制);保证消息可靠收发;
    3.消息持久化
    基于顺序存储的文件日志储存,不使用jvm内存的零拷贝机制,
    文件写入采用顺序追加机制,高效的实现文件写入和读取;
    4.高可用设计
    采用分区(可以水平扩展)同时提高partition读写能力;
    使用replica同步机制,当节点故障,利用zk的临时节点机制,选出新的主节点;

    使用kafka可以从以上几点优化配置;

    相关文章

      网友评论

          本文标题:为什么说使用MQ会更优雅?

          本文链接:https://www.haomeiwen.com/subject/gulfvhtx.html