Java面试题精选:消息队列(二)

一、Kafka的特性

1.消息持久化:消息存储在磁盘,所以消息不会丢失
2.高吞吐量:可以轻松实现单机百万级别的并发
3.扩展性:扩展性强,还是动态扩展
4.多客户端支持:支持多种语言(Java、C、C++、GO、)
5. Kafka Streams(一个天生的流处理):在双十一或者销售大屏就会用到这种流处理。使 用Kafka Streams可以快速的把销售额统计出来
6.安全机制:Kafka 进行生产或者消费的时候会有多种安全机制来进行确保
7.数据备份:不一定做生产消费,也可以做数据备份
8.轻量级:版本统一,安装便捷
9.消息压缩:如果消息非常占用带宽,可以进行消息压缩。并且不仅支持自定义的压缩算法,也可以按照默认的压缩算法进行处理。可以让消息的生产或消费更上一层楼

二、kafka中,可以不用zookeeper么?

Kafka是Java生态圈下的一员,用Scala,运行在Java虚拟机上,所以安装运行和普通java程序并没有什么区别。

Kafka需要zookeeper保存集群的元数据信息和消费者信息。Kafka一般会自带Zookeeper,但是从稳定性考虑,应该使用单独的Zookeeper,而且构建Zookeeper集群。

也就是新版本的kafka可以不用(>3.0版本的),可以使用Kafka with Kraft,就可以完全抛弃zookeeper

三、kafka适合哪些场景?

  • 日志收集:kafka高并发,又天生持久化。写文件也是按照顺序的方式写入
  • 消息系统:kafka虽然是按照大数据的领域设计的,但是表现形式和消息系统相似
  • 流式处理:kafka里面有一个Stream的组件。

四、为什么Kafka不支持读写分离?

Kafka不支持读写分离,但支持主从架构。
如果主写从读会导致:
1、数据一致性问题:数据从主节点转到从节点,必然会有一个延时的时间窗口,这个时间窗口会导致主从节点之间的数据不一致。
Java面试题精选:消息队列(二)_第1张图片
2、延时问题:Kafka追求高性能,如果走主从复制,必然是异步的,如果要实现读写分离,那必然就需要等,延时严重
Java面试题精选:消息队列(二)_第2张图片
3、如果实现主写从读,则无法实现负载均衡的。
4、如果不实现读写分离,架构会简单,出错的可能性就小
5、如果不实现读写分离,多副本的机制也会简单很多

五、Kafka中是怎么做到消息顺序性的?

生产者在发送消息的时候指定要发送到特定Partition(分区)
将 producer 发送的数据封装成一个 ProducerRecord 对象。
(1)指明 partition 的情况下,直接将指明的值直接作为 partiton 值;
(2)没有指明 partition 值但有 key 的情况下,在Producer往Kafka插入数据时,控制同一Key分发到同一Partition,并且设置参数max.in.flight.requests.per.connection=1,也即同一个链接只能发送一条消息,如此便可严格保证Kafka消息的顺序
通俗来讲,就是建立一个partition,一个生产者,一个消费者
Java面试题精选:消息队列(二)_第3张图片

六、Kafka为什么那么快?

  1. 利用 Partition 实现并行处理
  2. 顺序写磁盘:文件顺序读写,速度接近内存。(既可以使用磁盘的持久化,又可以保证高效)
  3. 充分利用 Page Cache
  4. 零拷贝技术:Kafka写入数据,传统需要4次拷贝。使用零拷贝技术,可以减少没有必要的拷贝
    Java面试题精选:消息队列(二)_第4张图片Java面试题精选:消息队列(二)_第5张图片
  5. 批处理
  6. 数据压缩。使用json文件的话,压缩比差不多有7倍
  7. 对流数据的支持

七、说一说Kafka你熟悉的参数?

一般来说,就记住acks、batch.size、linger.ms、max.request.size就行了,因为这4个参数重要些

  1. acks

指定了必须要有多少个分区副本收到消息,生产者才会认为写入消息是成功的,这个参数对消息丢失的可能性有重大影响。

acks=0:生产者在写入消息之前不会等待任 何来自服务器的响应,容易丢消息,但是吞吐量高。

acks=1:只要集群的首领节点收到消息,生产者会收到来自服务器的成功响应。如果消息无法到达首领节点(比如首领节点崩溃,新首领没有选举出来),生产者会收到一个错误响应,为了避免数据丢失,生产者会重发消息。不过,如果一个没有收到消息的节点成为新首领,消息还是会丢失。默认使用这个配置。

