分布式实时消息队列Kafka(未完)

一.消息队列及kafka的介绍

1.消息队列MQ的介绍

  • 定义

    • 官方定义:消息队列是一种异步的服务间通信方式,是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题,实现高性能、高可用、可伸缩和最终一致性架构。
    • 理解:消息队列MQ用于两个系统之间或者两个模块之间传递消息数据时,实现数据缓存
  • 功能

    • 基于队列的方式,实现消息传递的数据缓存
    • 保证消息传递有序性: == 队列先进先出== ,消息队列实现了先产生的先消费
  • 应用场景

    • 用于所有需要实现实时、高性能、高吞吐、高可靠的消息传递架构中
    • 大数据应用中: 作为唯一的实时数据存储平台
  • 优点

    • 实现了架构解耦: 将架构中的高耦合转换为低耦合,更加灵活
    • ** 实现异步,提高传输性能 ** : 生产一次,所有的消费都有可以并行
    • 限流削锋:不用再考虑不同时间资源分配不均衡的问题
  • 缺点

    • 增加了消息队列,架构运维更加复杂:一旦消息队列故障,整个系统全部崩溃
      • 消息队列架构的稳定性 :保证数据存储的安全性
      • 在任何情况下,都尽量保证数据可以正常提供读写
      • 解决:分布式架构存储
    • 数据保证更加复杂,必须保证生产安全和消费安全: == 每一步都必须不丢失和不重复==
      • 生产时候 :必须保证生产过程写入MQ数据不丢失不重复
      • 消费时候:必须保证消费过程读取MQ数据不丢失不重复
      • 保证数据传输过程中的安全性

2.消息队列的订阅发布模式

  • 实施分布式实时消息队列Kafka(未完)_第1张图片
  • 角色
    • 生产者
      • 功能:产生数据的程序,用于将产生的数据写入MQ
    • 消息队列
      • 功能:介于生产和消费之间,临时缓存中间的数据
    • 消费者
      • 功能:读取并处理数据的程序,用于从MQ读取数据进行处理
    • 主题
      • 功能:用于区分不同的数据来源
  • 流程
    • step1 :生产者往消息队列中产生数据,将数据写入对应的主题中
    • step2: 消费者可以订阅主题,如果主题中出现新的数据,消费就可以立即消费
    • 特点一个消费者可以订阅多个主题,一个主题可以被多个消费者订阅
    • 消费成功以后,不会立即主动删除数据
      • 可以实现数据共享
    • 理解:订阅发布模式高度类似于微信公众号的概念

3.kafka的功能及应用

  • 实施

    • 官网:kafka.apache.org

    • 公司:领英LinkedIn公司基于Scala语言开发的工具

      • 功能
    • 功能一:分布式流式数据实时存储分布式消息队列系统

    • 功能二:分布式流式计算:分布式计算:KafkaStream

  • 定义分布式的基于订阅发布模式的高吞吐高性能的实时消息队列系统

    • 消息队列

      • 本质 MQ的功能kafka可以实现
    • 基于发布和订阅

      • 模型 有生产者 消费者 主题 队列
    • 分布式

      • 不是单机软件 分布式软件 面对的是大数据场景
    • 实时

      • 生产消费时候的读写速度快 适合大数据实时处理场景
    • 最终一句话:kafka是一款基于发布和订阅模型的分布式实时消息队列软件

  • 应用场景:大数据实时计算的架构中,实现实时数据缓存的场景

    • 目前只要做实时大数据,都会用到kafka或者pulsar

    • kafka:作为大数据架构中实时消息队列,用于存储从外部同步到的所有实时数据,供实时计算引擎进行消费数据处理

    • 实时采集:Flume(实时采集日志)、Canal(实时采集数据库)

      • 在消息队列系统中就是生产者角色,把数据实时写入到kafka中
    • 实时MQ:kafka

      • 消息队列 实时读写
    • 实时计算:Flink、spark structstreaming

      • 在消息队列系统中就是消费者的角色,需要从kafak中订阅主题,从主题队列中拉取数据进行消费处理
  • 特点

    • 高性能:读写速度快,基于内存
    • 高并发: 每秒并发量,分布式
    • 高吞吐: 每秒数据量大,基于磁盘
    • 高安全性: 架构层面基于分布式(避免单点故障问题),存储层面基于副本机制(保证了数据安全性)
    • 高灵活性: 随意添加生产者或者消费者

二、kafka中的核心概念

