消息中间件(十二)-----kafka入门、安装

Kafka入门

什么是Kafka

kafka最初是LinkedIn的一个内部基础设施系统。最初开发的起因是,LinkedIn虽然有了数据库和其他系统可以用来存储数据,但是缺乏一个可以帮助处理持续数据流的组件。所以在设计理念上,开发者不想只是开发一个能够存储数据的系统,如关系数据库、Nosql数据库、搜索引擎等等,更希望把数据看成一个持续变化和不断增长的流,并基于这样的想法构建出一个数据系统,一个数据架构。

Kafka可以看成一个流平台,这个平台上可以发布和订阅数据流,并把他们保存起来,进行处理。Kafka有点像消息系统,允许发布和订阅消息流,但是它和传统的消息系统有很大的差异,首先,Kafka是个现代分布式系统,以集群的方式运行,可以自由伸缩。其次,Kafka可以按照要求存储数据,保存多久都可以,第三,流式处理将数据处理的层次提示到了新高度,消息系统只会传递数据,Kafka的流式处理能力可以让我们用很少的代码就能动态地处理派生流和数据集。所以Kafka不仅仅是个消息中间件。

同时在大数据领域,Kafka还可以看成实时版的Hadoop,Hadoop可以存储和定期处理大量的数据文件,往往以TB计数,而Kafka可以存储和持续处理大型的数据流。Hadoop主要用在数据分析上,而Kafka因为低延迟,更适合于核心的业务应用上。

本次课程,将会以kafka_2.11-0.10.1.1版本为主,其余版本不予考虑。

Kafka中的基本概念

概述

在深入理解Kafka之前,先介绍一下Kafka中的术语。下图展示了Kafka的相关术语以及之间的关系:

上图中一个topic配置了3个partition。Partition1有两个offset:0和1。Partition2有4个offset。Partition3有1个offset。副本的id和副本所在的机器的id恰好相同。

如果一个topic的副本数为3,那么Kafka将在集群中为每个partition创建3个相同的副本。集群中的每个broker存储一个或多个partition。多个producer和consumer可同时生产和消费数据。

消息和批次

消息,Kafka里的数据单元,也就是我们一般消息中间件里的消息的概念。消息由字节数组组成。消息还可以包含键,用以对消息选取分区。

为了提高效率,消息被分批写入Kafka。批次就是一组消息,这些消息属于同一个主题和分区。如果只传递单个消息,会导致大量的网络开销,把消息分成批次传输可以减少这开销。但是,这个需要权衡,批次里包含的消息越多,单位时间内处理的消息就越多,单个消息的传输时间就越长。如果进行压缩,可以提升数据的传输和存储能力,但需要更多的计算处理。

主题和分区

Kafka里的消息用主题进行分类,主题下有可以被分为若干个分区。分区本质上是个提交日志,有新消息,这个消息就会以追加的方式写入分区,然后用先入先出的顺序读取。

但是因为主题会有多个分区,所以在整个主题的范围内,是无法保证消息的顺序的,单个分区则可以保证。

Kafka通过分区来实现数据冗余和伸缩性,因为分区可以分布在不同的服务器上,那就是说一个主题可以跨越多个服务器。

前面我们说Kafka可以看成一个流平台,很多时候,我们会把一个主题的数据看成一个流,不管有多少个分区。

Topic:每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)类似于数据库的表名。

Partition:topic中的数据分割为一个或多个partition。每个topic至少有一个partition。每个partition中的数据使用多个segment文件存储。partition中的数据是有序的,不同partition间的数据丢失了数据的顺序。如果topic有多个partition,消费数据时就不能保证数据的顺序。在需要严格保证消息的消费顺序的场景下,需要将partition数目设为1。

生产者和消费者、偏移量、消费者群组

就是一般消息中间件里生产者和消费者的概念。一些其他的高级客户端API,像数据管道API和流式处理的Kafka Stream,都是使用了最基本的生产者和消费者作为内部组件,然后提供了高级功能。

生产者即数据的发布者,该角色将消息发布到Kafka的topic中。broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition。

消费者订阅主题,一个或者多个,并且按照消息的生成顺序读取。消费者通过检查所谓的偏移量来区分消息是否读取过。偏移量是一种元数据,一个不断递增的整数值,创建消息的时候,Kafka会把他加入消息。在一个分区里,每个消息的偏移量是唯一的。每个分区最后读取的消息偏移量会保存到Zookeeper或者Kafka上,这样分区的消费者关闭或者重启,读取状态都不会丢失。

