一、kafka简介
Kafka最初由Linkedin公司开发,是一个分布式的、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常用于web/nginx日志、访问日志、消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。

 

二、kafka的特性
高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒;
可扩展性:kafka集群支持热扩展;
持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止丢失;
容错性:允许集群中的节点失败(若副本数量为n,则允许n-1个节点失败);
高并发:单机可支持数千个客户端同时读写;

三、kafka的应用场景
日志收集:一个公司可以用Kafka收集各种服务的log,通过kafka以统一接口开放给各种消费端,例如hadoop、Hbase、Solr等。
消息系统:解耦生产者和消费者、缓存消息等。
用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索记录、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka也经常用来记录运营监控数据。
流式处理
 

四、kafka架构

kafka设置最大并发连接数 kafka最大支持连接数_kafka

kafka架构中包含四大组件:生产者、消费者、kafka集群、zookeeper集群

对照上面的结构图,我们先来搞清楚几个很重要的术语:

1、broker

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

2、topic

每条发布到kafka集群的消息都有一个类别,这个类别称为topic,其实就是将消息按照topic来分类,topic是逻辑上的分类,同一个topic的数据既可以在同一个broker上也可以在不同的broker结点上。

3、partition

分区,每个topic被物理划分为一个或多个分区,每个分区在物理上对应一个文件夹,该文件夹里面存储了这个分区的所有消息和索引文件。在创建topic时可指定parition数量,生产者将消息发送到topic时,消息会根据 分区策略 追加到分区文件的末尾,属于顺序写磁盘,因此效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)。

kafka设置最大并发连接数 kafka最大支持连接数_scala_02

上面提到了分区策略,所谓分区策略就是决定生产者将消息发送到哪个分区的算法。Kafka 为我们提供了默认的分区策略,同时它也支持自定义分区策略。kafka允许为每条消息设置一个key,一旦消息被定义了 Key,那么就可以保证同一个 Key 的所有消息都进入到相同的分区,这种策略属于自定义策略的一种,被称作"按消息key保存策略",或Key-ordering 策略。

同一topic的多个分区可以部署在多个机器上,以此来实现 kafka 的伸缩性。同一partition中的数据是有序的,但topic下的多个partition之间在消费数据时不能保证有序性,在需要严格保证消息顺序消费的场景下,可以将partition数设为1,但这种做法的缺点是降低了吞吐,一般来说,只需要保证每个分区的有序性,再对消息设置key来保证相同key的消息落入同一分区,就可以满足绝大多数的应用。
4、offset

partition中的每条消息都被标记了一个序号,这个序号表示消息在partition中的偏移量,称为offset,每一条消息在partition都有唯一的offset,消费者通过指定offset来指定要消费的消息。

正常情况下,消费者在消费完一条消息后会递增offset,准备去消费下一条消息,但也可以将offset设成一个较小的值,重新消费一些消费过的消息,可见offset是由consumer控制的,consumer想消费哪一条消息就消费哪一条消息,所以kafka broker是无状态的,它不需要标记哪些消息被消费过。

5、producer

生产者,生产者发送消息到指定的topic下,消息再根据分配规则append到某个partition的末尾。

6、consumer

消费者,消费者从topic中消费数据。

7、consumer group

消费组,每个consumer属于一个特定的consumer group,可以通过consumer.propertise文件中的group.id属性指定,如果不指定,默认是"test-consumer-group"。

一个consumer可以消费多个partition,但是同一个partition只能被同一个consumer group里面的一个consumer消费。一个consumer占用该partition的消费后,本消费组中的其他消费者将不能再消费,但其他消费组的消费者仍然可以消费。

这也是kafka用来实现消息的广播和单播的手段,如果需要实现广播,一个consumer group内只放一个消费者即可;要实现单播,将所有的消费者放到同一个consumer group即可。

8、leader

