在做分布式编译的时候,每一个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. zw量化交易·实盘操作·系列培训班

    参见: <zw量化交易·实盘操作·系列培训班> http://blog.sina.com.cn/s/blog_7100d4220102w0q5.html

  2. django 完整日志配置

    django中的log需要在settings.py中配置 import time cur_path = os.path.dirname(os.path.realpath(__file__)) # lo ...

  3. TLS握手、中断恢复与证书中心的原因

    在双方都拿到随机数A.B.C后,将会使用这三个随机数生成一个对话密钥,然后使用该对话密钥进行对称加密通信,这种方式我们可以看到,安全性取决于随机数C的加密,前面的几个都是明文传的,这里就取决于服务器的 ...

  4. <转>jmeter(二十三)分布式测试

    本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...

  5. 复习-css边框和背景属性

    css边框和背景属性 border:所有边框属性 border-width:四条边框的宽度 border-style:设置边框样式,主要有dotted.solid.double border-colo ...

  6. [C++ Primer Plus] 第6章、分支语句和逻辑运算符(二)课后习题

    一.复习题 3. #include<iostream> using namespace std; void main() { char ch; int c1, c2; c1 = c2 = ...

  7. opencv学习之路(28)、轮廓查找与绘制(七)——位置关系及轮廓匹配

    一.点与轮廓的距离及位置关系 #include "opencv2/opencv.hpp" #include <iostream> using namespace std ...

  8. UVA11995 I Can Guess the Data Structure!

    思路 简单题,用栈,队列,优先队列直接模拟即可 代码 #include <cstdio> #include <algorithm> #include <cstring&g ...

  9. 异常:unity3d ArgumentException: The Assembly System.Configuration is referenced by System.Data.

    异常:ArgumentException: The Assembly System.Configuration is referenced by System.Data. But the dll is ...

  10. CSS【04】:CSS组合选择器

    组合选择器 群组(并集)选择器 作用:给所有选择器选中的标签设置属性,可以同时控制多个选择器 格式: 选择器1, 选择器2 { 属性: 值; } 注意点: 必须使用,来连接 选择器可以使用标签名称.i ...