acks=all:只有当所有参与复制的节点都收到消息,生产者才会收到一个来自服务器的成功响应。延迟高。
金融业务,主备外加异地灾备。所以很多高可用场景一般不是设置2个副本,有可能达到5个副本,不同机架上部署不同的副本,异地上也部署一套副本
2. batch.size
当多个消息被发送同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。当批次内存被填满后,批次里的所有消息会被发送出去。但是生产者不一定都会等到批次被填满才发送,半满甚至只包含一个消息的批次也有可能被发送。缺省16384(16k) ,如果一条消息超过了批次的大小,会写不进去。
3. linger.ms
指定了生产者在发送批次前等待更多消息加入批次的时间。它和batch.size以先到者为先。也就是说,一旦我们获得消息的数量够batch.size的数量了,他将会立即发送而不顾这项设置,然而如果我们获得消息字节数比batch.size设置要小的多,我们需要“linger”特定的时间以获取更多的消息。这个设置默认为0,即没有延迟。设定linger.ms=5,例如,将会减少请求数目,但是同时会增加5ms的延迟,但也会提升消息的吞吐量。
4. max.request.size
控制生产者发送请求最大大小。默认这个值为1M,如果一个请求里只有一个消息,那这个消息不能大于1M,如果一次请求是一个批次,该批次包含了1000条消息,那么每个消息不能大于1KB。注意:broker具有自己对消息记录尺寸的覆盖,如果这个尺寸小于生产者的这个设置,会导致消息被拒绝。这个参数和Kafka主机的message.max.bytes 参数有关系。如果生产者发送的消息超过message.max.bytes设置的大小,就会被Kafka服务器拒绝。
5. bootstrap.servers
该属性指定broker的地址清单,地址的格式为host:port。清单里不需要包含所有的broker地址,生产者会从给定的broker里查询其他broker的信息。不过最少提供2个broker的信息(用逗号分隔,比如: 127.0.0.1:9092,192.168.0.13:9092),一旦其中一个宕机,生产者仍能连接到集群上。
5. key.serializer
生产者接口允许使用参数化类型,可以把Java对象作为键和值传broker,但是broker希望收到的消息的键和值都是字节数组,所以,必须提供将对象序列化成字节数组的序列化器。key.serializer必须设置为实现org.apache.kafka.common.serialization.Serializer的接口类,Kafka的客户端默认提供了ByteArraySerializer,IntegerSerializer, StringSerializer,也可以实现自定义的序列化器。
6. buffer.memory
设置生产者内存缓冲区的大小,生产者用它缓冲要发送到服务器的消息。如果数据产生速度大于向broker发送的速度,导致生产者空间不足,producer会阻塞或者抛出异常。缺省33554432 (32M)
7. max.block.ms
指定了在调用send()方法或者使用partitionsFor()方法获取元数据时生产者的阻塞时间。当生产者的发送缓冲区已满,或者没有可用的元数据时,这些方法就会阻塞。在阻塞时间达到max.block.ms时,生产者会抛出超时异常。缺省60000ms
8. retries
发送失败时,指定生产者可以重发消息的次数(缺省Integer.MAX_VALUE)。默认情况下,生产者在每次重试之间等待100ms,可以通过参数retry.backoff.ms参数来改变这个时间间隔。
9. receive.buffer.bytes和send.buffer.bytes
指定TCP socket接受和发送数据包的缓存区大小。如果它们被设置为-1,则使用操作系统的默认值。如果生产者或消费者处在不同的数据中心,那么可以适当增大这些值,因为跨数据中心的网络一般都有比较高的延迟和比较低的带宽。缺省102400
11. compression.type
producer用于压缩数据的压缩类型。默认是无压缩。正确的选项值是none、gzip、snappy。压缩最好用于批量处理,批量处理消息越多,压缩性能越好。snappy占用cpu少,提供较好的性能和可观的压缩比,如果比较关注性能和网络带宽,用这个。如果带宽紧张,用gzip,会占用较多的cpu,但提供更高的压缩比。
12. client.id
当向server发出请求时,这个字符串会发送给server。目的是能够追踪请求源头,以此来允许ip/port许可列表之外的一些应用可以发送信息。这项应用可以设置任意字符串,因为没有任何功能性的目的,除了记录和跟踪。
13. max.in.flight.requests.per.connection
指定了生产者在接收到服务器响应之前可以发送多个消息,值越高,占用的内存越大,当然也可以提升吞吐量。发生错误时,可能会造成数据的发送顺序改变,默认是5 (修改)。
如果需要保证消息在一个分区上的严格顺序,这个值应该设为1。不过这样会严重影响生产者的吞吐量。
14. request.timeout.ms
客户端将等待请求的响应的最大时间,如果在这个时间内没有收到响应,客户端将重发请求;超过重试次数将抛异常,默认30秒。
15. metadata.fetch.timeout.ms
是指我们所获取的一些元数据的第一个时间数据。元数据包含:topic,host,partitions。此项配置是指当等待元数据fetch成功完成所需要的时间,否则会跑出异常给客户端

你可能感兴趣的:(Java面试题精选,java,kafka)