kafka进阶

kafka进阶

      • 初识kafka
      • 生产者
      • 消费者
      • 主题与分区
      • ~~~
      • springboot+kafka
      • 集群
      • 监控
      • 面试题

初识kafka

  • 消息队列
  • 分布式发布-订阅消息系统
  • 日志处理

基础架构

  • Producer:消息生产者,向Kafka中发布消息的角色。
  • Consumer:消息消费者,即从Kafka中拉取消息消费的客户端。
  • Consumer Group:消费者组,消费者组则是一组中存在多个消费者,消费者消费Broker中当前Topic的不同分区中的消息,消费者组之间互不影响,所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。某一个分区中的消息只能够一个消费者组中的一个消费者所消费
    Broker:经纪人,一台Kafka服务器就是一个Broker,一个集群由多个Broker组成,一个Broker可以容纳多个Topic。
  • Topic:主题,可以理解为一个队列,生产者和消费者都是面向一个Topic
  • Partition:分区,为了实现扩展性,一个非常大的Topic可以分布到多个Broker上,一个Topic可以分为多个Partition,每个Partition是一个有序的队列(分区有序,不能保证全局有序)
    Replica:副本Replication,为保证集群中某个节点发生故障,节点上的Partition数据不丢失,Kafka可以正常的工作,Kafka提供了副本机制,一个Topic的每个分区有若干个副本,一个Leader和多个Follower
  • Leader:每个分区多个副本的主角色,生产者发送数据的对象,以及消费者消费数据的对象都是Leader。
  • Follower:每个分区多个副本的从角色,实时的从Leader中同步数据,保持和Leader数据的同步,Leader发生故障的时候,某个Follower会成为新的Leader。

特性

  • 缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理。

  • 解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。

  • 冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅topic的服务消费到,供多个毫无关联的业务使用。

  • 健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正常进行。

  • 异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

环境配置jdk、zookeeper

  • jdk配置
  • zookeeper配置

环境配置kafka

  • 准备

程序实战与优化

  • 实战

生产者

消费者

主题与分区

~~~

springboot+kafka

集群

监控

面试题

了解kafka么?能说一说kafka么?

  • 避轻就重

为什么要使用kafka?

  • 优点/特性
  • 成熟的消息队列
  • 能够彻底满足海量数据场景下高吞吐、高并发需求
  • 每秒大约可以生产25万消息(50MB)
  • 每秒处理55万消息(110MB)
  • 低延迟
  • 容错------具备一个固有功能,可以自行应对集群中的节点故障
  • 持久性
  • 可伸缩性

基础架构都有哪些,分别是干什么的?
*
*
你认为kafka存在哪些问题?有什么好的解决办法么?

  • 由于是批量发送,数据并非真正的实时;
  • 对于mqtt协议不支持;
  • 不支持物联网传感数据直接接入;
  • 仅支持统一分区内消息有序,无法实现全局消息有序;
  • 监控不完善,需要安装插件;
  • 依赖zookeeper进行元数据管理;
  • 扩展性差,剥离broker意味着必须复制topic分区和副本,效率很低。
  • 缺乏一致性,一旦API发生变化很有可能出现问题。
  • 存储成本非常高,几乎没有人用kafka长时间储存数据。
  • 没有与租户完全隔离的本地多租户,需要自行配置解决方案。
  • (我只在自己电脑玩过,并没有过实际的运维和实践,所以没感觉到存储量的压力)
  • 解决办法不知道,我觉得如果有解决办法,这些就不能算问题了
  • 现在好多大公司已经不用kafka了,改用了pulsar
  • pulsar系统可以同时拥有rabbitMQ、rocketMQ、kafka的特性…
  • (替代品就算是解决办法了吧,还有针对公司业务考虑可行性问题)

kafka和redis区别;和RabbitMQ区别?

  • 我觉得kafka和redis没有关系,也就没有可比性…
  • rabbitMQ大多用于重要的消息传递,保证数据的稳定、可靠
  • kafka处理大数据的,两者趋向的业务需求不一样

