Kafka 设计

原文链接:http://kafka.apache.org/documentation/#design
记在前头:这篇原文看了几次,总体感觉干货并不多,迷魂阵不少,不如自己抽出来干货记录下来,遂成此文。


1. 设计目的

从内部需求出发,LinkedIn的消息系统也是一个演变的过程。kafka的出现是为了Cover掉公司的所有的流式数据(不甘于缓存)。LinkedIn力争使其成为一个独立的通用处理系统。综合考虑各种场景,它应该具备如下能力:

  • 大吞吐,支持大的事件流场景,例如实时日志汇聚;
  • 低延时,能够堪比现存消息系统;
  • 高可靠,机器宕机不丢数据;
  • 抗积压,支持大量数据积压场景,例如周期性的离线数据导入;
  • 支持分区、分布式、支持对数据进行实时处理并派生出新的数据(流式);

综上,相比于传统的消息系统,kafka更像一个log系统。
在接触kafka时,会不断的遇到log这个词,日志数据这么定义:Append-only & Ordered by time,从它的定义去理解就会更加轻松,不会被“日志”这个词绊住思想。
为了实现上述功能,Kafka从以下几点着手。

2. Persistence

持久化可以打破内存存储的几点限制:1. 容量小,应付不来大量数据积压;2. 数据易失。RabbitMq同样也会将积压的数据落盘,落盘并不是什么创新。Kafka的创新在于充分利用“日志数据”顺序读写的特性,直接操作pageCache。带来的好处:

  • 速度并不慢,顺序读写省去了磁盘查找耗时,配上SSD, 速度甚至赶超内存;
  • 减少不必要缓存, filesystem的IO接口会涉及数据在用户态缓存;
  • 高效的存储,如果在内存中缓存数据,假设每个Record占用一个Object,会产生大量的对象。对象本身的数据会占用一部分存储,并且会涉及到频繁的GC。数据经producer端序列化然后传输到Server端,Server端直接将数据写入pagecache,存储会更加的高效。

3. Constant Time Suffices

一般消息系统采用B树存储数据,B树可以提供时间复杂度为O(log N)的查找效率。但是对磁盘存储的数据并不合适,磁盘的查找速率太慢并且不能并行。在日志场景,更加常见的是采用类queue结构,查询时间复杂度为O(log 1),与数据量无关,并且读写可同步进行。
此处原文说的太玄乎,其实就是说采用pagecache,因为在虚存中也会有映射,所以保证了访问效率,属于一举多得。

4. Efficiency

PageCache保证了磁盘IO的效率,拉低效率的可能还有两点:

  • 频繁的IO,可以细分为client和Broker的网络IO,Broker写数据的磁盘IO。Kafka将数据合并成batch进行IO,降低IO频次;
  • 过多的数据拷贝,Kafka的优化点在Broker向Consumer发送数据。采用Sendfile的方式,直接将数据从pagecache捅到网络协议栈,即零拷贝;
  • 提供数据压缩,降低带宽使用。

5. Producer

5.1 Load balancing

所有的broker都知道partition的元数据,知道partition的leader是谁。producer端从任一Broker拿到parition Leader信息后,将数据LB至各Leader。LB默认采用随机分配算法,同时也提供按照key值进行hash,还可以通过overwrite方式自定义LB逻辑。

5.2 Asynchronous send

Producer缓存数据形成batch后异步发送,具体可以控缓存数量或者是缓存时间。在这是可能丢失数据的。

6. Comsumer

6.1 push vs pull

两种方式各有优劣,pull方式更加符合kafka的基调:Damb Broker & Smart Client。

  • push方式,生产速度远大于消费速度时,强推消费端吃不消。push逻辑在Server端控制,消费者数量多并且能力差异较大时,Server端控制负担加重。可以加上反压机制调整push的速率,多消费者情况较为复杂。
  • pull方式,当Server端没有数据时可消费时,会产生空转, kafka设计接口的时候会设计成为阻塞接口,直到timeout或者有一定数量的数据,避免不停的pull空。
6.2 Consumer Postition

