Kafka 从入门到放弃

 

kafka 是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域。

  一、中间件常识


【1】消息系统分类(两种)1)、Peer-to-Peer:发送到队列中的消息仅仅被一个接收者接收。支持异步 “即发即弃” 的消息传送方式,也支持同步 “请求应答” 传送方式。
   2)、发布/订阅模式:发布到一个主题的消息,可以被多个订阅者所接收。也可以设置为单播(只允许一个消费者消费)。
【2】消息系统使用场景:1)、解耦:各系统之间通过消息系统这个统一的接口交换数据,无需了解彼此的存在。
   2)、持久化:部分消息系统具有消息持久化能力,避免消息的丢失。
   3)、峰值处理能力:消息系统可顶住峰值流量,业务系统可根据系统处理能力从消息系统获取并处理对应的请求。
   4)、可恢复性:系统中部分主键失效并不会影响整个系统,它恢复后仍然可以从消息系统中获取并处理消息。
   5)、异步通信:在不需要立即处理请求的场景下,可以将请求放入到消息系统,合适的时候再处理。
   6)、消息通信消息队列一般都内置了高效的通信机制,因此也可以用纯消息通信。比如实现点对点消息队列,或者聊天室。
【3】常用消息系统对比:1)RabbitMQ:Erlang编写,支持多种协议AMQP、XMPP、SMTP、STOMP。支持负载均衡和数据持久化。AMQP协议的领导实现,支持多种场景。淘宝的 MySQL 集群内部有使用它进行通讯。OpenStack 开源云平台的通信组件,最先在金融行业得到运用。
   2)ActiveMQ:是 Apache 出品,最流行的,能力强劲的开源消息总线,ActiveMQ 是一个完全支持 JMS1.1 和 J2EE1.4 规范的 JMS Provider 实现。支持持久化和 XA 事务。缺点:主要支持 Java 语言,不跨语言。
   3)ZeroMQ:史上最快的消息队列系统。
   4)Kafka:Apache 下的一个子项目,特点:高吞吐,在一台普通的服务器上既可以达到 10w/s 的吞吐速率,完全的分布式系统,适合处理海量数据。同时支持在线和离线处理。

二、kafka 的设计目标


  ■  高吞吐率:在连接的商用机器上单机可支持每秒100万条消息的读写。
  ■  消息持久化:所有消息均被持久化到磁盘,无消息丢失,支持消息重放。
  ■  完全分布式:Producer、Broker、Consumer 均支持水平扩展。

三、kafka 组件


【1】Kafka 服务:Kafka 服务就像是一个大的水池。不断的生产、存储、消费着各种类别的消息。
   ■ Topic:主题,Kafka 处理的消息的不同分类。
   ■ Broker:消息代理,Kafka 集群中的一个 Kafka 服务节点称为一个 Broker,主要存储消息数据。存在硬盘中。每个 Topic 都是有分区的。
   ■ Partition:Topic 物理上的分组,一个 Topic 在 Broker 中被分为 1个或者多个 Partition,分区在创建 Topic 的时候指定。
   ■ Message:消息,是通信的基本单位,每个消息都属于一个 Partition。
【2】Kafka 服务相关:
   ■ Producer:消息和数据的生产者,向 Kafka 的一个 Topic 发布消息。
   ■ Consumer:消息和数据的消费者,定期向 Topic 并发处理其发布的消息。
   ■ Zookeeper:协调 Kafka 的正常运行。

四、Broker


配置文件 server.properties,位于 kafka/config 目录下。 server.properties 重点信息说明:


############################# Server Basics #############################
# broker就是一个kafka的部署实例,在一个kafka集群中,每一台kafka都要有一个broker.id
# 并且,该id唯一,且必须为整数
broker.id=10

##################################################################################
# 默认处理网络请求的线程个数 3个
num.network.threads=3

##################################################################################
# 执行磁盘IO操作的默认线程个数 8
num.io.threads=8

##################################################################################
# socket服务 进行发送数据的缓冲区大小,默认100kb
socket.send.buffer.bytes=102400

##################################################################################
# socket服务所能够接收的最大的请求量,防止出现OOM(Out of memory)内存溢出,默认值为:100m
# (应该是socker server所能接收的一个请求的最大大小,默认为100M)
##################################################################################
socket.request.max.bytes=104857600

