分布式消息中间件(kafka理论篇)

kafka这几年在分布式领域的用途也是非常火热 , 感觉有超越老牌rabbitMQ的趋势。在大数据的时代,数据对我们也是越来越重要,就拿web系统来说,现在系统都走向了微服务,分布式,随之而来的是大量的日志信息,这些日志信息,收集起来也是一个问题,对于rabbitMQ来说,这些日志信息太多了,全交给它来说,越来太大。于是kafka就成了新的代言者,kafka刚好也有发布订阅等消息中间件特性。

 kafka消息模型如下

图中的broker可能有点瑕疵,在kafka中叫做topic。

一个topic可以理解为一个容器,这种模式中也有发布和订阅模式,即生产者将消息发布到topic中,然后消费者订阅此topic进行消息的消费。

对于任何一个MQ来说吞吐量都是一个特别重要的标准,kafka之所以吞吐量如此高是因为,它发送消息的时候使用的批处理,不是一条一条的发送(rabbitMQ是一条一条发送的),而是一小批,一小批的,发送。它在缓冲一段时间后,一下把缓存的消息都发送,这样和broker的交互就相对的少了,速度自然就快了。

还有一个重要的一点是kafka每次写入的时候都会把消息写入到页缓存中,而页缓存是在内存中分配的,所以速度也是非常的快。

kafka写入的时候是直接在文件使用append的方式,又比随机写磁盘要快。

kafka整体架构

 生产者----------------------------------kafka集群--------------------消费者

                                                 zookeeper集群(kafka集群依赖于zookeeper集群

这就是kafka(集群的时候使用的主从复制模式,主节点负责读写,主节点挂掉了,可以通过内部的isr机制来进行选举,选出新的leader)的整体架构

生产者发送消息到topic中某个partition中,然后消费者订阅topic中的某个partition来实现消费

图中涉及到概念有:

producer: 消息的发送者用来发送消息到topic中的某个分区

Consumer :消息消费者,向kafka broker取消息的客户

Topic :可以理解为一个队列;

 Consumer Group: 消费者组,表示多个消费者组成的集合,一个topic可以有多个消费者组,理论上一个消费者组中的消费者可以共享同一个topic,但是真正消费的时候,同一个消费者组下的消费者不能消费同一分区,因为这样可能会导致offset错乱

Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic;

Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序.

offset:偏移量,存在于partition中,作用是记录kafka的消费位置,kafka不像rabbitMQ,每消费一条消息就删除一条,它是消费之后在偏移量中记录消费的位置,下次消费的时候从上次记录的位置开始算起。

图中的partition和offset都是有序的

,生产的消息被不断追加到Partition log上,其中的每一个消息都被赋予了一个唯一的offset值

分区的原因

(1)方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;

(2)可以提高并发,因为可以以Partition为单位读写了。这样就不会说一个topic中的消息太多,而炸掉

分区原则

(1)指定了patition,则直接使用;

(2)未指定patition但指定key,通过对key的value进行hash出一个patition;

(3)patition和key都未指定,使用轮询选出一个patition。

 副本(Replication)

同一个partition可能会有多个replication(对应 server.properties 配置中的 default.replication.factor=N)。没有replication的情况下,一旦broker 宕机,其上所有 patition 的数据都不可被消费,同时producer也不能再将数据存于其上的patition。引入replication之后,同一个partition可能会有多个replication,而这时需要在这些replication之间选出一个leader,producer和consumer只与这个leader交互,其它replication作为follower从leader 中复制数据。

集群:

在开始kafka集群之前必须先搞一搞zookeeper的集群,zk集群的核心是myid文件(无后缀)

zk集群之后配置下列信息

配置文件在config/server.properties

broker.id=0,

listeners =PLAINTEXT://ip:port

zookeeper.connect=zk1:port,zk2:port,zk3:port

delete.topic.enable 是否允许kafka集群删除t局opic及其数据

log.retention.{hours|minutes|ms} 控制消息数据的留存时间,时,分,秒 ,默认留存时间是7天

log.retention.bytes 设置kafka集群为每个消息日志保存多大的数据,如果数据超过了kafka会启动清理策略

默认值为-1,表示不会根据日志文件的总大小来删除日志

num.network.threads 控制了broker在后台处理请求的线程数,默认是3

num.io.threads 实际处理网络请求的线程数,默认值是8

message.max.bytes  kafkabroker 能接受最大消息大小,默认是997kb,实际中需要修改

其它配置文件只需要改id的值和监听的端口号就可以加入集群了,加入 kafka内部就会在新节点复制信息,这样就达到轻量级的动态扩展.

kafka消息的写入流程

1)producer先从zookeeper的 "/brokers/.../state"节点找到该partition的leader

2)producer将消息发送给该leader

3)leader将消息写入本地log

4)followers从leader pull消息,写入本地log后向leader发送ACK

5)leader收到所有ISR中的replication的ACK后,增加HW(high watermark,最后commit 的offset)并向producer发送ACK

broker 存储消息的方式

1.物理上把topic分成一个或多个partition(对应server.properties中的num.partition=3配置)每个对应的partition物理上对应一个文件夹,(该文件夹存储此分区的所有消息和索引记录文件)

存储策略

这个在上面的配置文件中已经有所说明

在对应的broker中设置这些信息,即可。

zookeeper存储结构

 

注意:producer不在zk中注册,消费者在zk中注册。

1.图中可以看到消费者会将自己的信息在zookeeper中的注册,包括自己所在的消费者组,自己的组id,偏移量(offset)和主题信息(topic).

2.其它信息都是broker依赖于消费者的集群,选举等信息,看下即可

重提消费者组

消费者一般是以consumer group消费者组的方式工作,由一个或者多个消费者组成一个组,共同消费一个topic。每个分区在同一时间只能由group中的一个消费者读取,但是多个group可以同时消费这个partition。

好处在于 消费者可以通过水平扩展的方式同时读取大量的消息。如果一个消费者失败了,那么其他的group成员会自动负载均衡读取之前失败的消费者读取的分区(这一点就比较流弊)

消费方式

consumer采用pull(拉)模式从broker中读取数据。

push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。(rabbitMQ是使用推的方式,因为rabbitMQ中的消息远没有kafka的消息频率那么大(kakfa在大数据方向,应用广泛),并且在rabbit中如果消息太多阻塞了,可以用动态生成多个消费者协助消费来度过阻塞期)

pull模式也是有缺点的,当broker中没有消息的时候,消费者会陷入自己的循环中,白白消耗性能。这个时候就需要对consumer进行阻塞操作。

上图为观察者模型图,其实MQ的底层就是基于观察者机制来实现,如果能看懂jdk的观察者机制,就可以自动MQ的设计理论了

图中的具体主题就可以理解为一个kafka中的topic或者分区。可以理解为一个集合,然后具体的观察者可以理解为消费者原型。

消费者订阅集体的topic后,将此消费者的加入到具体的topic集合中,然后当次topic集合有消息的时候就会将消息发送给集合里面的所有成员,这样就形成了一个简单的发布订阅机制。jdk底层的观察者机制也确实是这么干的,spring底层的监听机制就是以此为思想进行实现的。由此可见设计模式之强大哈哈。

本篇文章写到这吧,后面会在介绍,broker,producer,consumer,设计原理。

 

以及kafka集群调优,监控和管理。

                                                                  -------------------------------本文知识储备来自于蚂蚁课堂,感谢余总的指点。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值