多个消费者可以构成一个消费者群组。怎么构成?共同读取一个主题的消费者们,就形成了一个群组。群组可以保证每个分区只被一个消费者使用。每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。

消费者和分区之间的这种映射关系叫做消费者对分区的所有权关系,很明显,一个分区只有一个消费者,而一个消费者可以有多个分区。

Broker和集群

Kafka 集群包含一个或多个服务器,服务器节点称为broker。

broker的主要工作是,接收生产者的消息,设置偏移量,提交消息到磁盘保存;为消费者提供服务,响应请求,返回消息。在合适的硬件上,单个broker可以处理上千个分区和每秒百万级的消息量。

多个broker可以组成一个集群。每个集群中broker会选举出一个集群控制器。控制器会进行管理,包括将分区分配给broker和监控broker。

集群里,一个分区从属于一个broker,这个broker被称为首领。但是分区可以被分配给多个broker,这个时候会发生分区复制。

broker存储topic的数据。如果某topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition。

如果某topic有N个partition,集群有(N+M)个broker,那么其中有N个broker存储该topic的一个partition,剩下的M个broker不存储该topic的partition数据。

如果某topic有N个partition,集群中broker数目少于N个,那么一个broker存储该topic的一个或多个partition。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致Kafka集群数据不均衡。

分区复制带来的好处是,提供了消息冗余。一旦首领broker失效,其他broker可以接管领导权。当然相关的消费者和生产者都要重新连接到新的首领上。

保留消息

在一定期限内保留消息是Kafka的一个重要特性,Kafka  broker默认的保留策略是:要么保留一段时间,要么保留一定大小。到了限制,旧消息过期并删除。但是每个主题可以根据业务需求配置自己的保留策略。

Leader

每个partition有多个副本,其中有且仅有一个作为Leader,Leader是当前负责数据的读写的partition。

Follower

Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。如果Leader失效,则从Follower中选举出一个新的Leader。当Follower与Leader挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower。

为什么选择Kafka

优点

多生产者和多消费者

基于磁盘的数据存储,换句话说,Kafka的数据天生就是持久化的。

高伸缩性,Kafka一开始就被设计成一个具有灵活伸缩性的系统,对在线集群的伸缩丝毫不影响整体系统的可用性。

高性能,结合横向扩展生产者、消费者和broker,Kafka可以轻松处理巨大的信息流,同时保证亚秒级的消息延迟。

常见场景

活动跟踪

跟踪网站用户和前端应用发生的交互,比如页面访问次数和点击,将这些信息作为消息发布到一个或者多个主题上,这样就可以根据这些数据为机器学习提供数据,更新搜素结果等等。

传递消息

标准消息中间件的功能

收集指标和日志

收集应用程序和系统的度量监控指标,或者收集应用日志信息,通过Kafka路由到专门的日志搜索系统,比如ES。

提交日志

收集其他系统的变动日志,比如数据库。可以把数据库的更新发布到Kafka上,应用通过监控事件流来接收数据库的实时更新,或者通过事件流将数据库的更新复制到远程系统。

还可以当其他系统发生了崩溃,通过重放日志来恢复系统的状态。

流处理

操作实时数据流,进行统计、转换、复杂计算等等。随着大数据技术的不断发展和成熟,无论是传统企业还是互联网公司都已经不再满足于离线批处理,实时流处理的需求和重要性日益增长。

近年来业界一直在探索实时流计算引擎和API,比如这几年火爆的Spark Streaming、Kafka Streaming、Beam和Flink,其中阿里双11会场展示的实时销售金额,就用的是流计算,是基于Flink,然后阿里在其上定制化的Blink。

基本的操作和管理

##列出所有主题

kafka-topics.bat --zookeeper localhost:2181/kafka --list

##列出所有主题的详细信息

kafka-topics.bat --zookeeper localhost:2181/kafka --describe

##创建主题 主题名 my-topic1副本,8分区

kafka-topics.bat --zookeeper localhost:2181/kafka --create --topic my-topic --replication-factor 1 --partitions 8

##增加分区,注意:分区无法被删除

kafka-topics.bat --zookeeper localhost:2181/kafka --alter --topic my-topic --partitions 16

##删除主题

kafka-topics.bat --zookeeper localhost:2181/kafka --delete --topic my-topic

