序言
说明下安装环境.在centos7上安装Kafka集群环境.
Kafka 依赖Java环境,所以需要提前配置.Kafka有自带的Zookeeper,但是一般不用.
Zookeeper集群环境安装请看另一篇文章.这里只描述kafka的环境搭建.
名词解释
- Broker——Kafka集群包含一个或多个服务器,这种服务器被称为broker ;
- Topic——每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)
- Partition——Partition是物理上的概念,每个Topic包含一个或多个Partition.
- Producer——负责发布消息到Kafka broker
- Consumer——消息消费者,向Kafka broker读取消息的客户端。
- Consumer Group——每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。
Kafka的topic可以看做是一个记录流 ("/orders", "/user-signups"),每个topic都有一个日志,它存储在磁盘上。
每个topic又被分成多个partition(区),每个partition在存储层面是append log文件,任何发布到partition的消息都会被直接追加到日志文件的尾部,Kafka Producer API用于生成数据记录流,Kafka Consumer API用于使用Kafka的记录流。
topic与日志相关联,日志是存储在磁盘上的数据结构,Kafka将producer的记录附加到topic日志的末尾。topic日志由分布在多个文件上的许多分区组成,这些文件可以分布在多个Kafka集群节点上。Kafka在集群的不同节点上分发topic日志分区,以实现具有水平可伸缩性的高性能。Spreading 分区有助于快速写入数据,Kafka将分区复制到许多节点以提供故障转移。
关于Kafka集群建通信的问题
在Kafka集群中会有一个或者多个broker,其中有一个broker会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态。当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。当使用kafka-topics.sh脚本为某个topic增加分区数量时,同样还是由控制器负责分区的重新分配。
这里请注意 kafka集群其实有两种类型的Leader,切都是由zookeeper选举产生的.即:Broker的Controller,Partition的Leader.
关于Kafka的高可用性
引入Replication之后,同一个Partition可能会有多个Replica,而这时需要在这些Replication之间选出一个Leader,Producer和Consumer只与这个Leader交互,其它Replica作为Follower从Leader中复制数据。
因为需要保证同一个Partition的多个Replica之间的数据一致性(其中一个宕机后其它Replica必须要能继续服务并且即不能造成数据重复也不能造成数据丢失)。如果没有一个Leader,所有Replica都可同时读/写数据,那就需要保证多个Replica之间互相(N×N条通路)同步数据,数据的一致性和有序性非常难保证,大大增加了Replication实现的复杂性,同时也增加了出现异常的几率。而引入Leader后,只有Leader负责数据读写,Follower只向Leader顺序Fetch数据(N条通路),系统更加简单且高效。
为了更好的做负载均衡,Kafka尽量将所有的Partition均匀分配到整个集群上。一个典型的部署方式是一个Topic的Partition数量大于Broker的数量。同时为了提高Kafka的容错能力,也需要将同一个Partition的Replica尽量分散到不同的机器。实际上,如果所有的Replica都在同一个Broker上,那一旦该Broker宕机,该Partition的所有Replica都无法工作,也就达不到HA的效果。同时,如果某个Broker宕机了,需要保证它上面的负载可以被均匀的分配到其它幸存的所有Broker上。
Producer在发布消息到某个Partition时,先通过ZooKeeper找到该Partition的Leader,然后无论该Topic的Replication Factor为多少,Producer只将该消息发送到该Partition的Leader。Leader会将该消息写入其本地Log。每个Follower都从Leader pull数据。这种方式上,Follower存储的数据顺序与Leader保持一致。Follower在收到该消息并写入其Log后,向Leader发送ACK。一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW并且向Producer发送ACK。
为了提高性能,每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中。因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中,也就不能完全保证异常发生后该条消息一定能被Consumer消费。
Consumer读消息也是从Leader读取,只有被commit过的消息才会暴露给Consumer。
安装集群
下载kafka,并解压.
[root@localhost cuiyaonan]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.3.0/kafka_2.11-2.3.0.tgz
[root@cuiyaonan2000@163.com kafka]# tar -zxvf kafka_2.11-2.3.0.tgz
[root@cuiyaonan2000@163.com kafka]# cp -rf kafka_2.11-2.3.0 kafka-01
[root@cuiyaonan2000@163.com kafka]# cp -rf kafka_2.11-2.3.0 kafka-02
[root@cuiyaonan2000@163.com kafka]# cp -rf kafka_2.11-2.3.0 kafka-03
然后依次修改config/server.properties
# kafka服务器监听IP和端口,这里也可以写域名,只要能解析就行
# 如果多个kafka在同一台机器上则端口号要区分开
listeners=PLAINTEXT://192.168.2.63:9092
# 三台服务器的ID不能相同,第一台是1,第二台是2,第三台是3
broker.id=1
# 日志路径 依次类推k1,k2,k3
log.dirs=/home/cuiyaonan/kafka/logs/k1
# Zookeeper连接参数
zookeeper.connect=192.168.2.64:2181,192.168.2.64:2182,192.168.2.64:2183
另外其他的配置信息如下:
broker.id=0 #当前机器在集群中的唯一标识,和zookeeper的myid性质一样
#这个属性貌似被取消了
port=19092 #当前kafka对外提供服务的端口默认是9092
host.name=192.168.7.100 #这个参数默认是关闭的,在0.8.1有个bug,DNS解析问题,失败率的问题。
num.network.threads=3 #这个是borker进行网络处理的线程数
num.io.threads=8 #这个是borker进行I/O处理的线程数
log.dirs=/opt/kafka/kafkalogs/ #消息存放的目录,这个目录可以配置为“,”逗号分割的表达式,上面的
num.io.threads要大于这个目录的个数这个目录,如果配置多个目录,新创建的topic他把消息持久化的地方是,当前以逗号分割的目录中,那个分区数最少就放那一个
socket.send.buffer.bytes=102400 #发送缓冲区buffer大小,数据不是一下子就发送的,先回存储到缓冲区了到达一定的大小后在发送,能提高性能
socket.receive.buffer.bytes=102400 #kafka接收缓冲区大小,当数据到达一定大小后在序列化到磁盘
socket.request.max.bytes=104857600 #这个参数是向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小
num.partitions=1 #默认的分区数,一个topic默认1个分区数
log.retention.hours=168 #默认消息的最大持久化时间,168小时,7天
message.max.byte=5242880 #消息保存的最大值5M
default.replication.factor=2 #kafka保存消息的副本数,如果一个副本失效了,另一个还可以继续提供服务
replica.fetch.max.bytes=5242880 #取消息的最大直接数
log.segment.bytes=1073741824 #这个参数是:因为kafka的消息是以追加的形式落地到文件,当超过这个值的时候,kafka会新起一个文件
log.retention.check.interval.ms=300000 #每隔300000毫秒去检查上面配置的log失效时间
(log.retention.hours=168 ),到目录查看是否有过期的消息如果有,删除
log.cleaner.enable=false #是否启用log压缩,一般不用启用,启用的话可以提高性能
zookeeper.connect=192.168.7.100:12181,192.168.7.101:12181,192.168.7.107:1218
#设置zookeeper的连接端口
依次启动kafka
[root@cuiyaonan2000@163.com bin]# ./kafka-server-start.sh -daemon ../config/server.properties
创建与查看Topic
创建命令如下,其中zookeeper 如果是集群随便一个就行
[root@cuiyaonan2000 bin]# ./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 3 --topic testTopic
- --replication-factor 3 :表示每个分区的副本数,并且注意副本是存放于不同broker上的,因此有个限制就是,副本数不能超过broker的数量
- --partitions 3: 新建topic的分区个数,分区没有borker的限制,可以有多个。
- --topic testTopic : 新建topic的名称
查看topic的命令如下(换了个zookeeper查看)
[root@cuiyaonan2000 bin]# ./kafka-topics.sh --list --zookeeper localhost:2181