在做分布式编译的时候,每一个worker都有一个consumer,适用的kafka+zookeep的配置都是默认的配置,在消息比较少的情况下,每一个consumer都能均匀得到互不相同的消息,但是当消息比较多的时候,这个时候consumer就有重复消费的情况。

如何排查这种问题呢?

最开始以为是系统资源的瓶颈,编译worker和kafka cluster都在一个集群上,导致消息同步不及时,所以就另外找了几个机器,kafka和编译worker分开。但是还是会遇到上述问题。

然后就想集群环境一致性最重要的一个条件是时间,然后将所有的机器都设置了统一的时间服务器,结果还是不行。

最后查看自己写的代码,将缓存队列开大一些,竟然没有重复了。

心想可能是自己使用的方式有点问题:下面是分析的过程

1: 分析重复的情况是什么?是由于不同hosts上重复的消费,还是相同hosts上的重复消费?

  经过对比测试,是属于相同hosts上的重复消费,间隔大概为20个message

2: kafka的消息队列模型是什么?

  • 一个topic: tizen-unified
  • 三个partition:0,1,2
  • 一个producer, 三个consumer。
  • 每个consumer 端设置一个缓存队列,当队列满的时候,consumer线程进入阻塞的状态,这个时候编译进程从队列中取package进行编译,直到队列为空为止。

如下是consumer端的代码:

#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
"""gbs-worker - distributed system worker module."""
import os
import re
import Queue
import time
import threading
import multiprocessing
from multiprocessing import Process
from kafka import KafkaConsumer
from kafka import KafkaProducer class Producer(Process):
def __init__(self):
super(Producer, self).__init__()
self.messageHandler = KafkaConsumer('tizen-unified',group_id='tizen-worker',bootstrap_servers='109.123.100.144:9092')
def run(self):
print "start produce, os pid: %d" % (os.getpid())
for message in self.messageHandler: # which will resume if there is a message from kafka
while(WorkerPool.taskQueue.full() is True):
time.sleep(5)
print "put package %s into queue" % message.value
WorkerPool.taskQueue.put(message.value) class GbsBuild(object):
errorRule = re.compile(r"some packages failed to be built")
def __init__(self,packageName, id):
super(GbsBuild, self).__init__()
self.sourcePath = "/home/scm/renjg/workspace"
self.logPath = "/home/scm/renjg/logs"
self.gbsPath = "/usr/bin/gbs"
self.gbsconf = self.sourcePath+"/.gbs.conf"
self.gbsRoot = "/home/scm/GBS-ROOT"
self.packageName = packageName
self.threadId = id
def build(self):
os.system("cd %s" % (self.sourcePath))
os.system("mkdir -p %s" % self.logPath)
result = os.popen("gbs -c %s build -A armv7l -B %s-%d --binary-list %s --clean >%s/%s.log 2>&1" % (self.gbsconf,self.gbsRoot, self.threadId, self.packageName, self.logPath, self.packageName)).read()
if GbsBuild.errorRule.findall(result):
print "%s build error \n log file is: %s/%s.log" % (self.packageName, self.logPath, self.packageName)
return "Fail"
os.system("scp -r %s renjg@109.123.123.6:/home/renjg/GBS-ROOT/local/repos/unified_standard/" % (self.gbsRoot+"-"+str(self.threadId)+"/local/repos/unified_standard/armv7l/"))
print "%s package in process %d ,build done, copy done" % (self.packageName, self.threadId)
return "Success" class Consumer(Process):
def __init__(self, threadId, partition = 0):
super(Consumer,self).__init__()
self.partition = partition
self.threadId = threadId
self.messageHandler = KafkaProducer(bootstrap_servers="109.123.100.144:9092")
def run(self):
print "start consume thread %d , os pid: %d" % (self.threadId, os.getpid())
while True:
while WorkerPool.taskQueue.empty() is True:
time.sleep(1)
packageName = WorkerPool.taskQueue.get()
print "thread %d start %s package " % (self.threadId, packageName)
gbsbuild = GbsBuild(packageName,self.threadId)
print "thread %d building %s package" % (self.threadId, packageName) if gbsbuild.build() == "Success":
#if True:
result = self.messageHandler.send("tizen-unified-status", value = "succeed", key = packageName, partition=0)
if(result.get(60)):
print "send success"
else:
print "send fail"
else:
result = self.messageHandler.send("tizen-unified-status", value = "failed", key = packageName, partition=0)
if(result.get(60)):
print "send success"
else:
print "send fail" class WorkerPool(object):
capcaticy = 4
curThreadNum = 0
taskQueue = multiprocessing.Queue(capcaticy*100) #如果taskQueue很小的话,那么就会出现producer重复的获取消息的情况。
def __init__(self):
self.producer = Producer()
self.consumers = [Consumer(i) for i in xrange(WorkerPool.capcaticy)]
def start(self):
print "start Worker pool"
self.producer.start()
for i in range(0, WorkerPool.capcaticy):
self.consumers[i].start()
self.producer.join()
for i in range(0, WorkerPool.capcaticy):
self.consumers[i].join()
wp = WorkerPool()
wp.start()
print "Done"

当前的改进思路是:扩大WorkerPool.taskQueue的容量,当一次poll就获取足够多的message,然后consumer慢慢处理。

还有一种改进思路是:去掉producer,直接在每一个consumer中间创建一个connection, 把互斥的任务交给kafka去做。待测试。