1.kafka概念:生产和消费

  • Broker:kafka是一个分布式集群,多台机器构成,每台kafka的节点就是一个Broker
  • Broker:就是kafka节点,负责存储kafka中的数据,提供读写
  • 进程:kafka
  • 架构:公平分布式主从架构,类似于zk设计,从节点可以选举称为主节点
  • 主:Broker【Controller】:kafka的主节点,负责管理kafka的节点、Topic、元数据、负责存储数据、对外提供读写
  • 从:Broker:负责存储数据,对外提供读写
  • Producer:生产者
    • 功能:负责往kafka写数据的客户端
    • 本质: 写数据的客户端
  • Consumer:消费者
    • 功能:负责从kafka中读数据
    • 本质: 读数据的客户端
  • Consumer Group: 消费者组,kafka的订阅发布模式中必须以消费者组的形式从kafka中消费数据
    • 理解:就是消费者不能单独获取kafka中的数据,哪怕只有一个消费者,也必须构建一个消费者组,以组的形式进行消费
    • 任何一个消费者必须属于某一个消费者组
    • 一个消费者组中可以有多个消费者:多个消费者共同并行消费数据,提高消费性能
    • 消费者组中多个消费者消费的数据是不一样的
    • 整个消费者中所有消费者消费的数据加在一起是一份完整的数据

2.kafka概念:Topic、Partition

  • Topic:数据主题,用于分区不同的数据,对数据进行分类
    • Topic是kafka中分布式的数据存储对象,类似数据库中表的概念,但是Topic是分布式的
    • kafka是分布式存储,所以kafka中的Topic也是分布式的概念,写入Topic的数据会分布式的存储在kafka中
  • Partition:数据分区,用于实现topic的分布式存储,对topic的数据进行划分
    • 每个topic都可以对应多个区,每个分区存储在不同的kafka节点Broker上
    • 写入topic:根据一定的规则决定写入哪个具体分区

类比Hdfs

概念 HDFS Kafka
节点 NameNode+DataMode:普通分布式注册架构 Broke:公平分布式
对象 文件 Topic
划分 Block块 Partition分区
规则 按照大小:BlockSize=128M 自己决定
安全 副本机制:默认三份 副本机制”:自己决定

3.kafka概念:分区副本机制

  • 1:Kafka中的每个Topic的每个分区存储在不同的节点上,如果某个节点故障,怎么保证集群正常可用?
    • Kafka选用了副本机制来保证数据的安全性
    • Kafka每一个分区都可以有多个副本,类似于HDFS的副本机制,一个块构建多个副本
    • 如果某台机器故障,其他机器还有这个分区的副本,其他机器的副本照样可以对外提供客户端读写
    • 注意:Kafka中一个分区的副本个数最多只能等于机器的个数,相同分区的副本不允许放在同一台机器,没有意义
  • 2:一个分区有多个副本,读写这个分区的数据时候,到底读写哪个分区副本呢?
    • Kafka将一个分区的多个副本,划分为两种角色
    • Leader副本:负责对外提供读写,生产者和消费者只对leader副本进行读写
    • Follower副本:与Leader同步数据,如果leader故障,从follower选举新的leader副本对外提供读写
    • 设计:方式类似于ZK中节点的设计,但是这里不是做节点的选举而是分区副本的选举
    • 实现:由Kafka的**主节点【controller】**根据机器的健康状态、数据的完整性来选择Leader和Follower副本

4.kafka概念:Segment、offset

  • Segment 的本质:对每个分区的数据进行更细的划分,用于存储kafka中的数据文件并记录索引

  • 规则: 先写入的数据会先生成一对Segment文件,存储到一定条件以后,后面数据写入另外一对Segment文件,每个文件就叫Segment文件对

  • 实现: 每个Segment对应三个文件

    • .log文件:存储数据
    • .index/.timeindex 文件:对应log文件的索引
  • 设计:为了加快数据检索的效率

    • 将数据按照规则写入不同的文件,以后可以根据规则快速的定位数据所在的文件
    • 读取对应的小的Semgent文件,不用读取所有数据文件
    • 为什么要这样设计:如果不设计Segment,整个分区的所有数据都存储在一个文件中,当文件越来越大,存储的数据越来越多,影响读的性能,会再构建一个新的Segment,老的Segment不在被写入
  • Offset

    • 定义:Offset是每条数据在自己分区中的偏移量
      • 写入分区的顺序就是offset的偏移量,offset是分区级别的,每个分区的offset独立管理,都是从0开始
      • 消息队列先进先出
      • 先写入的offset就越小
      • 第N条数据的offset就是N-1
    • 生成:生产者往kafka中写入数据,写入某个分区
      • 每个分区单端管理一套offset。offset从0开始给每条数据进行编号
      • kafka写入数据也是按照KV来写入数据
