《kafka --第一章:基础知识》
Kafka | kafka 是采用Scala 语言开发的多分区,多副本且基于zookeeper 协调的分布式消息系统。 Kafka 是一个高吞吐量、分布式的,发布一订阅消息系统。 Kafka 核心模块使用 Scala 语言开发,支持多语言 (如 Java IC++ rthon Go Erlang Node.js 等)客户端,水平扩展和具有高吞吐量等 特性而被广泛使用 目前越来越多的开源分布式处理系统(如 Flume Apache Storm Spark Flink 等)支持与 Kafka 集成。 |
Kafka 是一款开源的、轻量级的 、分布式、可分区和具有复制备份的 Replicated )、基于 Zoo Keeper 协调管理的分布式流平台的功能强大的消息系统 。与传统的消息系统相比, Kafka 能够很好地处理活跃的流数据,使得数据在各个子系统中高性能、低延迟地不停流转。 |
Kafka 定位就是一个分布式流处理处理平台,必须具备以下 个关键特性。 能够允许发布和订阅流数据。
1. 存储流数据时提供相应的容错机制。 |
2. 当流数据到达时能够被及时处理 |
kafka 的三大特点:
1.消息系统 | kafka具备系统解耦,冗余存储,流量消峰,缓冲,异步通信,扩展性,可恢复性等功能。kafka 还提供消息的顺序性保障和回溯消费的功能。 |
2.存储系统 | kafka 把消息持久化到磁盘【其他的消息是存储到内存】,有效的降低了数据丢失的风险。基于kafka的消息持久化功能和多副本机制,可以作为长期的数据存储系统来使用,但要把对应的数据保留策略设置为永久或启用主题的日志压缩功能。 |
3.流式处理平台 | kakfa 不仅仅为每个流行的流式处理框架提供了可靠的数据来源,还提供了一个完整的流式处理类库,比如窗口,连接,变换,聚合等各类操作。 |
kafka包括若干producer,broker,consumer,以及一个zookeeper集群。
Zookeeper : | 是kafka 用来负责集群元数据的管理,控制器的选举等操作。Kafka 通过zookeeper来实施对元数据信息的管理,包括集群,broker,主题,分区等内容。zookeeper是一个开源的分布式协调服务,分布式应用可以基于zookeeper实现诸如数据发布/订阅,负载均衡,命名服务,分布式协调/通知,集群管理,master 选举,配置维护等功能。 zookeeper中共有3个角色:leader ,follower,observer。 |
producer : | 消息发送者,将消息发送到broker。 |
Broker : | 服务代理节点,将收到的消息存储到磁盘中。 |
consumer: | 消息消费者,负责从broker 订阅并消费消息。 |
topic: | 主题,Kafka 中的消息以主题为单位进行归类,生产者负责将消息发送到特定的主题,而消息者负责订阅主题并进行消费。 |
Partition : | 主题是一个逻辑上的概念,还可以细分为多个分区,一个分区只属于单个主题,很多时候也会把分区称为主题分区。同一主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志log文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset),offset是消息在分区中的唯一标识,Kafka通过它来保证消息在分区内的顺序性,不过offset 并不跨越分区,也就是说,Kafka保证的是分区的有序而不是主题有序。 |
名称 | 描述 |
提升容灾能力 | 多副本机制:Kafka 为分区引入了多副本机制,通过增加副本数量可以提升容灾能力。同一分区的不同副本中保存的是相同的消息,副本之间是一主多从的关系,其中leader副本负责处理读写请求,follower 副本只负责与leader 副本的消息同步。副本处于不同的broker 中,当leader副本出现故障时,从folloer副本中重新选举新的leader副本对外提供服务。Kafka 通过多副本机制实现了故障的自动转移,当Kafka集群中的某个broker失效时仍然能保证服务可用。 |
保证消息不丢失 | Kafka 消费端也具备一定的容灾能力。consumer 使用pull 拉 模式从服务端拉取消息,并且保存消费的具体位置,当消费者宕机后恢复上线时可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失。 |
AR | 分区中所有副本统称为AR(assigned replicas),所有与leader副本(包括leader副本在内)保持一定程度同步的副本组成ISR(in-sync replicas)。 ISR集合是AR集合中的一个子集。消息会先发送到leader副本,然后follower副本才能从leader副本中拉取消息进行同步,同步期间消息有一定的滞后性。与leader副本同步滞后过多的副本组成ORS(out-of-sync replicas)。 |
选举: | leader副本负责维护和跟踪ISR集合中所有follower副本的滞后状态,当follower副本落后太多或者失效时,leader副本会把它从ISR集合中剔除,如果ORS集合中有follower副本追上了leader副本,那么leader副本会把它从OSR集合转移到ISR。当leader 副本发生故障时,只有在ISR集合中的副本才有资格被选举为新的leader。 |
整个生产者客户端由两个线程协调运行,分别是主线程和sender发送线程。在主线程中由Kafka producer 创建消息,然后通过可能的拦截器,序列化,分区器的作用之后缓存到消息累加器(record accumulator消息收集器)中,sender 线程负责从消息收集器中获取消息并将其发送到Kafka中。
消息收集器 | 消息收集器record accumulator主要作用就是缓存消息,以便sender线程可以批量发送,进而减少网络传输的资源消耗以提升性能。消息收集器缓存的大小可以通过生产者客户端参数buffer.memory 配置,默认值为32MB。如果生产者发送消息的速度超过发送到服务器的速度,则会导致生产者空间不足,这个时候kafkaProducer的send方法要么被阻塞,要么抛出异常。 |
序列化: | 生产者需要用序列化器serializer把对象转换成字节数组才能通过网络发送给kafka,而消费者需要用反序列化器deserializer把从kafka中收到的字节数组转换成相应的对象。 |
主线程发送过来的消息都会被追加到消息收集器的某个双端队列(deque)中,在消息收集器record accumulator 的内部为每个分区都维护了一个双端队列,队列的内容就是producerBatch。即Deque<ProducerBatch>。消息写入缓存时,追加到双端队列的尾部;发送线程sender读取消息时,从双端队列的头部读取。【一个消息队列producer batch可以包含多个消息记录】 注意: ProducerBatch 不是 ProducerRecord, ProducerBatch 中可以包含一至多个 ProducerRecord。。如果生产者客户端需要向很多分区发送消息, 则可以将buffer memory 参数适当调大以增加整体的吞吐量。 消息在网络上都是以字节byte 的形式传输的,在发送之前需要创建一块内存区域来保存对应的消息。在Kafka生产者客户端中,通过java.io.bytebuffer 实现消息内存的创建和释放。不过频繁的创建和释放是比较耗费资源的。所以消息累加器的内部还有一个bufferPool,它主要用来实现byteBuffer的复用,以实现缓存的高效利用。不过bufferPool只针对特定大小的byteBuffer进行管理,而其他大小的byteBuffer不会缓存到bufferPool中,这个特定大小由batch.size 参数指定,默认值16KB。 |
ProducerBatch的大小和batch.size参数有着密切的关系。当一条消息(ProducerRecord)流入消息累加器RecordAccumulator时,会先寻找与消息分区所对应的双端队列(如果没有则新建),再从这个双端队列的尾部获取一个ProducerBatch(如果没有则新建),查看ProducerBatch中是否还可以写入这个ProducerRecord,如果可以则写入,如果不可以则需要创建一个新的 ProducerBatch。在新建ProducerBatch时评估这条消息的大小是否超过batchsize参数的大小,如果不超过,那么就以batchsize参数的大小来创建ProducerBatch,这样在使用完这段内存区域之后,可以通过BufferPool的管理来进行复用;如果超过,那么就以评估的大小来创建producerBatch ,这段内存区域不会被复用。 |
acks: acks: 这个参数用来指定分区中必须有多少个副本收到这条消息,生产者才会认为这条消息是成功写入的。acks是生产者客户端中一个非常重要的参数,她涉及到消息的可靠性和吞吐量之间的权衡,且是一个字符串类型。 acks = 1 生产者发送消息之后,只要分区的leader副本成功写入消息,那么它就会收到来自服务器的成功响应。如果消息无法写入leader副本,比如leader副本崩溃,重新选举新的leader副本的过程中,那么生产者就会收到一个错误的响应,为了避免消息丢失,生产者可以选择重新发送。如果消息写入leader副本并返回成功响应给生产者,且在被其他follower副本拉取之前leader副本崩溃,那么消息还是会丢失,因为新选举的leader副本中并没有这条对应的消息,acks设置为1,是消息可靠性和吞吐量之间的折中方案。 acks = 0 生产者发送消息之后不需要等待任何服务端的响应。如果在消息从发送到写入Kafka的过程中出现某些异常,导致Kafka并没有收到这条消息,此时消息丢失。在其他配置环境相同的情况下,acks 设为0可以达到最大的吞吐量。 acks = -1 或者acks = all ,生产者在消息发送之后,需要等待ISR中的所有副本都成功写入消息之后才能收到来自服务端的成功响应,在其他配置环境相同的情况下, acks = -1 或者acks = all 可以达到最强的可靠性,但并不保证一定可靠。 |
max.request.size: max.request.size: 这个参数用来限制生产者客户端能发送的消息的最大值,默认1MB。 |
retries和 retry.backoff.mx: retries和 retry.backoff.mx: retries 参数用来配置生产者重试的次数,默认值为0,即在发生异常的时候不进行任何重试动作,消息在从生产者发出到成功写入服务器之前可能会发生异常,比如网络抖动,leader 副本的选举等,这些异常往往都是可以自行恢复的,生产者可以通过配置retries 大于0 的值,以此通过内部重试来恢复而不是一味的将异常抛给生产者的应用程序。如果重试达到设定的次数,那么生产者就会放弃重试并返回异常。retry.backoff.mx 默认值为100,这个参数是用来设定重试之间的时间间隔,避免无效的频繁重试。 |
消息有序性的总结: Kafka 可以保证同一个分区中的消息是有序的,如果生产者按照一定的顺序发送消息,那么这些消息也会顺序的写入分区,进而消费者可以按照同样的顺序消费它们。对于某些应用来说,顺序性非常重要,比如mysql 的binlog 传输。如果将acks 参数配置为非零值,并且max.in.flight.requests.per.connection参数配置为大于1的值,那么就会出现错序的现象:如果第一批次消息写入失败,而第二批次消息写入成功,那么生产者会重试发送第一批次的消息,此时如果第一批次的消息写入成功,那么这两个批次的消息就会出现了错序。一般来说:在需要保证消息顺序的场合建议把参数max.in.flight.requests.per.connection配置为1,而不是把acks 配置为0,不过这样也会影响整体的吞吐。 |
compression.type: compression.type: 指定消息的压缩方式,默认值为:none,即不会被压缩。该参数还可以配置为("gzip","snappy","lz4")。对消息进行压缩可以极大的减少网络传输量,降低网络I/O。从而提高整体的性能。消息压缩是一种使用时间换空间的优化方式,如果对时间延迟有一定的要求,则不推荐对消息进行压缩。 |
connections.max.idle.mx: connections.max.idle.mx: 用来指定在多久之后关闭限制的连接,默认值9分钟【540000ms】 |
linger.ms: linger.ms:这个参数用来指定生产者发送producerBatch 之前等待更多的消息producerRecord加入producerBatch的时间,默认值为0。生产者客户端会在producerBatch被填满或等待时间超过linger.ms值时发送出去。增大这个参数的值会增加消息的延迟,但是同时能提升一定的吞吐量。 |
receive.buffer.bytes: receive.buffer.bytes: 用来设置socket接收消息缓冲区的大小,默认值为32KB。如果设置为-1 ,则使用操作系统的默认值,如果producer与Kafka处于不同的机房,则可以适当的调大这个参数值。 |
send.buffer.bytes: send.buffer.bytes: 参数用来设置socket 发送消息缓冲区的大小,默认值128KB。与receive.buffer.bytes参数一样,如果设置为-1,则使用操作系统的默认值。 |
request.timeout.ms: request.timeout.ms: 用来配置producer等待请求响应的最长时间,默认值30000ms。 请求超时后可以选择进行重试。注意,这个参数需要比broker端参数replica.lag.time.max.ms的值要大,这样可以减少因客户端重试而引起的消息重复的概率。 |
总结: Kafkaproducer 是线程安全的,我们可以在多线程的环境中复用它,而Kafkaconsumer,它是非线程安全的,因为它具备了状态。 |
kafka下载:Apache Kafka
下载好,解压。
启动步骤如下:
1.启动zookeeper: 1. cd C:\tools\kafka\kafka_2.11-1.1.1\bin\windows + 回车 2.zookeeper-server-start.bat C:\tools\kafka\kafka_2.11-1.1.1\config\zookeeper.properties +回车 【这样zk就启动啦】 |
2.启动kafka: 1. cd C:\tools\kafka\kafka_2.11-1.1.1\bin\windows + 回车 2.kafka-server-start.bat C:\tools\kafka\kafka_2.11-1.1.1\config\server.properties +回车 【这样kafka 就启动啦】 |
kafka Manager 安装: 1.下载安装包:https://pan.baidu.com/s/1tW_5diGSg2ZhJFAnwy4w9w 提取码:bps9 2.在c盘下进行建文件夹KM,将安装包进行解压 |
3.将配置文件C:\tools\km\km\conf\application.conf 修改成:kafka-manager.zkhosts="localhost:2181" |
4.启动C:\tools\km\km\bin\kafka-manager.bat【需要依次启动ZK,kafka,KM】 |
6.如下画面:
|
3.下面开始创建项目运用kafka
kafka 组件的概念:
topic主题 | Kafka 组消息抽象归纳为 个主题( Topic ),也就是说,一个主题就是对消息的 分类。生产者将消息发送到特定主题,消费者订阅主题或主题的某些分区进行消费。 offset偏移量,是消息在分区内的唯一标识,kafka 通过它来保证消息在分区内的顺序性,不过offset 并不跨越分区。 |
消息 |