kafka丢消息的问题

  • 丢消息会发生在生产Producer、消费Consumer和代理(经纪人)Broker
  • producer丢消息,发生在client,为了提升效率,减少流,消息会打包发送到缓存管道,当client出现问题,就会导致数据的流失,客户端的硬件问题也可能会是消息丢失的原因。
  • 解决:使用阻塞线程池;扩大缓冲区的容量;直接存到磁盘上。
  • consumer自动提交的机制有实践间隔,commit过程和消费消息是异步的,这时候就可能会出现类似与数据库的事务问题,消息就丢失了。
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
// 自动提交开关
props.put("enable.auto.commit", "true");
// 自动提交的时间间隔,此处是1s
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("foo", "bar"));
while (true) {
        // 调用poll后,1000ms后,消息状态会被改为 committed
  ConsumerRecords<String, String> records = consumer.poll(100);
  for (ConsumerRecord<String, String> record : records)
    insertIntoDB(record); // 将消息入库,时间可能会超过1000ms
 
  • 上面的示例是自动提交的例子。如果此时,insertIntoDB(record)发生异常,消息将会出现丢失。接下来是手动提交的例子:
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
// 关闭自动提交,改为手动提交
props.put("enable.auto.commit", "false");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("foo", "bar"));
final int minBatchSize = 200;
List<String, String>> buffer = new ArrayList<>();
while (true) {
        // 调用poll后,不会进行auto commit
  ConsumerRecords<String, String> records = consumer.poll(100);
  for (ConsumerRecord<String, String> record : records) {
    buffer.add(record);
  }
  if (buffer.size() >= minBatchSize) {
    insertIntoDb(buffer);
                // 所有消息消费完毕以后,才进行commit操作
    consumer.commitSync();
    buffer.clear();
  }
 
  • broker丢失消息是由于Kafka本身的原因造成的,kafka为了得到更高的性能和吞吐量,将数据异步批量的存储在磁盘中。消息的刷盘过程,为了提高性能,减少刷盘次数,kafka采用了批量刷盘的做法。即,按照一定的消息量,和时间间隔进行刷盘。这种机制也是由于linux操作系统决定的。将数据存储到linux操作系统种,会先存储到页缓存(Page cache)中,按照时间或者其他条件进行刷盘(从page cache到file),或者通过fsync命令强制刷盘。数据在page cache中时,如果系统挂掉,数据会丢失。

使用kafka的场景

  • 日志收集
  • 消息系统
  • 用户活动追踪
  • 运营指标
  • 流式处理

Kafka 分区的目的?

  • 分区对于 Kafka 集群的好处是:实现负载均衡。分区对于消费者来说,可以提高并发度,提高效率。

你知道 Kafka 是如何做到消息的有序性?

  • kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在里面保证消息的顺序性。但是分区之间的消息是不保证有序的。

Kafka消息是采用Pull模式,还是Push模式?

  • Kafka最初考虑的问题是,customer应该从brokes拉取消息还是brokers将消息推送到consumer,也就是pull还push。在这方面,Kafka遵循了一种大部分消息系统共同的传统的设计:producer将消息推送到broker,consumer从broker拉取消息。
  • 一些消息系统比如Scribe和Apache Flume采用了push模式,将消息推送到下游的consumer。这样做有好处也有坏处:由broker决定消息推送的速率,对于不同消费速率的consumer就不太好处理了。消息系统都致力于让consumer以最大的速率最快速的消费消息,但不幸的是,push模式下,当broker推送的速率远大于consumer消费的速率时,consumer恐怕就要崩溃了。最终Kafka还是选取了传统的pull模式。
  • Pull模式的另外一个好处是consumer可以自主决定是否批量的从broker拉取数据。Push模式必须在不知道下游consumer消费能力和消费策略的情况下决定是立即推送每条消息还是缓存之后批量推送。如果为了避免consumer崩溃而采用较低的推送速率,将可能导致一次只推送较少的消息而造成浪费。Pull模式下,consumer就可以根据自己的消费能力去决定这些策略。
  • Pull有个缺点是,如果broker没有可供消费的消息,将导致consumer不断在循环中轮询,直到新消息到t达。为了避免这点,Kafka有个参数可以让consumer阻塞知道新消息到达。

未完

你可能感兴趣的:(kafka进阶)