#Kafka中一条数据存储的结构
offset		Key				Value
  • 功能基于offset来指定数据的顺序,消费时候按照offset顺序来读取

    • 消费者消费Topic分区中的数据是按照offset进行分区级别顺序消费

    • 怎么保证消费不丢失不重复只要保证消费者每次按照offset的顺序消费即可

      • 如果没有Offset

      • 从头取一遍:数据重复

      • 从最新的读:数据丢失

    • kafka中所有消费者数据的读取都是按照offset来读取

5.总结kafka中的概念

Kafka 解释
Producer Kafka生产者,负责往Kakfa写数据的客户端
Consumer Kafka消费者,负责从Kafka读取数据的客户端
ConsumerGroup 消费者组,必须以消费组的形式才能消费,一个消费者组中可以包含多个消费者,任何一个消费者都必须属于某个消费者组
Broker Kafka节点,每个节点叫做一个Broker
Topic 主题,用于区分不同的数据,实现数据分类,分布式逻辑的概念,一个Topic可以对应多个分区
Partition 分区,用于实现Kafka中Topic的分布式存储,每个分区可以分布在不同节点上,每个分区可以有多份
Replication 副本,用于保证Kafka中分区的数据安全,每个分区中副本个数小于等于节点个数,两种角色:Leader,Follower
Segment 分区文件段,用于将分区中的数据按照一定的规则进行细分,加快查询性能,由两种文件组成,.log数据文件和.index索引文件
KV Kafka中写入数据也是KV结构
Offset 每条数据在分区中的偏移量,第N条件数据的offset = N-1,用于保证消费者按照offset顺序消费,一致性

分布式实时消息队列Kafka(未完)_第2张图片

三.kafka集群架构及部署

1.kafka集群架构和角色功能

    • Kafka中的每个角色以及对应的功能
    • 分布式主从架构【公平:允许从节点选举成为主节点
    • 主:Kafka Broker
      • 是一种特殊的Broker,从所有Broker中选举出来的,负责普通Broker的工作
      • 负责管理所有从节点:Topic、分区和副本【负责决定一个分区的leader副本和follower副本
      • 每次启动集群,会从所有Broker中选举一个Controller由ZK实现
    • 从:Kafka Broker
      • 对外提供读写请求
      • 其他的Broker监听Controller在ZK中创建的临时节点,如果Controller故障,会重新从Broker选举一个新的Controller
  • ZK的功能
    • 辅助选举Controller:启动时所有Broker都会到ZK中创建临时节点,谁创建成功谁就是主节点
    • 存储Kafka元数据
  • Kafka 3.0版本新特性:可以摆脱ZK,独立运行了

2.kafka分布式集群部署

  • 下载解压安装
    • 下载:http://archive.apache.org/dist/kafka/
    • 上传到第一台机器
    cd /export/software
    rz
    
    *解压
#解压安装
tar -zxvf kafka_2.12-2.4.1.tgz -C /export/server/
cd /export/server/kafka_2.12-2.4.1/
#Kafka数据存储的位置
mkdir datas
  • 修改配置
    • 切换到配置文件目录
    cd /export/server/kafka_2.12-2.4.1/config
    
    • 修改server.properties:
#21行:唯一的 服务端id
broker.id=1
#60行:指定kafka的日志及数据【segment【.log,.index】】存储的位置
log.dirs=/export/server/kafka_2.12-2.4.1/datas
#123行:指定zookeeper的地址
zookeeper.connect=node1:2181,node2:2181,node3:2181
#在最后添加两个配置,允许删除topic,当前kafkaServer的主机名
delete.topic.enable=true
host.name=node1
  • 分发
cd /export/server/
scp -r kafka_2.12-2.4.1 node2:$PWD
scp -r kafka_2.12-2.4.1 node3:$PWD
  • 第二台:vim /export/server/kafka_2.12-2.4.1/config/server.properties
#21行:唯一的 服务端id
broker.id=2
#最后
host.name=node2
  • 第三台同第二台修改,将2改为3即可
  • 添加环境变量
vim /etc/profile
#KAFKA_HOME
export KAFKA_HOME=/export/server/kafka_2.12-2.4.1
export PATH=:$PATH:$KAFKA_HOME/bin
source /etc/profile

