﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-给工作生活留点痕迹(haoxuewu)-文章分类-kafka</title><link>http://www.blogjava.net/haoxuewu/category/54109.html</link><description>路漫漫其修远兮，吾将上下而求索</description><language>zh-cn</language><lastBuildDate>Tue, 28 Jan 2014 12:09:14 GMT</lastBuildDate><pubDate>Tue, 28 Jan 2014 12:09:14 GMT</pubDate><ttl>60</ttl><item><title>kafka配置举例</title><link>http://www.blogjava.net/haoxuewu/articles/408677.html</link><dc:creator>陕西BOY</dc:creator><author>陕西BOY</author><pubDate>Wed, 08 Jan 2014 04:08:00 GMT</pubDate><guid>http://www.blogjava.net/haoxuewu/articles/408677.html</guid><wfw:comment>http://www.blogjava.net/haoxuewu/comments/408677.html</wfw:comment><comments>http://www.blogjava.net/haoxuewu/articles/408677.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haoxuewu/comments/commentRss/408677.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haoxuewu/services/trackbacks/408677.html</trackback:ping><description><![CDATA[<div>##broker标识,id为正数,且全局不得重复. &nbsp;</div><div>broker.id=0</div><div>##日志文件保存的目录 &nbsp;推荐放到存储大的盘目录</div><div>log.dirs=/opt/kafkadata/logs &nbsp;</div><div>##broker需要使用zookeeper保存meata信息,因此broker为zk &nbsp;</div><div>##此处为zookeeper集群的connectString,后面可以跟上path</div><div>##不过需要注意,path的全路径需要有自己来创建(使用zookeeper脚本工具) &nbsp;</div><div>zookeeper.connect=hostname1:port1,hostname2:port2/kafka &nbsp;</div><div>##用来侦听链接的端口,prudcer或consumer将在此端口建立链接 &nbsp;</div><div>port=10000</div><div>##指定broker实例绑定的网络接口地址 &nbsp;</div><div>host.name=ip &nbsp;</div><div>##每个topic默认partition的个数,默认为1</div><div>num.partitions=2 &nbsp;</div><div>##日志文件中每个segment文件的尺寸,默认为1G &nbsp;</div><div>##log.segment.bytes=1024*1024*1024 &nbsp;</div><div>##滚动生成新的segment文件的最大时间 &nbsp;</div><div>##log.roll.hours=24*7 &nbsp;</div><div>##segment文件保留的最长时间,超时将被删除 &nbsp;</div><div>##log.retention.hours=24*7 &nbsp;</div><div>##partiton中buffer中,消息的条数,达到阀值,将触发flush到磁盘. &nbsp;</div><div>log.flush.interval.messages=30000 &nbsp;</div><div>#消息buffer的时间,达到阀值,将触发flush到磁盘. &nbsp;</div><div>log.flush.interval.ms=5000 &nbsp;</div><div>##partition leader等待follower同步消息的最大时间, &nbsp;</div><div>##如果超时,leader将follower移除同步列表 &nbsp;</div><div>replica.lag.time.max.ms=10000 &nbsp;</div><div>##消息的备份的个数,默认为1,通常使用在replication-cluster环境中 &nbsp;</div><div>##kafka-cluster已经具备自动故障转移能力(&gt;0.8V) &nbsp;</div><div>num.replica.fetchers=1</div><img src ="http://www.blogjava.net/haoxuewu/aggbug/408677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haoxuewu/" target="_blank">陕西BOY</a> 2014-01-08 12:08 <a href="http://www.blogjava.net/haoxuewu/articles/408677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>kafka设计理论备忘</title><link>http://www.blogjava.net/haoxuewu/articles/408676.html</link><dc:creator>陕西BOY</dc:creator><author>陕西BOY</author><pubDate>Wed, 08 Jan 2014 04:01:00 GMT</pubDate><guid>http://www.blogjava.net/haoxuewu/articles/408676.html</guid><wfw:comment>http://www.blogjava.net/haoxuewu/comments/408676.html</wfw:comment><comments>http://www.blogjava.net/haoxuewu/articles/408676.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haoxuewu/comments/commentRss/408676.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haoxuewu/services/trackbacks/408676.html</trackback:ping><description><![CDATA[<p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">kafka的设计初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息,并需要能够支撑较大的数据量,且具备良好的容错能力.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>1.Persistence</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka使用文件存储消息,这就直接决定kafka在性能上严重依赖文件系统的本身特性.且无论任何OS下,对文件系统本身的优化几乎没有可能.文件缓存/直接内存映射等是常用的手段.因为kafka是对日志文件进行append操作,因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO调用的次数.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>2.Efficiency</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 需要考虑的影响性能点很多,除磁盘IO之外,我们还需要考虑网络IO,这直接关系到kafka的吞吐量问题.kafka并没有提供太多高超的技巧;对于producer端,可以将消息buffer起来,当消息的条数达到一定阀值时,批量发送给broker;对于consumer端也是一样,批量fetch多条消息.不过消息量的大小可以通过配置文件来指定.对于kafka broker端,似乎有个sendfile系统调用可以潜在的提升网络IO的性能:将文件的数据映射到系统内存中,socket直接读取相应的内存区域即可,而无需进程再次copy和交换.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 其实对于producer/consumer/broker三者而言,CPU的开支应该都不大,因此启用消息压缩机制是一个良好的策略;压缩需要消耗少量的CPU资源,不过对于kafka而言,网络IO更应该需要考虑.可以将任何在网络上传输的消息都经过压缩.kafka支持gzip/snappy等多种压缩方式.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>3. Producer</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Load balancing:</strong>&nbsp;producer将会和Topic下所有partition leader保持socket连接;消息由producer直接通过socket发送到broker,中间不会经过任何"路由层".事实上,消息被路由到哪个partition上,有producer客户端决定.比如可以采用"random""key-hash""轮询"等,如果一个topic中有多个partitions,那么在producer端实现"消息均衡分发"是必要的.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 其中partition leader的位置(host:port)注册在zookeeper中,producer作为zookeeper client,已经注册了watch用来监听partition leader的变更事件.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Asynchronous send:</strong>&nbsp;将多条消息暂且在客户端buffer起来,并将他们批量发送到broker;小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率;不过这也有一定的隐患,比如当producer失效时,那些尚未发送的消息将会丢失.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>4.Consumer</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; consumer端向broker发送"fetch"请求,并告知其获取消息的offset;此后consumer将会获得一定条数的消息;consumer端也可以重置offset来重新消费消息.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 在JMS实现中,Topic模型基于push方式,即broker将消息推送给consumer端.不过在kafka中,采用了pull方式,即consumer在和broker建立连接之后,主动去pull(或者说fetch)消息;这中模式有些优点,首先consumer端可以根据自己的消费能力适时的去fetch消息并处理,且可以控制消息消费的进度(offset);此外,消费者可以良好的控制消息消费的数量,batch fetch.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 其他JMS实现,消息消费的位置是有prodiver保留,以便避免重复发送消息或者将没有消费成功的消息重发等,同时还要控制消息的状态.这就要求JMS broker需要太多额外的工作.在kafka中,partition中的消息只有一个consumer在消费,且不存在消息状态的控制,也没有复杂的消息确认机制,可见kafka broker端是相当轻量级的.当消息被consumer接收之后,consumer可以在本地保存最后消息的offset,并间歇性的向zookeeper注册offset.由此可见,consumer客户端也很轻量级.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>5.Message Delivery Semantics</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 对于JMS实现,消息传输担保非常直接:有且只有一次(exactly once).在kafka中稍有不同:</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 1) at most once: 最多一次,这个和JMS中"非持久化"消息类似.发送一次,无论成败,将不会重发.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 2) at least once: 消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 3) exactly once: 消息只会发送一次.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; at most once: 消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理.那么此后"未处理"的消息将不能被fetch到,这就是"at most once".</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; at least once: 消费者fetch消息,然后处理消息,然后保存offset.如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是"at least once".</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; exactly once: kafka中并没有严格的去实现(基于2阶段提交,事务),我们认为这种策略在kafka中是没有必要的.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 通常情况下"at-least-once"是我们搜选.(相比at most once而言,重复接收数据总比丢失数据要好).</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>6. Replication</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka将每个partition数据复制到多个server上,任何一个partition有一个leader和多个follower(可以没有);备份的个数可以通过broker配置文件来设定.leader处理所有的read-write请求,follower需要和leader保持同步.Follower和consumer一样,消费消息并保存在本地日志中;leader负责跟踪所有的follower状态,如果follower"落后"太多或者失效,leader将会把它从replicas同步列表中删除.当所有的follower都将一条消息保存成功,此消息才被认为是"committed",那么此时consumer才能消费它.即使只有一个replicas实例存活,仍然可以保证消息的正常发送和接收,只要zookeeper集群存活即可.(不同于其他分布式存储,比如hbase需要"多数派"存活才行)</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 当leader失效时,需在followers中选取出新的leader,可能此时follower落后于leader,因此需要选择一个"up-to-date"的follower.选择follower时需要兼顾一个问题,就是新leader server上所已经承载的partition leader的个数,如果一个server上有过多的partition leader,意味着此server将承受着更多的IO压力.在选举新leader,需要考虑到"负载均衡".</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>7.Log</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 如果一个topic的名称为"my_topic",它有2个partitions,那么日志将会保存在my_topic_0和my_topic_1两个目录中;日志文件中保存了一序列"log entries"(日志条目),每个log entry格式为"4个字节的数字N表示消息的长度" + "N个字节的消息内容";每个日志都有一个offset来唯一的标记一条消息,offset的值为8个字节的数字,表示此消息在此partition中所处的起始位置..每个partition在物理存储层面,有多个log file组成(称为segment).segment file的命名为"最小offset".kafka.例如"00000000000.kafka";其中"最小offset"表示此segment中起始消息的offset.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;"><br /><img alt="" src="http://dl2.iteye.com/upload/attachment/0088/5864/7fdfd8ce-4225-3f73-86b0-3bbd5900ff60.png" style="border: 0px;" /><br />(摘自官网)&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 其中每个partiton中所持有的segments列表信息会存储在zookeeper中.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 当segment文件尺寸达到一定阀值时(可以通过配置文件设定,默认1G),将会创建一个新的文件;当buffer中消息的条数达到阀值时将会触发日志信息flush到日志文件中,同时如果"距离最近一次flush的时间差"达到阀值时,也会触发flush到日志文件.如果broker失效,极有可能会丢失那些尚未flush到文件的消息.因为server意外实现,仍然会导致log文件格式的破坏(文件尾部),那么就要求当server启东是需要检测最后一个segment的文件结构是否合法并进行必要的修复.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 获取消息时,需要指定offset和最大chunk尺寸,offset用来表示消息的起始位置,chunk size用来表示最大获取消息的总长度(间接的表示消息的条数).根据offset,可以找到此消息所在segment文件,然后根据segment的最小offset取差值,得到它在file中的相对位置,直接读取输出即可.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 日志文件的删除策略非常简单:启动一个后台线程定期扫描log file列表,把保存时间超过阀值的文件直接删除(根据文件的创建时间).为了避免删除文件时仍然有read操作(consumer消费),采取copy-on-write方式.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>8.Distribution</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka使用zookeeper来存储一些meta信息,并使用了zookeeper watch机制来发现meta信息的变更并作出相应的动作(比如consumer失效,触发负载均衡等)</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<em>1) Broker node registry:</em>&nbsp;当一个kafka broker启动后,首先会向zookeeper注册自己的节点信息(临时znode),同时当broker和zookeeper断开连接时,此znode也会被删除.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 格式: /broker/ids/[0...N] &nbsp; --&gt;host:port;其中[0..N]表示broker id,每个broker的配置文件中都需要指定一个数字类型的id(全局不可重复),znode的值为此broker的host:port信息.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<em>2) Broker Topic Registry:</em>&nbsp;当一个broker启动时,会向zookeeper注册自己持有的topic和partitions信息,仍然是一个临时znode.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 格式: /broker/topics/[topic]/[0...N] &nbsp;其中[0..N]表示partition索引号.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<em>3) Consumer and Consumer group:</em>&nbsp;每个consumer客户端被创建时,会向zookeeper注册自己的信息;此作用主要是为了"负载均衡".</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 一个group中的多个consumer可以交错的消费一个topic的所有partitions;简而言之,保证此topic的所有partitions都能被此group所消费,且消费时为了性能考虑,让partition相对均衡的分散到每个consumer上.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<em>4) Consumer id Registry:</em>&nbsp;每个consumer都有一个唯一的ID(host:uuid,可以通过配置文件指定,也可以由系统生成),此id用来标记消费者信息.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 格式: /consumers/[group_id]/ids/[consumer_id]</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 仍然是一个临时的znode,此节点的值为{"topic_name":#streams...},即表示此consumer目前所消费的topic + partitions列表.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<em>5) Consumer offset Tracking:</em>&nbsp;用来跟踪每个consumer目前所消费的partition中最大的offset.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 格式: /consumers/[group_id]/offsets/[topic]/[broker_id-partition_id] &nbsp; --&gt;offset_value</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 此znode为持久节点,可以看出offset跟group_id有关,以表明当group中一个消费者失效,其他consumer可以继续消费.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<em>6) Partition Owner registry:</em>&nbsp;用来标记partition被哪个consumer消费.临时znode</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 格式:&nbsp;/consumers/[group_id]/owners/[topic]/[broker_id-partition_id] &nbsp; --&gt;consumer_node_id</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 当consumer启动时,所触发的操作:</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; A) 首先进行"Consumer id Registry";</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; B) 然后在"Consumer id Registry"节点下注册一个watch用来监听当前group中其他consumer的"leave"和"join";只要此znode path下节点列表变更,都会触发此group下consumer的负载均衡.(比如一个consumer失效,那么其他consumer接管partitions).</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; C) 在"Broker id registry"节点下,注册一个watch用来监听broker的存活情况;如果broker列表变更,将会触发所有的groups下的consumer重新balance.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;"><br /><img alt="" src="http://dl2.iteye.com/upload/attachment/0088/5886/c762f4ef-ee37-3601-a4b9-c8b7accff305.jpeg" style="border: 0px;" /><br />&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 1) Producer端使用zookeeper用来"发现"broker列表,以及和Topic下每个partition leader建立socket连接并发送消息.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 2) Broker端使用zookeeper用来注册broker信息,已经监测partition leader存活性.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 3) Consumer端使用zookeeper用来注册consumer信息,其中包括consumer消费的partition列表等,同时也用来发现broker列表,并和partition leader建立socket连接,并获取消息.</p><img src ="http://www.blogjava.net/haoxuewu/aggbug/408676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haoxuewu/" target="_blank">陕西BOY</a> 2014-01-08 12:01 <a href="http://www.blogjava.net/haoxuewu/articles/408676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>kafka概念备忘</title><link>http://www.blogjava.net/haoxuewu/articles/408675.html</link><dc:creator>陕西BOY</dc:creator><author>陕西BOY</author><pubDate>Wed, 08 Jan 2014 03:58:00 GMT</pubDate><guid>http://www.blogjava.net/haoxuewu/articles/408675.html</guid><wfw:comment>http://www.blogjava.net/haoxuewu/comments/408675.html</wfw:comment><comments>http://www.blogjava.net/haoxuewu/articles/408675.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/haoxuewu/comments/commentRss/408675.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/haoxuewu/services/trackbacks/408675.html</trackback:ping><description><![CDATA[<p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">Kafka is a distributed, partitioned, replicated commit log service. 它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka对消息保存时根据Topic进行归类,发送消息者成为Producer,消息接收者成为Consumer;此外kafka集群有多个kafka实例组成,每个实例(server)称为broker.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性以及保存一些meta信息.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp;<br /><img alt="" src="http://dl2.iteye.com/upload/attachment/0088/5769/9392096f-4654-3665-8056-83b6077d7b08.png" style="border: 0px;" /><br />(摘自官网)&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Topics/logs</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 一个Topic可以认为是一类消息,每个topic将被分成多个partition(区),每个partition在存储层面是append log文件.任何发布到此partition的消息都会直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它唯一的标记一条消息.kafka并没有提供其他额外的索引机制来存储offset,因为在kafka中几乎不允许对消息进行"随机读-写".</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;"><br /><img alt="" src="http://dl2.iteye.com/upload/attachment/0088/5777/06074c05-468c-33e1-a027-052c8c867aa8.png" style="border: 0px;" /><br />(摘自官网)&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka和JMS实现(activeMQ)不同的是:即使消息被消费,消息仍然不会被立即删除.日志文件将会根据broker中的配置要求,保留一定的时间之后删除;比如log文件保留2天,那么两天后,文件会被清除,无论其中的消息是否被消费.kafka通过这种简单的手段,来释放磁盘空间,以及减少消息消费之后对文件内容改动的磁盘IO开支.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 对于consumer而言,它需要保存消费消息的offset,对于offset的保存和使用,有consumer来控制;当consumer正常消费消息时,offset将会"线性"的向前驱动,即消息将依次顺序被消费.事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值..(offset将会保存在zookeeper中,参见下文)</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka集群几乎不需要维护任何consumer和producer状态信息,这些信息有zookeeper保存;因此producer和consumer的客户端实现非常轻量级,它们可以随意离开,而不会对集群造成额外的影响.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; partitions的设计目的有多个.最根本原因是kafka基于文件存储.通过分区,可以将日志内容分散到多个server上,来避免文件尺寸达到单机磁盘的上限,每个partiton都会被当前server(kafka实例)保存;可以将一个topic切分多任意多个partitions,来消息保存/消费的效率.此外越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力.(具体原理参见下文).</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Distribution</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 一个Topic的多个partitions,被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 基于replicated方案,那么就意味着需要对多个备份进行调度;每个partition都有一个server为"leader";leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可..由此可见作为leader的server承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Producers</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息归属于哪个partition;比如基于"round-robin"方式或者通过其他的一些算法等.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Consumers</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 本质上kafka只支持Topic.每个consumer属于一个consumer group;反过来说,每个group中可以有多个consumer.发送到Topic的消息,只会被订阅此Topic的每个group中的一个consumer消费.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 如果所有的consumer都具有相同的group,这种情况和queue模式很像;消息将会在consumers之间负载均衡.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 如果所有的consumer都具有不同的group,那这就是"发布-订阅";消息将会广播给所有的消费者.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;"><br /><img alt="" src="http://dl2.iteye.com/upload/attachment/0088/5814/c8a693cb-165f-3f0e-aa54-792898b128f9.png" style="border: 0px;" /><br />(摘自官网)&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 在kafka中,一个partition中的消息只会被group中的一个consumer消费;每个group中consumer消息消费互相独立;我们可以认为一个group是一个"订阅"者,一个Topic中的每个partions,只会被一个"订阅者"中的一个consumer消费,不过一个consumer可以消费多个partitions中的消息.kafka只能保证一个partition中的消息被某个consumer消费时,消息是顺序的.事实上,从Topic角度来说,消息仍不是有序的.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp;&nbsp;<strong>Guarantees</strong></p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 1) 发送到partitions中的消息将会按照它接收的顺序追加到日志中</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 2) 对于消费者而言,它们消费消息的顺序和日志中消息顺序一致.</p><p style="margin: 0px; padding: 0px; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.1875px; background-color: #ffffff;">&nbsp; &nbsp; 3) 如果Topic的"replication factor"为N,那么允许N-1个kafka实例失效.</p><img src ="http://www.blogjava.net/haoxuewu/aggbug/408675.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/haoxuewu/" target="_blank">陕西BOY</a> 2014-01-08 11:58 <a href="http://www.blogjava.net/haoxuewu/articles/408675.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>