kafka深入理解

可紊 提交于 2020-03-10 15:30:37

kafka深入

1 分片与副本机制

分片机制:主要解决了单台服务器存储容量有限的问题

当数据量非常大的时候,一个服务器存放不了,就将数据分成两个或者多个部分,存放在多台服务器上。每个服务器上的数据,叫做一个分片

副本:副本备份机制解决了数据存储的高可用问题

当数据只保存一份的时候,有丢失的风险。为了更好的容错和容灾,将数据拷贝几份,保存到不同的机器上。

 kafka中对于分片的数量可以是任意的,建议不要超过节点数,但对于副本的数量,最多等于节点数

2 kafka保证数据不丢失机制

2.1 producer到kafka过程

解决方案:当producer发送数据到kafka后,kafka应该给予一个响应信息,    ACK校验机制

ack校验机制的三种状态码:

a) 0:生产者只负责发送数据,不关心kafka是否接受的到

b) 1:某个partition的leader收到数据给出响应

c) -1:某个partition的所有副本都收到数据后给出响应

在生产环境下设置状态码的时候, 根据数据的效率和重要性判断设置标准

数据在发送的过程中主要有二种模式: 同步模式  和 异步模式
    同步模式:
          发送一条数据, 等待响应, 响应成功后, 发送下一条数据即可
          在同步模式下, 如果broker一直不给于响应, 设置超时(10s), 超时后, 进行重试(3)即可,最终会报错
    异步模式:
          引入缓冲池, 实现批量发送数据, 当达到一定数据的阈值或者时间阈值后, 进行批量发送数据即可
          内部和同步一样, 都会有超时和重试策略, 不同点在于生产者不断的发送数据, 将数据写入到缓冲池中
          如果缓冲池满了, 可以选择直接将其清空, 或者将其保存第三方的容器中

    a) 先将数据保存在生产者端的buffer中。Buffer大小是2万条。 32M

    b) 满足数据阈值或者时间阈值其中的一个条件就可以发送数据。

    c) 发送一批数据的大小是500条。16Kb


模拟异步发送数据:
    直接调send方法, 其实就是一个异步发送方式:
        // 异步的方式方式
        kafkaProducer.send(producerRecord);
        或者:
        kafkaProducer.send(producerRecord, new Callback() {
            // onCompletion什么会调用呢?  
            //      当一批数据发送成功后, 回调这个函数, Exception ==null
            //      当一批数据经过重试后, 依然失败, 也会回调这个函数, 此时 Exception不为null
            @Override
            public void onCompletion(RecordMetadata metadata, Exception exception) {
            
                // 如果 Exception 不为null, 表示数据经过重试后, 发送失败了
                // 在这个代码块中编写失败后的业务代码即可
                
            }
        });

    设置缓存池: 
         props.put("buffer.memory", 33554432);
    设置批量数据;
         props.put("batch.size", 16384); 
    设置时间阈值:
         props.put("linger.ms", 1); 
 

2.2 borker端保证数据不丢失

多副本机制+ ack=-1

2.3 consumer端保证数据不丢失

给予offset(数据消费的偏移量)

通过offset commit 来保证数据的不丢失,kafka自己记录了每次消费的offset数值,下次继续消费的时候,会接着上次的offset进行消费。

每一个消费者都会有一个groupid,将多个消费者放置到同一个groupid中

如果是第一次访问,我们默认从当前时间进行消费

开始监控数据,一旦有数据过来,直接获取

在broker端 会记录这着每一个消费者组消费的偏移量的信息, 
        当消费者消费完数据后, 需要通知给broker, broker更新偏移量的数据
        当消费者出现宕机后, 从broker中获取上次的消费偏移量, 从这个偏移量开始消费即可

偏移量记录记录在topic中的consumer_offset,默认有50个分区,1个副本

重复消费问题:

当consumer消费完成后,并没有即使响应给broker偏移量数据(宕机)

3 消息存储机制

假设一个partition有10T数据

kafka中是多文件存储

kafka作为消息中间件,只负责消息的临时存储,并不是永久存储,需要删除过期数据

数据存储在一个文件中,需要删除数据变得非常麻烦,并且读写的效率比较慢,因为每次都需要打开一个大文件

切分为多个文件后,根据文件的日期属性删除即可

默认保留7天(168小时)

kafka数据多文件存储以segment段的形式,当segment段中的log文件达到1G,就会生产新的segment段

segment段的组成:

    log文件:数据存储文件

    index文件:索引文件,当前这个log文件的索引信息,提升查询效率.(存储log文件中消息对应的偏移量所在文件中的物理位置)

    文件名:表示消息在文件中的其实偏移量

 4 消息查询机制

如何查询633254这条数据:?

    1) 确定这条数据在哪个segment段(根据文件名确定)

    2) 根据偏移量信息,到index文件中查询这个偏移量对应的log文件中数据的物理偏移量

    3) 根据物理偏移量到log文件中查询数据

5 生产者数据分发策略 

当producer生产数据的时候,消息应该发送给哪个分片?

kafka在数据生产的时候,有一个数据分发策略。默认的情况使用DefaultPartitioner.class类。

1) 轮询策略

    当发送数据的时候,如果只发送value数据,默认采用轮询策略

2) hash取模计算

    当发送数据的时候,必须传递key数据,即可使用hash取模   key.hashCoe()%分区数量

3)指定分区号

    当发送数据,在producerRecord中指定分区号(分区好从零开始)

4)自定义分发策略

    自定义一个类,继承partitioner,实现其中的方法即可,然后将自定义类配置到生产者中

 props.put("partition.class","com.itheima.kafka.MyPartitioner");

前三中都是使用一个类:

    ProducerRecord类实现分发

    PartitionerClass获取分区

 

6 消费者负载均衡机制

生产者每分钟生产120条数据,消费者每分钟消费40条数据,在kafka中造成大量数据堆叠无法消费

解决办法:多搞几个消费者,让消费者同属于一个消费者组(3个)

注意:规定一个topic中的一个分区的数据,只能被一个消费者组消费

当生产者每分钟发送160条数据!!!

消费者组中消费者的数量和partition数量最多保持一致,多出来的消费者将会一直处于空闲状态

解决方案: 增加分区的数量,增加消费速度

基于这个消费者概念, 其实通过kafka模拟一个点对点和发布订阅的方式:
    
    点对点  :  一个生产者将数据生产到kafka中,  让多个消费者处于同一个消费者组中即可 
    发布订阅:  一个生产者将数据生产到kafka中,  让多个消费者都处于不同的组当中
 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!