3、kafka的启动和关闭

  • 启动zk
start-zk-all.sh

启动kafka :只能启动当前节点

cd /export/server/kafka_2.12-2.4.1/
bin/kafka-server-start.sh config/server.properties >>/dev/null 2>&1 &

关闭kafka

bin/kafka-server-stop.sh 
  • 封装kafka脚本
    • 启动脚本
vim /export/server/kafka_2.12-2.4.1/bin/start-kafka.sh
#!/bin/bash
KAFKA_HOME=/export/server/kafka_2.12-2.4.1

for number in {1..3}
do
        host=node${number}
        echo ${host}
        /usr/bin/ssh ${host} "cd ${KAFKA_HOME};source /etc/profile;export JMX_PORT=9988;${KAFKA_HOME}/bin/kafka-server-start.sh ${KAFKA_HOME}/config/server.properties >>/dev/null 2>&1 &"
        echo "${host} started"
done
chmod u+x /export/server/kafka_2.12-2.4.1/bin/start-kafka.sh
  • 关闭脚本
vim /export/server/kafka_2.12-2.4.1/bin/stop-kafka.sh
#!/bin/bash
KAFKA_HOME=/export/server/kafka_2.12-2.4.1

for number in {1..3}
do
  host=node${number}
  echo ${host}
  /usr/bin/ssh ${host} "cd ${KAFKA_HOME};source /etc/profile;${KAFKA_HOME}/bin/kafka-server-stop.sh"
  echo "${host} stoped"
done
chmod u+x /export/server/kafka_2.12-2.4.1/bin/stop-kafka.sh

关闭之后,可能需要多等待一会,才看不到进程

4、Topic管理:创建、列举、查看、删除

  • Topic管理脚本 kafka-topics.sh,可以查看用法
  • 创建Topic
kafka-topics.sh --create --topic bigdata01 --partitions 3 --replication-factor 2 --bootstrap-server node1:9092,node2:9092,node3:9092


#如果之前安装的时候没有配置kafka的环境变量 那怎么执行?
#先cd到kafka的安装包目录下  通过相关路径去执行 也可以绝对路径执行


#探究  如果创建主题的时候 分区及副本数都不指定 报错?还是有默认值?
kafka-topics.sh --create --topic test1 --bootstrap-server node1:9092,node2:9092,node3:9092

kafka-topics.sh --describe --topic test1  --bootstrap-server node1:9092,node2:9092,node3:9092

[root@node1 ~]# kafka-topics.sh --describe --topic test1  --bootstrap-server node1:9092,node2:9092,node3:9092
Topic: test1    PartitionCount: 1       ReplicationFactor: 1   
Topic: test1    Partition: 0    Leader: 2       Replicas: 2     Isr: 2

#结论:如果没有指定分区数及副本数 默认主题的只有一个分区 一个副本 

#探究:副本数大于集群节点个数会如何?
kafka-topics.sh --create --topic test2 --replication-factor 5 --bootstrap-server node1:9092,node2:9092,node3:9092

#报错
Replication factor: 5 larger than available brokers: 3

#探究:分区个数大于集群节点个数会如何?
  • –create:创建
  • –list:列举
  • –topic:topic名称
  • –partitions:指定topic的分区数
  • –replication-factors:指定分区副本个数
  • –bootstrap-server:指定服务端地址
  • 列举Topic
kafka-topics.sh --list -bootstrap-server node1:9092,node2:9092,node3:9092
  • 查看topic
kafka-topics.sh --describe --topic bigdata01  --bootstrap-server node1:9092,node2:9092,node3:9092
  • 结果
# Topic名称              分区个数					副本个数
Topic: bigdata01        PartitionCount: 3       ReplicationFactor: 2 
# 分区:Topic名称  +      分区编号			
Topic: bigdata01        Partition: 0    Leader: 3       Replicas: 3,1   Isr: 3,1
Topic: bigdata01        Partition: 1    Leader: 1       Replicas: 1,2   Isr: 1,2
Topic: bigdata01        Partition: 2    Leader: 2       Replicas: 2,3   Isr: 2,3

  • Topic:Topic名称

  • Partition:分区的编号,从0开始

  • Replicas:当前这个分区所有的副本所在的Broker的id

  • Isr:当前这个分区所有可用的副本所在的Broker的id

  • Leader:当前这个分区的Leader副本所在的Broker的id

  • 删除Topic