####################### Log Basics (数据相关部分,kafka的数据称为log)##############
# 一个用逗号分隔的目录列表,用于存储kafka接收到的数据
log.dirs=/home/uplooking/data/kafka

##################################################################################
# 每一个topic 所对应的 log 的 partition 分区数目,默认1个。更多的partition数目会提高消费
# 并行度,但是也会导致在kafka集群中有更多的文件进行传输
# (partition就是分布式存储,相当于是把一份数据分开几份来进行存储,即划分块、划分分区的意思)
num.partitions=1

##################################################################################
# 每一个数据目录用于在启动 kafka时恢复数据和在关闭时刷新数据的线程个数。如果kafka数据存储在磁盘阵列中
# 建议此值可以调整更大。
num.recovery.threads.per.data.dir=1

############################# Log Flush Policy (数据刷新策略)#####################
# kafka中只有基于消息条数和时间间隔数来制定数据刷新策略,而没有大小的选项,这两个选项可以选择配置一个
# 当然也可以两个都配置,默认情况下两个都配置,配置如下。
# 消息刷新到磁盘中的消息条数阈值
log.flush.interval.messages=10000

# 消息刷新到磁盘生成一个log数据文件的时间间隔
log.flush.interval.ms=1000

############################# Log Retention Policy(数据保留策略)###################
# 下面的配置用于控制数据片段的清理,只要满足其中一个策略(基于时间或基于大小),分片就会被删除
# 基于时间的策略,删除日志数据的时间,默认保存7天
log.retention.hours=168

# 基于大小的策略,1G
#log.retention.bytes=1073741824

# 数据分片策略
log.segment.bytes=1073741824

# 每隔多长时间检测数据是否达到删除条件
log.retention.check.interval.ms=300000

############################# Zookeeper ############################
# zookeeper 的集群
zookeeper.connect=uplooking01:2181,uplooking02:2181,uplooking03:2181
# 连接 zookeeper 的超时时间
zookeeper.connection.timeout.ms=6000

五、Producer


配置文件:producer.properties

【1】自定义 Partition:Producer 根据用户设置的算法和消息的 key 来计算发送到哪个 Partition:partitioner.class
【2】异步或者同步发送,配置项:producer.type:
    同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据的通讯方式。  
    异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据的通讯方式。
【3】批量发送可以很有效的提高发送效率:Kafka producer 的异步发送模式允许进行批量发送,先将消息缓存在内存中,然后一次请求批量发送出去。具体配置queue.buffering.max.ms、queue.buffering.max.messages。默认值分别为5000和10000

六、Consumers


配置文件:consumer.properties

【1】每个 Consumer 属于一个 consumer group,可以指定组id。group.id
【2】消费形式:
   ■ 组内:组内的消费者消费同一份数据;同时只能有一个 consumer消费一个 Topic 中的1个 Partition;一个 consumer 可以消费多个 partitions 中的消息。所以,对于一个 topic,同一个 group 中推荐不能有多于 partitions个数的 consumer 同时消费,否则将意味着某些 consumer 将无法得到消息。
   ■ 组间:每个消费组消费相同的数据,互不影响。
【3】、在一个 Consumer 多个线程的情况下,一个线程相当于一个消费者。例如:Partition 为3,一个 Consumer 起了3个线程消费,另一个后来的 Consumer 就无法消费。

这是 Kafka 用来实现一个 Topic 消息的广播(发给所有的Consumer)和单播(发给某一个Consumer)的手段。一个 Topic 可以对应多个 Consumer Group。如果需要实现广播,只要每个 Consumer 有一个独立的 Group 就可以了。要实现单播只要所有的 Consumer 在同一个 Group 里。用 Consumer Group 还可以将 Consumer 进行自由的分组而不需要多次发送消息到不同的 Topic

七、Topic、Partition、Message


【1】每个 Partition 在存储层面是 append log 文件。新消息都会被直接追加到 log文件的尾部,每条消息在 log文件中的位置称为 offset(偏移量)。
【2】每条 Message 包含了以下三个属性:
   ●  offset 对应类型:long  此消息在一个 Partition 中序号。可以认为 offset 是 Partition 中 Message 的 id;
   ●  MessageSize 对应类型:int32 此消息的字节大小;
   ●  data  是 message 的具体内容;
