大数据中间件kafka的设计哲学

在这里插入图片描述

1,kafka是基于多分区多副本的分布式消息系统。

一个topic对应多个partition,每个partition又由一个一个消息组成。每个消息都被标识了一个递增序列号代表其进来的先后顺序,并按顺序存储在partition中。

在这里插入图片描述
这样,消息就以一个个id的方式,组织起来。

producer选择一个topic,生产消息,消息会通过分配策略append到某个partition末尾。

consumer选择一个topic,通过id指定从哪个位置开始消费消息。消费完成之后保留id,下次可以从这个位置开始继续消费,也可以从其他任意位置开始消费。
这个id,在kafka中被称为offset

*多分区的优点*
  1. 消费者可以根据需求,灵活指定offset消费

  2. 保证了消息不变性,为并发消费提供了线程安全的保证。每个consumer都保留自己的offset,互相之间不干扰,不存在线程安全问题

  3. 消息访问的并行高效性。每个topic中的消息被组织成多个partition,partition均匀分配到集群server中。生产、消费消息的时候,会被路由到指定partition,减少竞争,增加了程序的并行能力

  4. 增加消息系统的可伸缩性。每个topic中保留的消息可能非常庞大,通过partition将消息切分成多个子消息,并通过负责均衡策略将partition分配到不同server。这样当机器负载满的时候,通过扩容可以将消息重新均匀分配

  5. 保证消息可靠性。消息消费完成之后不会删除,可以通过重置offset重新消费,保证了消息不会丢失

  6. 灵活的持久化策略。可以通过指定时间段(如最近一天)来保存消息,节省broker存储空间

2,kafka producer

  1. topic:往哪个topic生产消息。
  2. partition:往哪个partition生产消息。
  3. key:根据该key将消息分区到不同partition。
  4. message:消息

3,consumer group

kafka通过consumer group将两种模式(队列和发布订阅)统一处理:每个consumer将自己标记consumer group名称,之后系统会将consumer group按名称分组,将消息复制并分发给所有分组,每个分组只有一个consumer能消费这条消息。

在这里插入图片描述
consumer rebalance:在一个group中,有consumer加入或者离开时,会触发partitions均衡。均衡的最终目的,是提升topic的并发消费能力。

4,kafka 可靠性,一致性

可靠性:

Durability can be configured with the producer configuration request.required.acks

0 : The producer never waits for an ack
1 : The producer gets an ack after the leader replica has received the data
-1 : The producer gets an ack after all ISRs receive the data

Leader 选举:每个分区的 leader 会维护一个 ISR (in-sync replicas)列表,ISR 列表里面就是 follower 副本的 Borker 编号,只有跟得上 Leader 的 follower 副本才能加入到 ISR 里面,这个是通过 replica.lag.time.max.ms 参数配置的(它跟踪 follower 副本没有向 leader 发送获取请求的时间,通过这个可以推断 follower 是否正常)。这在网络流量大时,可以避免由replica.lag.max.messages=4所造成的不精确缺陷。

所以当 Leader 挂掉了,而且 unclean.leader.election.enable=false 的情况下,Kafka 会从 ISR 列表中选择第一个 follower 作为新的 Leader,因为这个分区拥有最新的已经 committed 的消息。通过这个可以保证已经 committed 的消息的数据可靠性。

综上所述,为了保证数据的可靠性,我们最少需要配置一下几个参数:

  • producer 级别:acks=all(或者 request.required.acks=-1),同时发生模式为同步
    producer.type=sync
  • topic 级别:设置 replication.factor>=3,并且min.insync.replicas>=2;
  • broker 级别:关闭不完全的 Leader 选举,即unclean.leader.election.enable=false;
数据一致性:

在这里插入图片描述
通过HW(high water mark)机制实现。
假设分区的副本为3,其中副本0是 Leader,副本1和副本2是 follower,并且在 ISR 列表里面。虽然副本0已经写入了 Message4,但是 Consumer 只能读取到 Message2。因为所有的 ISR 都同步了 Message2,只有 High Water Mark 以上的消息才支持 Consumer 读取,而 High Water Mark 取决于 ISR 列表里面偏移量最小的分区,对应于上图的副本2,这个很类似于木桶原理。

5,性能

kafka在以下四点做了优化:
  1. 将大量小io改造成少量大io
  2. 利用sendfile减少数据拷贝
  3. 支持snappy,gzip,lz4三种算法批量压缩消息,减少网络传输消耗
  4. 采用nio网络模型,与1 acceptor thread + N processor threads的reactor线程模型
    大量读写少量消息会导致性能较差,通过将消息聚合,可以减少读写次数(减少随机IO),增加单次读写数据量(增加顺序IO)

6,持久化

基于以下几点事实,kafka重度依赖磁盘而非内存来存储消息
  1. 硬盘便宜,内存贵
  2. 顺序读+预读取操作,能提高缓存命中率
  3. 操作系统利用富余的内存作为pagecache,配合预读取(read-ahead)+写回(write-back)技术,从cache读数据,写到cache就返回(操作系统后台flush),提高用户进程响应速度
  4. java对象实际大小比理想大小要大,使得将消息存到内存成本很高 当堆内存占用不断增加时,gc抖动较大
  5. 基于文件顺序读写的设计思路,代码编写简单

在持久化数据结构的选择上,kafka采用了queue而不是Btree

  1. kafka只有简单的根据offset读和append操作,所以基于queue操作的时间复杂度为O(1),而基于Btree操作的时间复杂度为O(logN)
  2. 在大量文件读写的时候,基于queue的read和append只需要一次磁盘寻址,而Btree则会涉及多次。磁盘寻址过程极大降低了读写性能

参考:
http://kafka.apache.org/
https://www.sohu.com/a/144225753_236714
https://blog.csdn.net/vinfly_li/article/details/79397201
https://www.iteblog.com/archives/2560.html
https://www.iteblog.com/archives/2556.html
https://www.jianshu.com/p/da62e853c1ea

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值