创建
kafka-topics.sh --create --topic bigdata02 --partitions 2  --replication-factor 3 --bootstrap-server node1:9092,node2:9092,node3:9092 
删除
kafka-topics.sh --delete --topic bigdata02  --bootstrap-server node1:9092,node2:9092,node3:9092

5、kafka 生产者Python API开发

  • 安装kafka-python
pip install kafka-python -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 生产者API
# coding:utf8
from kafka import KafkaProducer

"""
    TODO1:构建Kafka生产者客户端对象,并且指定生产者的配置
        bootstrap_servers:指定的是服务端的地址
        acks:应答机制,用于决定生产者写入数据到Kafka是同步还是异步
            0:生产者生产一条数据写入Kafka,不用等待Kafka的回复,直接生产下一条【快,数据容易丢失】
            1:生产者生产一条数据写入Kafka,等待Kafka确保这个分区的Leader已经写入,就返回一个ack,生产者收到ack就发送下一条【性能和安全做了权衡】
            all/-1:生产者生产一条数据写入Kafka,等待Kafka确保这个分区的所有ISR副本都已经写入成功,再返回ack,生产者收到ack就发送下一条【安全,性能最差】
        retries:重试机制,如果生产者长时间没有收到ack,就认为数据丢失,会重新发送一份数据写入,直到收到ack
        ||
        应答机制+重试机制保证生产者生产数据不丢失
"""
producer = KafkaProducer(bootstrap_servers=['node1:9092', 'node2:9092', 'node3:9092'], acks=1)

"""
    TODO2:实现通过生产者对象调用生产方法将数据生产写入Kafka中
        方法:send:用于将数据写入Kafka
        参数:
            topic:指定要写入的Topic
            key:指定写入的Key,决定了写入数据的分区规则
            value:指定写入的Value,也就是真正需要传递的数据
"""
# 每次从0 - 9 中取一个值
for i in range(0, 10):
    # 调用方法写入数据:topic、key、value
    rs = producer.send(topic="bigdata01", key=f"{i}".encode("UTF-8"), value=f"itcast{i}".encode("UTF-8"))
    # 调用方法写入数据:topic、value
    # rs = producer.send(topic="bigdata01", value=f"itcast{i}".encode("UTF-8"))
    # 调用方法写入数据:topic、key、value、partition
    # rs = producer.send(topic="bigdata01", key=f"{i}".encode("UTF-8"), value=f"itcast{i}".encode("UTF-8"), partition=0)
    # 获取返回结果
    metadata = rs.get(timeout=10)
    # 打印生产结果
    print(f"数据:itcast{i}  topic:{metadata.topic}  partition:{metadata.partition}  offset:{metadata.offset}")

"""
    TODO3:生产者不是直接将数据写入Kafka,而是先放到本地一个缓存中,当缓存达到一定大小或者超过一定的时间才会真正的写入Kafka
        flush:强制将本地缓存的数据提交到Kafka
"""
producer.flush()
  • 启动消费者
kafka-console-consumer.sh --topic bigdata01 --bootstrap-server node1:9092,node2:9092,node3:9092
  • 测试运行

6、kafka 消费者Python API开发

  • 安装kafka-python
pip install kafka-python -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 消费者API
# coding:utf8
from kafka import KafkaConsumer

"""
    TODO:1-构建一个消费者对象,指定一些配置信息
        topics:需要消费的Topic
        group_id:指定当前消费者属于哪个消费者组,消费组的id
        bootstrap_servers:指定服务端地址
        auto_offset_reset:用于指定第一次消费从什么位置消费, earliest-最早位置,latest-最近位置
        enable_auto_commit:自动提交,开启后每个消费者会自动将自己负责的分区的commitoffset提交到__consumer_offsets这个topic中
            还有一个参数是提交时间间隔:自动提交是按照时间间隔自动提交,1000ms = 1s
"""
consumer = KafkaConsumer(
    "bigdata01",
    group_id="cg1",
    bootstrap_servers=['node1:9092', 'node2:9092', 'node3:9092'],
    auto_offset_reset='earliest',
    enable_auto_commit=True
)