【3】越多的 Partitions 意味着可以容纳更多的 Consumer,有效提升并发消费的能力。
【4】总之:业务区分增加 Topic、数据量大增加 Partition。

八、Topic 操作


【1】创建 Topic 案例:需要连接 zk 服务

kafka-topics.sh --create --topic hadoop --zookeeper localhost:2181 --partitions 1 --replication-factor 1

【2】创建 Topic过程的问题,replication-factor 个数不能超过 Broker 的个数。

bin/kafka-topics.sh --create --topic sqoop --zookeeper uplooking01:2181 --partitions 3 --replication-factor 3
Error while executing topic command : replication factor: 3 larger than available brokers: 1

【3】在创建 Topic 后,可以在 /home/uplooking/data/kafka 目录查看到分区的目录,有多少个分区就会相应创建多少个目录。
【4】查看 Topic列表

kafka-topics.sh --list --zookeeper localhost:2181

【5】查看某一个具体的 Topic:

[root@localhost bin]# ./kafka-topics.sh --zookeeper localhost:2181 --describe --topic first
Topic:first	PartitionCount:3	ReplicationFactor:1	Configs:
	Topic: first	Partition: 0	Leader: 0	Replicas: 0	Isr: 0
	Topic: first	Partition: 1	Leader: 0	Replicas: 0	Isr: 0
	Topic: first	Partition: 2	Leader: 0	Replicas: 0	Isr: 0

   ■ PartitionCount:Topic 对应的 Partition 的个数;
   ■ ReplicationFactor:Topic 对应的副本因子,说白就是副本个数;
   ■ Partition:Partition 编号,从0开始递增;
   ■ Leader:当前 Partition 起作用的 Breaker.id;
   ■ Replicas:当前副本数据 Leader 的 breaker.id,是一个列表,排在最前面的起作用;
   ■ Isr:当前 kakfa 集群中可用的 breaker.id 列表;
【6】修改 Topic:不能修改 replication-factor,以及只能对 Partition 个数进行增加,不能减少

kafka-topics.sh --alter --topic hive --zookeeper uplooking01:2181 --partitions 3

  Partition 由3变为2的时,抛出的异常:

ERROR kafka.admin.AdminOperationException: The number of partitions for a topic can only be increased

【6】删除 Topic:彻底删除一个 Topic,需要在 server.properties 中配置 delete.topic.enable=true,否则只是标记删除。配置完成之后,需要重启 kafka 服务。

kafka-topics.sh --delete --topic hbase --zookeeper localhost:2181
Topic hbase is marked for deletion.
Note: This will have no impact if delete.topic.enable is not set to true.

九、生产者消费者案例


使用 kafka 提供的标准生产消费脚本

【1】生产数据:生产数据时需要指定:当前数据流向哪个 Broker,以及哪一个 Topic

kafka-console-producer.sh --broker-list uplooking01:9092 --topic hadoop

【2】消费数据:在消费数据的时候,只需要指定 Topic,以及 Topic 的元数据信息即可(在ZK中存放),所以这里需要使用zk

kafka-console-consumer.sh --topic hadoop --zookeeper uplooking01:2181

 说明:该消费语句,只能获取最新的数据,要想历史数据,需要添加选项:--from-beginning

/kafka-console-consumer.sh --topic hadoop --zookeeper uplooking01:2181 --from-beginning

【3】消费者:黑名单(blacklist)和白名单(whitelist)选项:
   ■ blacklist 后面跟需要过滤的 topic 的列表,使用","隔开,意思是除了列表中的 topic之外,都能接收其它 Topic 的数据
   ■ whitelist 后面跟需要过滤的 topic 的列表,使用","隔开,意思是除了列表中的 topic 之外,都不能接收其它 Topic 的数据

kafka-console-consumer.sh --zookeeper uplooking01:2181 --from-beginning --blacklist hadoop,hive
kafka-console-consumer.sh --zookeeper uplooking01:2181 --from-beginning --whitelist hadoop,fl

十、kafka 分布式环境搭建与概念验证


【1】kafka 中没有主从节点的概念,因此只需要将 kafka 安装目录拷贝到其它节点上即可,不过需要注意的是,需要修改 brokerId 为唯一的:但是 zookeeper 集群是要在配置各自之间的服务器地址(具体百度)