kafka consumer重复消费问题的更多相关文章

  1. Apache Kafka(九)- Kafka Consumer 消费行为

    1. Poll Messages 在Kafka Consumer 中消费messages时,使用的是poll模型,也就是主动去Kafka端取数据.其他消息管道也有的是push模型,也就是服务端向con ...

  2. Kafka重复消费和丢失数据研究

    Kafka重复消费原因 底层根本原因:已经消费了数据,但是offset没提交. 原因1:强行kill线程,导致消费后的数据,offset没有提交. 原因2:设置offset为自动提交,关闭kafka时 ...

  3. kafka丢失和重复消费数据

    Kafka作为当下流行的高并发消息中间件,大量用于数据采集,实时处理等场景,我们在享受他的高并发,高可靠时,还是不得不面对可能存在的问题,最常见的就是丢包,重发问题. 1.丢包问题:消息推送服务,每天 ...

  4. 【消息队列】kafka是如何保证消息不被重复消费的

    一.kafka自带的消费机制 kafka有个offset的概念,当每个消息被写进去后,都有一个offset,代表他的序号,然后consumer消费该数据之后,隔一段时间,会把自己消费过的消息的offs ...

  5. kafka一直rebalance故障,重复消费

    今天我司线上kafka消息代理出现错误日志,异常rebalance,而且平均间隔2到3分钟就会rebalance一次,分析日志发现比较严重.错误日志如下 08-09 11:01:11 131 pool ...

  6. Kafka中的消息是否会丢失和重复消费(转)

    在之前的基础上,基本搞清楚了Kafka的机制及如何运用.这里思考一下:Kafka中的消息会不会丢失或重复消费呢?为什么呢? 要确定Kafka的消息是否丢失或重复,从两个方面分析入手:消息发送和消息消费 ...

  7. Kafka如何保证百万级写入速度以及保证不丢失不重复消费

    一.如何保证百万级写入速度: 目录 1.页缓存技术 + 磁盘顺序写 2.零拷贝技术 3.最后的总结 “这篇文章来聊一下Kafka的一些架构设计原理,这也是互联网公司面试时非常高频的技术考点. Kafk ...

  8. kafka如何保证不重复消费又不丢失数据_Kafka写入的数据如何保证不丢失?

    我们暂且不考虑写磁盘的具体过程,先大致看看下面的图,这代表了 Kafka 的核心架构原理. Kafka 分布式存储架构 那么现在问题来了,如果每天产生几十 TB 的数据,难道都写一台机器的磁盘上吗?这 ...

  9. 实际业务处理 Kafka 消息丢失、重复消费和顺序消费的问题

    关于 Kafka 消息丢失.重复消费和顺序消费的问题 消息丢失,消息重复消费,消息顺序消费等问题是我们使用 MQ 时不得不考虑的一个问题,下面我结合实际的业务来和你分享一下解决方案. 消息丢失问题 比 ...

随机推荐

  1. mecacheq的配置

    在处理业务逻辑时有可能遇到高并发问题,例如商城秒杀.微博评论等.如果不做任何措施可能在高瞬间造成服务器瘫痪,如何解决这个问题呢?队列是个不错的选择.队列(Queue)又称先进先出(First In F ...

  2. 查看 chrome 浏览器中的 Headers

    查看 chrome 浏览器中的 Headers, Response 信息:

  3. JavaScript判断对象有没有定义

    if ( typeof(callbackfun) != "undefined" ) { callbackfun(); }

  4. JavaScript中的变量提升和函数提升

    在EcmaScript5中只有全局作用域和函数作用域,EcmaScript6增加了块级作用域. 块级作用域(一对花括号{}即为一个块级作用域) 变量提升 console.log(name); //un ...

  5. 服务器日志文件Web远程查看

    公司买的一款企业应用软件,所有透过应用操作DB的操作都会生成有日志,日志是以文本文件的形式存放在服务器上,后缀名为*.log.1,*.log.2之类的,软件本身也提供功能查询这些日志,但这个查询的功能 ...

  6. Shell if条件语句

    1.if条件语句:设定一个条件如果怎么,然后怎么样. (1)-gt大于.-lt小于.-ge大于等于.-le小于等于.-eq等于.-ne不等于. (2)[]内是包括变量时所使用的. (3)-f文件.-n ...

  7. opencv学习之路(23)、轮廓查找与绘制(二)——访问轮廓每个点

    一.简介 二.画出每个轮廓的每个点 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat src= ...

  8. [c/c++] programming之路(12)、循环结构

    一.求2n #include<stdio.h> void main(){ ; ; while(n--){ s*=; printf("%d,%d\n",s,n); } g ...

  9. SIP 编解码器

    编解码器,编码器 - 解码器的简称,做两个基本操作 - 首先,它将模拟语音信号转换为其等效数字形式,以便可以容易地发送. 此后,它将压缩的数字信号转换回其原始模拟形式,以便可以重放. 市场上有许多编解 ...

  10. 【JS面试向】选择排序、桶排序、冒泡排序和快速排序简介

    新年伊始,又到了金三银四的时候了.面对前端越来越多的算法面试题,我简单的整理了一下几种比较常见的数组排序方式,分别介绍其基本原理和优劣势.(ps:才疏学浅,希望大家可以在issues下面指出问题) 选 ...