"""
    TODO:2-实现消费,这是一个死循环,表示源源不断的去消费,如果没有数据数据就等待,有数据就立即消费,不停的
        message:表示消费到的每一条数据
        topic:当前数据所属的Topic
        partition:当前数据属于这个Topic哪个分区
        offset:当前数据属于这个分区的哪个offset
        key:获取数据中的key
        value:获取数据中的value
"""
# 不断消费Kafka中的每条数据
for message in consumer:
    # 从每条数据中获取所有信息
    topic = message.topic
    partition = message.partition
    offset = message.offset
    key = message.key
    value = message.value.decode("UTF-8")
    # 打印每条数据的内容
    print(f"Topic={topic}  Partition={partition} Offset={offset} Key={key} Value={value}")
  • 测试运行

四.Kafka消费者消费过程

1. 消费者消息数据的过程

  • kafka消费者消费数据的规则
    • 消费者消费Kafka中的Topic根据每个分区的offset进行消费,每次从上一次的位置继续消费
    • 第一次消费规则[消费者id在kafka元数据中不存在] :由属性决定
auto.offset.reset = latest | earliest
latest:默认的值,从Topic每个分区的最新的位置开始消费
earliest:从最早的位置开始消费,每个分区的offset为0开始消费
    • **第二次消费开始【消费者组已经在kafka中存在】:**根据==上一次消费的每个分区offset位置+1继续进行消费
      • consumer offset : 消费者已经消费到这个分区的offset
      • commit offset:消费者下一个要消费的offset
      • 关系: consumer offset +1 = commit offset

面试题:

  • 消费者如何找到下一次要请求的位置是什么?
    • 每个消费者维护自己下一次要消费的commit offset,放在自己的内存
    • 但是消费者是客户端,如果客户端故障,就会出现问题
  • 如果因为一些原因,消费者故障了,重启消费者,原来内存中commit offset 就没有了,就会出现以下场景
    • 场景1:如果消费者重启了,这个消费者怎么知道下一次消费分区的位置
    • 场景2:如果这个消费者长时间没有重启,这个分区会交给这个消费者组的其他消费者消费,其他消费者怎么知道这个分区下一次消费的位置?
    • 解决:
      • 首先,造成这些的原因是:每次分区下一次消费的offset放在消费者客户端的内存中,这样就导致了消费者一旦故障,内存数据会丢失,offset就丢失了
      • 将offset持久化存储,不仅仅存放在内存中,如果内存丢失,其他地方也能读到
  • kafka offset 偏移量管理
    • kafka让所有消费者每个分区下次消费的位置主动记录在一个topic中:_consumer_offsets
      • 每个负责消费这个分区的消费者会主动将自己消费的commit offset写入到这个topic中
      • consumer offset : 消费者已经消费到的位置
      • commit offset : 下一次要消费的位置
    • 如果下次消费者重启以后注册或者将这个分区分给别的活着的消费者,kafka就根据自己记录的offset来提供消费的位置
    • 提交的规则:根据时间自动提交
#是否自动提交offset:true表示每个消费者将自己负责的分区下一次要消费的位置自动的写入     __consumer_offsets中
 enable_auto_commit=True

自动提交

  • 自动提交的规则
    • 根据时间周期来提交下一次要消费的offset,记录在_consumer_offsets 中
    • 每1s提交一次
  • 数据丢失情况
    • 如果刚消费,还没处理,就达到提交周期,记录了当前的offset
    • 最后处理失败,需要重启,重新消费处理
    • kafka中已经记录消费过了,从上次消费的后面进行消费
  • 数据重复的情况
    • 如果消费并处理成功,但是没有提交offset,程序故障
    • 重启之后,kafka记录的还是之前的offset,重新由消费一遍
    • 数据重复问题
  • 原因
    * 自动提交:按照时间来进行提交,提交目的为了保证安全性
    * 实际需求:按照消费并处理的结果
    * 如果消费并处理成功,提交offset,下一次接着处理成功的数据之后来进行消费
    * 如果消费失败或处理失败,不提交offset,下一次重新消费和处理这部分数据

手动提交Commit offset

关闭自动提交:

# 构建消费者对象
consumer = KafkaConsumer(
    "bigdata01", # topic,必须写
    group_id="cg1", # 消费者组id,必须写
    bootstrap_servers=['node1:9092', 'node2:9092', 'node3:9092'],
    auto_offset_reset='earliest',    # 启动的时候 从`可用`的最早数据开始读取,如果不设置这个参数,上来就等新数据,已有的完全不管
    enable_auto_commit=False    # 如果是True,你消费后,默认1分钟会在Kafka中记录你上一次消费到哪了
)

手动提交

    # 手动提交Commit Offset
    consumer.commit()

你可能感兴趣的:(大数据,kafka,分布式,java)