众所周知,Kafka 0.11.0.0版本正式支持精确一次处理语义(exactly once semantics,下称EOS)。Kafka的EOS主要体如今3个方面:html
上面3种EOS语义有着不一样的应用范围,幂等producr只能保证单分区上无重复消息;事务能够保证多分区写入消息的完整性;而流处理EOS保证的是端到端(E2E)消息处理的EOS。用户在使用过程当中须要根据本身的需求选择不一样的EOS。如下是启用方法:缓存
所谓幂等producer指producer.send的逻辑是幂等的,即发送相同的Kafka消息,broker端不会重复写入消息。同一条消息Kafka保证底层日志中只会持久化一次,既不会丢失也不会重复。幂等性能够极大地减轻下游consumer系统实现消息去重的工做负担,所以是很是实用的功能。值得注意的是,幂等producer提供的语义保证是有条件的:ide
虽然有上面两个限制,幂等producer依然是一个很是实用的新功能。下面咱们来讨论下它的设计原理。若是要实现幂等性, 一般都须要花费额外的空间来保存状态以执行消息去重。Kafka的幂等producer总体上也是这样的思想。设计
首先,producer对象引入了一个新的字段:Producer ID(下称PID),它惟一标识一个producer,当producer启动时Kafka会为每一个producer分配一个PID(64位整数),所以PID的生成和分配对用户来讲是彻底透明的,用户无需考虑PID的事情,甚至都感觉不到PID的存在。其次,0.11 Kafka重构了消息格式(有兴趣的参见Kafka 0.11消息设计),引入了序列号字段(sequence number,下称seq number)来标识某个PID producer发送的消息。和consumer端的offset相似,seq number从0开始计数并严格单调增长。同时在broker端会为每一个PID(即每一个producer)保存该producer发送过来的消息batch的某些元信息,好比PID信息、消息batch的起始seq number及结束seq number等。这样每当该PID发送新的消息batch时,Kafka broker就会对比这些信息,若是发生冲突(好比起始seq number和结束seq number与当前缓存的相同),那么broker就会拒绝此次写入请求。假若没有冲突,那么broker端就会更新这部分缓存而后再开始写入消息。这就是Kafka实现幂等producer的设计思路:1. 为每一个producer设置惟一的PID;2. 引入seq number以及broker端seq number缓存更新机制来去重。日志