kafka
分布式架构下,上下游两个微服务通信,性能不匹配的话,比如上游的QPS是200,下游QPS只有100,那么此时上游和下游之间以联机接口的方式通信就会把下游给打垮。没有什么是加一层不能解决的!尤其是这种平衡二者速度的问题,如果是写场景就加队列,如果是读场景就加缓存,计算机领域的常规操作啦。
1、高性能:加了消息队列以后,本质上是一个生产者消费者模型,并且属于多生产者多消费者模型,我们知道按照生产者消费者模型的规则,同一时刻最多只能有一个生产者/消费者来访问临界资源,除非临界资源划分了槽位,那就可以把并发粒度控制在每个槽位。首先,按照Topic划分槽位,这样并发粒度就可以是Topic级别,进一步每个topic内部再划分patition,这样并发的粒度又精细化到了patition。
2、高可用:
- 备份:我们直接按照最小的单位patition去说(就像谈论k8s的时候,最常提及的就是最小的单位pod),patition不能只有一份,一定要有副本,patition越来越多肯定不能都部署在同一个服务上,所以就要划分broker,把patition打散分布在不同broker上,并且patition的本体和副本不在同一个broker上,这样防止一个broker崩了patition的本体和副本全崩了。说到这里你应该就发现了,kafka实现高可用不是redis、MySQL那样的主从集群,kafka的备份粒度不是一整台MySQL服务器,而是patition。
- 持久化:再就是要持久化到磁盘,目的后面再来补充//todo
3、消费者组:因为一个topic不止被一个下游服务消费,比如说有个订单的topic,既要被扣减库存的服务消费,又要被增加积分的服务消费,但是二者消费的进度不一样,可能扣减库存的服务已经消费到offset=9的位置了,增加积分的服务比较慢才消费到offset=3的位置。既然大家对于同一个topic的消费速度不一样,就只能划分组。
4、zookeeper:组件太多了,每个组件都有自己的状态,所以需要有一个统一来管理维护的角色——分布式协调服务。
rocketMQ
对于rocketMQ,不需要从0到1去学,聪明的做法是跟kafka对比着去学,主要是两点,在架构上做了减法,在功能上做了加法。
- 在架构上做了减法
- 去掉zookeeper,采用轻量级的nameserver服务。因为zookeeper其实很强大,可以实现名字服务、分布式锁、配置管理等等,但是kafka只用到了名字服务这个功能,属于杀鸡用牛刀,后来kafka的开发者也意识到了这个问题,所以新版的kafka去掉了zookeeper,改用Raft算法。
- 底层存储逻辑变了,提升写入速度。kafka存储patition的时候,给每个patition划分成多个segment,每个segment对应磁盘里的一个文件,每个文件里是顺序写。但是随着patition的增多,这个文件写一下,那个文件写一下,顺序写逐渐“收敛”到了随机写。所以rocketMQ索性维护一个大文件,在这个大文件里顺序写,然后每个patition里维护索引,指向大文件,读的时候读两次,有点“回表”的感觉哈!
- 在功能上做了加法
- 新增了定时消息,比如你12点下单晚上17点的预定外卖,可能16:00的时候rocketMQ才会推给商家服务。
============下面是2023年写的,理解不够===
一、消息队列的流派
- 有broker的MQ
- 重Topic(必须有topic) :kafka
- 轻Topic
- 无broker的MQ
二、kafka基本概念
三、demo——生产者和消费者——单机
官方demo;:Apache Kafka
消费者有两种消费的方式,如下:
就像我们进群一样,有的刚进来以后只能看见进群之后的消息;有的可以看到全部历史群聊。
既然“历史群聊”也可以被看见,那就说明消息不是和socket通信一样发完以后关掉server和client就没有了的,而是被保存了下来。对的,以日志的形式保存在kafka服务器上。具体位置可以自己指定。
有个问题,“历史聊天记录”太多,多达几个T,一个磁盘放不下怎么办?这就引出了Topic分区。
3.1 Topic分区
除了能让磁盘放下之外,分区还有一个好处。之前只放在一个文件的时候,一次只能有一个producer去写这个文件,但是分区以后, 读写可以并行了!
如何指定创建几个分区:把一个topic分成几个区在创建topic的时候用命令参数--partitions 去指定
3.2 单播和多播(其实是一个东西)
单播:对于同一个consumerGroup里订阅了同一个topic的消费者们,只有一个consumer能收到producer发送的消息,而且是最新加入的那个consumer。
PS:consumer1和consumer2在一个组里(运行时指定的,截图的时候可能被挡住了)
多播:不同的consumerGroup组订阅同一个topic,那么每个组里只有一个consumer能收到消息。
四、搭建kafka集群
以3个broker(kafka)节点的集群为例,这里我们用3个端口代表3个节点,就不开3个服务器了
要新建3个server.properties文件
然后启动3个节点
有了集群以后,创建topic的时候可以指定生成副本(也就是备份),一共有3个节点,也就可以有3个备份。
而且kafka会自动指定哪个节点作为leader,leader可以理解为MySQL主从复制的master,以leader节点存储的信息为主,producer也只往leader节点上发消息,不是3个节点都发,同样consumer也只去读leader节点上的消息,其他两个节点去同步/拷贝leader的信息!其他两个节点只是在leader挂了的时候才能用到,这又涉及到了选举的问题,以后再说选举策略!
如上图所示,名为my-replicated-topic的topic有两个分区,partition0和partition1,这两个分区各自都有3个副本,其中partition0的leader是2号节点,partition1的leader是0号节点,示意如下: