Kafka数据消费:快速上手
Kafka逻辑模型
整体流程
由一些Producer进程向Kafka的服务器(称为Broker)发送消息,这些消息以topic区分,消息本身由key,value对和其他的属性字段组成;Broker接收来自Producer的消息(按照topic区分)之后,按照分区策略分到不同的partition,每一个partition内的消息是有序的队列,并按照副本策略复制指定次数;当Consumer进程连接到Broker后,订阅(subscribe)特定的topic,就可以开始消费数据,即从topic的多个partition中获得(poll)数据。
存储逻辑模型
Kafka在理论上提供一个稳定且长久保存的消息队列,但实际上因为磁盘空间有限或者策略设置,会将旧的数据清除掉;当Broker收到Producer发送的一条消息后,消息被送到其中的一个分区中,并将该分区的结束位置偏移量(end offset)向后增加1;当根据清理策略将旧的一条消息清除后,开始位置偏移量(begin offset)向后增加1。
Kafka数据消费
消费者组
Kafka在理论上提供并发和可靠的消息消费,对于一个消费者组(Consumer group)来说,topic下的多个partition会被分配(assign)到Consumer group中的相同或不同Consumer上(取决于partition数量和Consumer数量,如果二者数量相等,则每个Consumer将从每个被固定分配的partition中读取数据)。
将Consumer group看作一个整体,每次新的Consumer group初始化的时候,依照策略将当前的读取位置偏移量(position)移动到begin offset或end offset上;在每次从某个partition中poll数据后,应当将该group在该partition中的position向后移动此次poll的数据量(这个过程称为commit,如果设置了auto commit,则该过程和poll过程捆绑进行),从而记录下该分区的数据已经消费到何处了,从而避免数据的重复消费。
数据获取
Kafka提供的数据消费接口是poll(获取),poll的执行单位是Consumer group,当执行poll的时候,实际的执行流程伪代码(仅用于理解具体过程,如果不需要,可以直接跳到下一节)为:
function poll(Consumer_group g)
{
polled_data = Dict()
foreach Consumer c in g: // 对于组里的每个Consumer c
{
if not assigned(consumer_id=c){ // 如果c没有被分配topic中的分区
assign_partition(consumer_id=c) // 就分配若干分区
}
Partition_list pars = get_assigned_partitions(consumer_id=c) // 如果已经分配,则获取分配的分区
foreach Partirion par in pars: // 对于分配的每个分区par
{
if not par.is_paused(){ // 如果没有被暂停消费
pos = par.get_position(group_id=g) // 获得c在该分区当前的偏移量position
data = fetch_data_from_parti