在kafka中为什么高吞吐量是他的优点
    1、创建一个topic时,同时可以指定分区数目,分区数越多,其吞吐量也越大,但是需要的资源也越多,同时也会导致更高的不可用性,kafka在接收到生产者发送的消息之后,会根据均衡策略将消息存储到不同的分区中。因为每条消息都被append到该Partition中,属于顺序写磁盘,因此效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)。
    2、我们知道在kafaf中的数据不会一直保存着,一般默认是存储2周时间,2周时间之后会删除数据,当然这些可以通关参数去调整,
    因此Kafka提供两种策略删除旧数据。一是基于时间,二是基于Partition文件大小。例如可以通过配置$KAFKA_HOME/config/server.properties,让Kafka删除一周前的数据,也可在Partition文件超过1GB时删除旧数据,
    log.retention.hours=168
    log.segment.bytes=1073741824
    log.retention.check.interval.ms=300000
    log.cleaner.enable=false
    那既然删除数据和kafka的性能无关,怎么删除数据就磁盘策略以及具体的需求有关。
    offset由Consumer控制,因为offet由Consumer控制,所以Kafka broker是无状态的,它不需要标记哪些消息被哪些消费过,也不需要通过broker去保证同一个Consumer Group只有一个Consumer能消费某一条消息,因此也就不需要锁机制,这也为Kafka的高吞吐率提供了有力保障。
    3、有了Partition后,不同的消息可以并行写入不同broker的不同Partition里,极大的提高了吞吐率。
    4、使用consumer high level api时,同一个topic的一条消息只能被同一个consumer group内的一个consumer消费,但多个consumer group可以同时消费这一个消息。

    生产者传递消息到broker过程
    1、Producer在发布消息到某个Partition时,先通过ZooKeeper找到该Partition的Leader,然后无论该Topic的Replication Factor为多少,Producer只将该消息发送到该Partition的Leader。
    2、Leader会将该消息写入其本地Log。
    3、每个Follower都从Leader pull数据。这种方式上,Follower存储的数据顺序与Leader保持一致。
    4、Follower在收到该消息并写入其Log后,向Leader发送ACK。
    5、一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,
    6、Leader将增加HW并且向Producer发送ACK。
    提示:
    为了提高性能,每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中。
    注意:
    因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中,也就不能完全保证异常发生后该条消息一定能被Consumer消费。Consumer读消息也是从Leader读取,只有被commit过的消息才会暴露给Consumer。 //这里就有可能存在丢数据的可能性 丢数据可能性3

    丢数据可能性1**
    当Producer向broker发送消息时,一旦这条消息被commit,因数replication的存在,它就不会丢。但是如果Producer发送数据给broker后,遇到网络问题而造成通信中断,那Producer就无法判断该条消息是否已经commit。虽然Kafka无法确定网络故障期间发生了什么,但是Producer可以生成一种类似于主键的东西,发生故障时幂等性的重试多次,这样就做到了Exactly once。
    //这一步是Producer生产者到kafka broker过程会出现的消息丢失的可能性和解决方法

    丢数据可能性2
    接下来讨论的是消息从broker到Consumer的delivery guarantee语义。(仅针对Kafka consumer high level API)。Consumer在从broker读取消息后,可以选择commit,该操作会在Zookeeper中保存该Consumer在该Partition中读取的消息的offset。该Consumer下一次再读该Partition时会从下一条开始读取。
    如未commit,下一次读取的开始位置会跟上一次commit之后的开始位置相同。当然可以将Consumer设置为autocommit//自动提交,即Consumer一旦读到数据立即自动commit。如果只讨论这一读取消息的过程,那Kafka是确保了Exactly once。
    但实际使用中应用程序并非在Consumer读取完数据就结束了,而是要进行进一步处理,而数据处理与commit的顺序在很大程度上决定了消息从broker和consumer的delivery guarantee semantic(交付保证语义)。
    //这一步是Consumer消费者到kafka broker过程会出现的消息丢失的可能性和解决方法

    什么是producer的同步模式和异步模式?
    同步模式
     如果Producer使用同步模式则Producer会在尝试重新发送message.send.max.retries(默认值为3)次后抛出Exception,用户可以选择停止发送后续数据也可选择继续选择发送。而前者会造成数据的阻塞,后者会造成本应发往该Broker的数据的丢失。
    异步模式
    如果Producer使用异步模式,则Producer会尝试重新发送message.send.max.retries(默认值为3)次后记录该异常并继续发送后续数据,这会造成数据丢失并且用户只能通过日志发现该问题。同时,Kafka的Producer并未对异步模式提供callback接口。

    如何保证kafka消费topic的时候,数据完全有序的,也就是不同partition之间也是有序的。
    1、我们知道当前paritition内部的顺序,但是我们不能比较来自不同的两个partition的顺序,这是没有意义的。partition中的数据是有序的,不同partition间的数据丢失了数据的顺序。如果topic有多个partition,消费数据时就不能保证数据的顺序。在需要严格保证消息的消费顺序的场景下,需要将partition数目设为1。
    2、对于每一个写入kafka中的数据,他们会随机的写入到当前topic中的某一个partition内,有一个例外,你提供一个key给当前的数据,这个时候,你就可以用当前的key去控制当前数据应该传入到哪个partition中。
    kafka默认是消费者可以分组(Consumer Group),比如有两个消费者组A 和B,共同消费一个topic:order_info,A 和B所消费的消息不会重复
    比如order_info 中有100 个消息,每个消息有一个id,编号从0-99,那么,如果A组消费0-49 号,B 组就消费50-99 号
    //生产环境中也可以让多个consumer共同消费同一个topic中的数据?需要设置调整
    实现方法一:代码段可以实现
    使用Consumer high level API时,同一Topic的一条消息只能被同一个Consumer Group内的一个Consumer消费,但多个Consumer Group可同时消费这一消息。
    实现方法二:我们可以这样,把A B两个消费者分为2个不同的组,不同的消费组可以消费同一个topic的数据。