每个partition有多个副本,其中有且仅有一个作为leader,leader会负责所有的客户端读写操作。

9、follower

follower不对外提供服务,只与leader保持数据同步,如果leader失效,则选举一个follower来充当新的leader。当follower与leader挂掉、卡住或者同步太慢,leader会把这个follower从ISR列表中删除,重新创建一个follower。

10、rebalance

同一个consumer group下的多个消费者互相协调消费工作,我们这样想,一个topic分为多个分区,一个consumer group里面的所有消费者合作,一起去消费所订阅的某个topic下的所有分区(每个消费者消费部分分区),kafka会将该topic下的所有分区均匀的分配给consumer group下的每个消费者,如下图,

kafka设置最大并发连接数 kafka最大支持连接数_scala_03

Rebalance表示"重平衡",consumer group内某个消费者挂掉后,其他消费者自动重新分配订阅主题分区的过程,是 Kafka 消费者端实现高可用的重要手段。如下图Consumer Group A中的C2挂掉,C1会接收P1和P2,以达到重新平衡。同样的,当有新消费者加入consumer group,也会触发重平衡操作。
 

kafka集群搭建

  • 使用vm虚拟三个linux主机,IP分别为

192.168.234.101

192.168.234.102

192.168.234.103

  • 确保每个节点上已安装好jdk1.8环境
  • 每台服务器节点安装好zookeeper

1.下载并且安装zookeeper安装包
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.6.0/zookeeper-3.6.0.tar.gz
2. 解压安装包
tar -zxvf zookeeper-3.6.0.tar.gz
3. 重命名
重命名: mv zookeeper-3.6.0 zookeeper

  • 搭建Zookeeper集群环境

修改zoo_sample.cfg文件

cd /usr/local/zookeeper/conf
mv zoo_sample.cfg zoo.cfg
修改conf: vi zoo.cfg 修改两处
(1) dataDir=/usr/local/zookeeper/data(注意同时在zookeeper创建data目录)
(2)最后面添加
server.0=192.168.234.101:2888:3888
server.1=192.168.234.102:2888:3888
server.2=192.168.234.103:2888:3888

  • 创建服务器标识

服务器标识配置:
创建文件夹: mkdir data
创建文件myid并填写内容为0: vi
myid (内容为服务器标识 : 0)

  • 关闭每台服务器节点防火墙,systemctl stop firewalld.service
  • 启动zookeeper
    启动zookeeper:
    路径: /usr/local/zookeeper/bin
    执行: zkServer.sh start
    (注意这里3台机器都要进行启动)
    状态: zkServer.sh status(在三个节点上检验zk的mode,一个leader和俩个follower)
  • 安装kafuka

下载kafka压缩包
wget https://mirror.bit.edu.cn/apache/kafka/2.5.0/kafka_2.13-2.5.0.tgz
tar -zxvf kafka_2.13-2.5.0.tgz 
mv kafka_2.13-2.5.0 kafka

  • // 修改配置文件(同步修改192.168.234.101和192.168.234.102)
    vi ./kafka/config/server.properties
    broker.id=0
    listeners=PLAINTEXT://192.168.234.103:9092
    zookeeper.connect=192.168.234.101:2181,192.168.234.102:2181,192.168.234.103:2181
  • 在系统环境中配置kafka的路径(同步修改192.168.234.101和192.168.234.102)

vi /etc/profile

增加下面内容:
export KAFKA_HOME=/home/software/kafka
export ZOOKEEPER_HOME=/home/software/zookeeper
// 多路径PATH写法为PATH=${ZOOKEEPER_HOME}/bin:${KAFKA_HOME}/bin:$PATH
export PATH=$PATH:$KAFKA_HOME/bin:$ZOOKEEPER_HOME/bin
// 使修改完的环境变量生效
source /etc/profile

  • 在后台开启3台虚拟机启动kafka程序(cd /usr/local/kafka)