##列出消费者群组(仅Linux

kafka-topics.sh --new-consumer --bootstrap-server localhost:9092/kafka --list

##列出消费者群组详细信息(仅Linux

kafka-topics.sh --new-consumer --bootstrap-server localhost:9092/kafka --describe --group 群组名

Broker配置

配置文件放在Kafka目录下的config目录中,主要是server.properties文件

常规配置

broker.id

在单机时无需修改,但在集群下部署时往往需要修改。它是个每一个broker在集群中的唯一表示,要求是正数。当该服务器的IP地址发生改变时,broker.id没有变化,则不会影响consumers的消息情况

listeners

监听列表(以逗号分隔 不同的协议(plaintext,trace,ssl、不同的IP和端口)),hostname如果设置为0.0.0.0则绑定所有的网卡地址;如果hostname为空则绑定默认的网卡。如果
没有配置则默认为java.net.InetAddress.getCanonicalHostName()。

如:PLAINTEXT://myhost:9092,TRACE://:9091PLAINTEXT://0.0.0.0:9092,

zookeeper.connect

zookeeper集群的地址,可以是多个,多个之间用逗号分割

log.dirs

Kafka把所有的消息都保存在磁盘上,存放这些数据的目录通过log.dirs指定

num.recovery.threads.per.data.dir

每数据目录用于日志恢复启动和关闭时的线程数量因为这些线程只是服务器启动和关闭时会用到所以完全可以设置大量的线程来达到并行操作的目的注意这个参数指的是每个日志目录的线程数比如本参数设置为8,而log.dirs设置为了三个路径,则总共会启动24个线程。

auto.create.topics.enable

是否允许自动创建主题。如果设为true,那么produceconsume或者fetch metadata一个不存在的主题时,就会自动创建。缺省为true

主题配置

新建主题的默认参数

num.partitions

每个新建主题的分区个数这个参数一般要评估比如每秒钟要写入和读取1GB数据,如果现在每个消费者每秒钟可以处理50MB的数据,那么需要20个分区,这样就可以让20个消费者同时读取这些分区,从而达到设计目标。

log.retention.hours

日志保存时间,默认为7天(168小时)。超过这个时间会清理数据。bytesminutes无论哪个先达到都会触发。与此类似还有log.retention.minuteslog.retention.ms,都设置的话,优先使用具有最小值的那个。

log.retention.bytes

topic每个分区的最大文件大小,一个topic的大小限制 = 分区数*log.retention.bytes-1没有大小限制。log.retention.byteslog.retention.minutes任意一个达到要求,都会执行删除。

log.segment.bytes

分区的日志存放在某个目录下诸多文件中,这些文件将分区的日志切分成一段一段的,我们称为日志片段。这个属性就是每个文件的最大尺寸;当尺寸达到这个数值时,就会关闭当前文件,并创建新文件。被关闭的文件就开始等待过期。默认为1G

如果一个主题每天只接受100MB的消息,那么根据默认设置,需要10天才能填满一个文件。而且因为日志片段在关闭之前,消息是不会过期的,所以如果log.retention.hours保持默认值的话那么这个日志片段需要17天才过期。因为关闭日志片段需要10天,等待过期又需要7天。

log.segment.ms

作用和log.segment.bytes类似,只不过判断依据是时间。同样的,两个参数,以先到的为准。这个参数默认是不开启的。

message.max.bytes

表示一个服务器能够接收处理的消息的最大字节数,注意这个值producerconsumer必须设置一致,且不要大于fetch.message.max.bytes属性的值。该值默认是1000000字节,大概900KB~1MB

硬件配置对Kafka性能的影响

磁盘吞吐量/磁盘容量

磁盘吞吐量会影响生产者的性能。因为生产者的消息必须被提交到服务器保存,大多数的客户端都会一直等待,直到至少有一个服务器确认消息已经成功提交为止。也就是说,磁盘写入速度越快,生成消息的延迟就越低。

磁盘容量的大小,则主要看需要保存的消息数量。如果每天收到1TB的数据,并保留7天,那么磁盘就需要7TB的数据。

内存

Kafka本身并不需要太大内存,内存则主要是影响消费者性能。在大多数业务情况下,消费者消费的数据一般会从内存中获取,这比在磁盘上读取肯定要快的多。

网络

网络吞吐量决定了Kafka能够处理的最大数据流量。