scp -r /home/uplooking/app/kafka/ uplooking@uplooking02:/home/uplooking/app
scp -r /home/uplooking/app/kafka/ uplooking@uplooking03:/home/uplooking/app

【2】在三个节点上分别启动 kafka:-daemon 表示以守护线程启动

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

【3】创建一个 Topic:填写 zookeeper 的集群环境(IP 也可以)

kafka-topics.sh --create --topic hadoop --partitions 3 --replication-factor 3 --zookeeper uplooking01:2181,uplooking02:2181,uplooking03:2181

【4】查看该 Topic 的详细信息:

[uplooking@uplooking01 ~]$ kafka-topics.sh --describe hbase --zookeeper uplooking01:2181,uplooking02:2181,uplooking03:2181
Topic:hadoop    PartitionCount:3        ReplicationFactor:3     Configs:
        Topic: hadoop   Partition: 0    Leader: 101     Replicas: 101,102,103   Isr: 101,102,103
        Topic: hadoop   Partition: 1    Leader: 102     Replicas: 102,103,101   Isr: 102,103,101
        Topic: hadoop   Partition: 2    Leader: 103     Replicas: 103,101,102   Isr: 103,101,102

  ●  PartitionCount:topic 对应的 partition 的个数;
  ●  ReplicationFactor:topic 对应的副本因子,说白就是副本个数;
  ●  Partition:partition 编号,从 0 开始递增;
  ●  Leader:当前 partition 起作用的 breaker.id;
  ●  Replicas:当前副本数据坐在的 breaker.id,是一个列表,排在最前面的起作用;
  ●  Isr:当前 kakfa 集群中可用的 breaker.id 列表;

 这意味着,三个分区在三个节点上都有保存数据,可以分别在每个节点上查看相关的分区数据信息:

[uplooking@uplooking01 kafka]$ ll
总用量 24
-rw-rw-r-- 1 uplooking uplooking    0 3月  25 19:33 cleaner-offset-checkpoint
drwxrwxr-x 2 uplooking uplooking 4096 3月  25 19:33 hadoop-0
drwxrwxr-x 2 uplooking uplooking 4096 3月  25 19:33 hadoop-1
drwxrwxr-x 2 uplooking uplooking 4096 3月  25 19:33 hadoop-2
-rw-rw-r-- 1 uplooking uplooking   56 3月  25 19:33 meta.properties
-rw-rw-r-- 1 uplooking uplooking   37 3月  25 19:48 recovery-point-offset-checkpoint
-rw-rw-r-- 1 uplooking uplooking   37 3月  25 19:49 replication-offset-checkpoint

 为了进一步理解相关概念,可以尝试把 uplooking01 上的 kafka 关掉,然后再查看 topic 的详细信息:

[uplooking@uplooking01 ~]$ kafka-topics.sh --describe hadoop --zookeeper uplooking01:2181,uplooking02:2181,uplooking03:2181
Topic:hadoop    PartitionCount:3        ReplicationFactor:3     Configs:
        Topic: hadoop   Partition: 0    Leader: 102     Replicas: 101,102,103   Isr: 102,103
        Topic: hadoop   Partition: 1    Leader: 102     Replicas: 102,103,101   Isr: 102,103
        Topic: hadoop   Partition: 2    Leader: 103     Replicas: 103,101,102   Isr: 103,102

前面提到:业务区分增加 Topic、数据量大增加 Partition。所以 Partition 分区,是为了把数据分散来存放,这好比日志需要每天分割一样,也是避免单个存储位置数据量过多。显然,至于我们的每个消息存放在哪个分区,kafka 本身是有机制去进行计算的:

int hashCode = Math.abs("ttt".hashCode());
int partition = hashCode % 50;

另外,因为设置了3个副本因子,所以3个分区的数据在3个节点上都会有保存,同时为了起到负载均衡的作用,kafka 会为每个分区设置一个 Leader 节点来专门进行该分区数据的相关操作。现在再去看前面 kafka 组件的理论知识,就很容易理解了。


----关注公众号,获取更多内容----

posted @ 2020-11-18 17:40  Java程序员进阶  阅读(11)  评论(0编辑  收藏  举报