对于消费完就删数据的消息系统,需要两个消费状态:”已发送的数据”和”Client端已确认的数据”,”Client端已确认”的数据会被清理。Client异常情况下,如果不重发数据,数据可能会丢失;如果重发数据,就要重发已经发送但是Client还未确认的数据,这种情况下Client端可能会收到重复数据。两个通用解决办法:1. Client端自己控制自己要哪些数据;2. Client的处理逻辑做成幂等,能够应付重复数据。
Kafka数据消费完不会立马清除,消费记录模型变得简单:只记录一个“Client端已确认的数据”,并且提供指定offset消费的接口,将控制权交给Consumer。数据的重复处理和防丢失逻辑其实是由Consumer端的code决定的。也就是说,Consumer 是Exactly once还是At least Once并不是Broker决定的。

6.3 Offline Data Load

持久化的设计,为数据定时导入离线系统提供可能。hadoop场景可以启动多个map并发进行数据加载。camus采用这种方式,但是逐渐退出历史舞台,取而代之的是kafka connect。

7 Message Delivery Semantics

Producer和Comsumer 分开讲:

  • Producer,是”At least once”,0.11.0.0版本之前,依靠commit,未commit的消息进行重新发送。0.11.0.0之后搞定了重发数据不重复的问题,基于每producer进行消息编号,实现幂等。能否重发也还要倚靠数据源的能力。
  • Consumer端:是收到数据就commit还是处理完数据再commit,这个需要consumer自己定;在0.11.0.0之后引入事务,从A topic消费处理后写入B Topic的流式场景,可以实现Exactly Once。

8 Replication

有两个事情一定要掰扯开讲: 数据可靠性和Leader的选举。

8.1 数据的可靠性

要想数据可靠,数据必须在多个节点上有副本,这样集群中节点fail后,数据不会丢失。如果想保证n个节点挂掉了数据还OK,则写入数据时必须同步n+1个节点。同步的节点越多,越可靠,但是占用越多的带宽和存储,多节点情况下带宽可能首先成为瓶颈。

8.2 Leader选举

Leader的选举,不少采用Majority vote方法的系统。但是这种方法必须得到过半数的选票才能成为leader。那么,如果想保证集群中n个节点挂掉后还能产生新的leader,集群的总数必须大于2n+1,此种方式对集群规模要求太严格。

8.3 Kafka处理方式

Replica。Kafka将一个Topic分隔成为多个Partition,每个Partition又有多个Replica。Leader选举指的是在这个多个Replica中选举出一个Leader,作为Partition数据读写的统一入口。

ISR。Kafka引入了ISR,什么概念呢?为了保证可靠,副本的总数还是要跟上去,避免节点挂了之后所有的数据都丢失了,但是并不要求每次写入操作都同步过半数的副本,只需要同步少量的副本,这些处于同步状态的副本就会计入ISR。注意,每次写入时同步的副本数是可配置的,他保证了ISR中的最小副本数,但是可能比ISR中副本总数小。ISR是一个不会和Leader偏离太多的副本集合。Kafka采用异步同步方式,ISR中可能还有些自己跑得快的兄弟。一旦Leader挂掉,新的Leader从ISR产出。

异步同步。Kafka直接复用了Consumer机制进行Replica的同步,也就是说同步是一种pull模型,是异步的。

Leader选举Controller。集群中选择一个broker作为controller,当某个broker挂掉之后,controller对leader是异常broker上的partition进行选举。controller本身有HA。
这是一种速度和粒度的折衷,如果基于每topic partition进行精细控制,会加大leader切换的时间。

8.4 小结

Kafka采用了折衷方法,同步较少的副本,更小代价产出新的副本,可能会丢失数据。如果就是希望更高可靠的场景怎么办?1.设置unclean的副本不能成为leader, 负面的影响就是可能导致服务不可用,牺牲易用性;2. 加大副本最小同步份数,多用点带宽和存储。
(原文中,关于数据一致性那一段了,没啥干货并且搞的整体很难懂。)

9 Log Compaction

日志压缩和删除过期的数据并不冲突,压缩是为了适用不关系过程数据的场景,例如表中数据的update过程等。这些场景在异常恢复时,无需关系历史过程,读取少量数据就可以恢复。同时,日志的压缩也可以减少对存储的占用。怎么压缩?同一个key值保留最后一个值,有配置项控制多长时间前的数据开始压缩。

10 Quotas

基于网络带宽和请求频率的资源控制。这个原文说的很精简,参考原文。

11 自己说

没有读过具体的源码,有理解错误或者觉得原文中很重要但是我没有提到的,请大家帮忙通知我,我会第一时间修整和添加。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值