在做分布式编译的时候,每一个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. The All-purpose Zero (最长公共子序列)

    题意:求最长公共子序列,但是有个辅助条件,那就是如果那个值为0,那么他可以更换为任意值. 思路:假设现在只剩下没有0的序列是不是就很好求了?那么我们的想法就是看有没有办法将0往最左端或者最有端移动,显 ...

  2. 2017-2018-1 20155228 《数学建模》 MatlabR2017a安装教程

    2017-2018-1 20155228MatlabR2017a安装教程 原版软件和破解补丁的下载 原版软件和破解补丁的下载链接 需要关注微信公众号才能获取下载密码,照办就是了,为了学习嘛哈哈哈 有三 ...

  3. configparser配置文件处理

    创建一个configparser格式的文档: import configparser config = configparser.ConfigParser()config["DEFAULT& ...

  4. IP通信基础学习第一周

    在IP方向上,IP通信基础是学习其他诸如:数字程教控交换技术与应用.IPV6技术与应用.SDH传输技术与应用等课程的基础. 学习IP通信基础,对学生而言至少可以拿学分,不仅有利于以后的学习,还有机会从 ...

  5. 每天一个Linux命令 10

    文件处理命令:ln命令名称:ln 命令英文原意:link语法: ln -s [原文件] [目标文件] -s 创建软连接功能描述:生成链接文件 #ln -s /etc/issue /tmp/issue. ...

  6. POJ 1038 Bugs Integrated, Inc.(DFS + 三进制状压 + 滚动数组 思维)题解

    题意:n*m方格,有些格子有黑点,问你最多裁处几张2 * 3(3 * 2)的无黑点格子. 思路:我们放置2 * 3格子时可以把状态压缩到三进制: 关于状压:POJ-1038 Bugs Integrat ...

  7. UVA1160 X-Plosives

    思路 每个元素设为点,化合物设为边 不能出现k条边k个点的环 直接并查集检查即可 代码 #include <cstdio> #include <algorithm> #incl ...

  8. 【Visual Studio 扩展工具】如何在ComponentOneFlexGrid树中显示RadioButton

    概述 在ComponentOne Enterprise .NET控件集中,FlexGrid表格控件是用户使用频率最高的控件之一.它是一个功能强大的数据管理工具,轻盈且灵动,以分层的形式展示数据(数据呈 ...

  9. WEB 前端插件整理

    Vs Code 系统插件 #1 Bracket Pair Colorizer 让括号拥有独立的颜色,易于区分.可以配合任意主题使用. #2 Code Runner 非常强大的一款插件,能够运行多种语言 ...

  10. 力扣(LeetCode) 263. 丑数

    编写一个程序判断给定的数是否为丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例 1: 输入: 6 输出: true 解释: 6 = 2 × 3 示例 2: 输入: 8 输出: true ...