./bin/kafka-server-start.sh -daemon config/server.properties

在三个节点输入jps都能够看到kafka,表示启动正常,或者看日志检查是否报错。

[root@slave1 bin]# jps
2949 Kafka
2521 QuorumPeerMain
3018 Jps

 

验证是否成功

在kafka安装目录,创建一个topic

[root@master kafka]# bin/kafka-topics.sh --create --zookeeper 192.168.234.101:2181 --replication-factor 3 --partitions 3 --topic my-test 
 Created topic my-test.
 [root@master kafka]#

打开zookeeper连接工具,检查已经创建成功

kafka设置最大并发连接数 kafka最大支持连接数_zookeeper_04

生产者连接my-test
[root@master kafka]# bin/kafka-console-producer.sh --broker-list 192.168.234.101:9092 --topic my-test
 >ni^H^H
 >玩一会消费者连接my-test
[root@master kafka]# bin/kafka-console-consumer.sh --bootstrap-server 192.168.234.101:9092 --topic my-test --from-beginning
 ni
 玩一会

 

kafka常用命令


 

经验分享:

在启动kafka的时候总是报这个错,后面切换1.8最稳定版本:1.8.0_241版本,问题解决了!!!

链接: https://pan.baidu.com/s/1vBOB4MHGS9-5N_n5Chl-UQ 提取码: cqqn

[2020-05-22 21:06:10,287] INFO Registered kafka:type=kafka.Log4jController MBean (kafka.utils.Log4jControllerRegistration$)
 [2020-05-22 21:06:10,725] ERROR Exiting Kafka due to fatal exception (kafka.Kafka$)
 java.lang.VerifyError: Uninitialized object exists on backward branch 50
 Exception Details:
   Location:
     scala/util/matching/Regex.unapplySeq(Ljava/lang/CharSequence;)Lscala/Option; @97: goto
   Reason:
     Error exists in the bytecode
   Bytecode:
     0000000: 2ab6 004b 2bb6 004f 4d2a 2cb6 0053 9900
     0000010: 6abb 0055 59b2 005a 572c b600 5e3e bb00
     0000020: 6059 b700 643a 0419 041d b900 6a02 0003
     0000030: 3605 1505 1da2 002f 2c15 0504 60b6 006e
     0000040: 3a08 1908 013a 083a 0719 0701 3a07 3a06
     0000050: 1904 1906 b600 7257 013a 0615 0504 6036
     0000060: 05a7 ffd1 1904 b900 7601 00c0 0078 013a
     0000070: 0401 3a06 b700 7bb0 b200 80b0
   Stackmap Table:
     full_frame(@50,{Object[#2],Object[#140],Object[#57],Integer,Object[#96],Integer},{Uninitialized[#17],Uninitialized[#17]})
     full_frame(@100,{Object[#2],Object[#140],Object[#57],Integer,Object[#96],Integer},{Uninitialized[#17],Uninitialized[#17]})
     chop_frame(@120,3)        at scala.collection.StringOps$.r$extension(StringOps.scala:843)
         at kafka.cluster.EndPoint$.<clinit>(EndPoint.scala:29)
         at kafka.server.Defaults$.<clinit>(KafkaConfig.scala:79)
         at kafka.server.KafkaConfig$.<clinit>(KafkaConfig.scala:961)
         at kafka.metrics.KafkaMetricsConfig.<init>(KafkaMetricsConfig.scala:33)
         at kafka.metrics.KafkaMetricsReporter$.startReporters(KafkaMetricsReporter.scala:62)
         at kafka.server.KafkaServerStartable$.fromProps(KafkaServerStartable.scala:33)
         at kafka.Kafka$.main(Kafka.scala:68)
         at kafka.Kafka.main(Kafka.scala)
 [2020-05-22 21:07:10,098] INFO Registered kafka:type=kafka.Log4jController MBean (kafka.utils.Log4jControllerRegistration$)