CPU

Kafkacpu的要求不高,主要是用在对消息解压和压缩上。所以cpu的性能不是在使用Kafka的首要考虑因素。

Kafka的集群

为何需要Kafka集群

本地开发,一台Kafka足够使用。在实际生产中,集群可以跨服务器进行负载均衡,再则可以使用复制功能来避免单独故障造成的数据丢失。同时集群可以提供高可用性。

如何估算Kafka集群中Broker的数量

要估量以下几个因素:

需要多少磁盘空间保留数据,和每个broker上有多少空间可以用。比如,如果一个集群有10TB的数据需要保留,而每个broker可以存储2TB,那么至少需要5broker。如果启用了数据复制,则还需要一倍的空间,那么这个集群需要10broker

集群处理请求的能力。如果因为磁盘吞吐量和内存不足造成性能问题,可以通过扩展broker来解决。

Broker如何加入Kafka集群

非常简单,只需要两个参数。第一,配置zookeeper.connect,第二为新增的broker设置一个集群内的唯一性id

安装Kafka

下载

wget http://mirrors.hust.edu.cn/apache/kafka/2.0.0/kafka_2.12-2.0.0.tgz

如果下载比较慢,也可以提前下载压缩包,然后上传到服务器上。

解压

tar -zxvf kafka_2.12-2.0.0.tgz

注意,kafka_2.12-2.0.0.tgz版本是已经编译好的版本,解压就能使用。

修改配置文件

进入kafka的安装配置目录

[hadoop@hadoop1 ~]$ cd apps/kafka/config/

主要关注:server.properties 这个文件即可,我们可以发现在目录下:

有很多文件,这里可以发现有Zookeeper文件,我们可以根据Kafka内带的zk集群来启动,但是建议使用独立的zk集群

server.properties(broker.id和host.name每个节点都不相同) 

//当前机器在集群中的唯一标识,和zookeeper的myid性质一样
broker.id=0
//当前kafka对外提供服务的端口默认是9092
port=9092
//这个参数默认是关闭的,在0.8.1有个bug,DNS解析问题,失败率的问题。
host.name=hadoop1
//这个是borker进行网络处理的线程数
num.network.threads=3
//这个是borker进行I/O处理的线程数
num.io.threads=8
//发送缓冲区buffer大小,数据不是一下子就发送的,先回存储到缓冲区了到达一定的大小后在发送,能提高性能
socket.send.buffer.bytes=102400
//kafka接收缓冲区大小,当数据到达一定大小后在序列化到磁盘
socket.receive.buffer.bytes=102400
//这个参数是向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小
socket.request.max.bytes=104857600
//消息存放的目录,这个目录可以配置为“,”逗号分割的表达式,上面的num.io.threads要大于这个目录的个数这个目录,
//如果配置多个目录,新创建的topic他把消息持久化的地方是,当前以逗号分割的目录中,那个分区数最少就放那一个
log.dirs=/home/hadoop/log/kafka-logs
//默认的分区数,一个topic默认1个分区数
num.partitions=1
//每个数据目录用来日志恢复的线程数目
num.recovery.threads.per.data.dir=1
//默认消息的最大持久化时间,168小时,7天
log.retention.hours=168
//这个参数是:因为kafka的消息是以追加的形式落地到文件,当超过这个值的时候,kafka会新起一个文件
log.segment.bytes=1073741824
//每隔300000毫秒去检查上面配置的log失效时间
log.retention.check.interval.ms=300000
//是否启用log压缩,一般不用启用,启用的话可以提高性能
log.cleaner.enable=false
//设置zookeeper的连接端口
zookeeper.connect=192.168.123.102:2181,192.168.123.103:2181,192.168.123.104:2181
//设置zookeeper的连接超时时间
zookeeper.connection.timeout.ms=6000

producer.properties

metadata.broker.list=192.168.123.102:9092,192.168.123.103:9092,192.168.123.104:9092

consumer.properties

zookeeper.connect=192.168.123.102:2181,192.168.123.103:2181,192.168.123.104:2181

启动

首先启动zookeeper集群

所有zookeeper节点都需要执行

[hadoop@hadoop1 ~]$ zkServer.sh start

启动Kafka集群服务

[hadoop@hadoop1 kafka]$ bin/kafka-server-start.sh config/server.properties

猜你喜欢

转载自www.cnblogs.com/alimayun/p/12907437.html