kafka运维
来源:互联网 发布:找出数组中重复的元素 编辑:程序博客网 时间:2024/06/10 05:42
Kafka 运维手册
编制
架构设计部 伍超
审核
批准
1.编写说明
以下是LinkedIn在生产中使用kafka集群的一些经验和信息,基于kafka0.9.0版本官方文档翻译。;
2.基本运维
这个章节将说明在运维kafka集群时最常见的操作,所提到的工具都位于kafka安装路径下的bin/目录,每个工具会打印详细使用信息如果没有指定参数。
2.1新增/删除topics
你可以手动新增或利用程序自动创建不存在的topics,如果是自动创建,你可以在broker配置文件server.properties里调整topic的相关默认参数。
通过工具新增或修改topics:
>bin/kafka-topics.sh --zookeeper zkhost:port --create --topic topicname --partitions 6 --replication-factor 3 --config x=y
参数replication-factor控制写入的信息会复制到多少个broker中。如果该参数设置为3,在可以正常访问数据的前提下将允许最多2个broker挂掉。通常建议使用2或3副本,这样可以提高系统的可用性。
参数partitions控制topic可以划分为多少个分区,每个分区只对应一个broker,分区的个数也影响着可以同时进行消费的消费者个数,每个分区只能被同一个消费者组内的其中一个消费者消费,但可以被不同消费者组内的消费者同时消费。
工具指定的配置参数在运行时会覆盖配置文件里对应的配置参数。
2.2修改topics
你可以通过工具修改一个topic的配置或分区数量。
新增分区数量:
>bin/kafka-topics.sh –zookeeper zkhost:port –alter –topic topicname –partitions 6
注意partition作用之一是划分数据,新增partitions不会改变集群中已经存在的数据的原有分区。也就是如果数据以hash(key)%number-of-partitions的方式分配,那新收到的数据可能会被分配到新的分区,但kafka不会自动重新分配已存在的数据。
新增配置
>bin/kafka-topics.sh –zookeeper zkhost:port –alter –topic topicname –config x=y
移除配置
>bin/kafka-topics.sh –zookeeper zkhost:port –alter –topic topicname –delete-config x
最后删除topic
>bin/kafka-topics.sh –zookeeper zkhost:port –delete –topic topicname
Topic删除选项默认是关闭的,通过设置broker配置参数delete.topic.enable=true来开启
Kafka目前还不支持削减topic的partitions的数目。
2.3优雅的关闭
Kafka集群会自动检测是否有broker宕机或服务挂了,并为相关的partitions选取新的leader。Kafka支持一种更优雅的关闭服务机制而不是强制杀死它。当服务优雅的关闭时会有两个好处:
1. 首先,它会同步所有的数据到磁盘而不需要再重启的时候去恢复数据,数据恢复会耗费更多的时间;
2. 其次,他会在服务关闭前将leader partitions迁移到其他副本。这样使leader partitions选取的更快从而减小了partition不可用的时间。
当服务停止而不是强制杀死服务的时候,自动同步数据到磁盘会自动进行,但是leader的迁移需要broker做如下配置:controlled.shutdown.enable=true。
注意,优雅关闭的前提是每个partition在其他broker上有存活的副本,也就是说副本数要大于1并最少有1个副本是存活的。
2.4均衡leader
当一个broker停止或异常挂了,都会导致该broker上的leaderpartition迁移到其他的副本上。这意味着当该broker重启后,它的partitions会全部成为follwer,意味着它不会被客户端读写,从而造成每个broker负载不均衡。
避免这种不均衡情况,kafka有个preferred 副本概念,如果一个partition的副本列表为{1,5,9},那么1将成为leader,意味它是副本列表的第一个。服务停止的broker在恢复之后,你可以使该broker原来的partition重新成为leader,通过以下命令可以实现:
>bin/kafka-preferred-replica-election.sh –zookeeper zkhost:port
如果你不想每次通过命令来做这种均衡,你可以通过配置kafka来自动完成这个过程,配置如下:auto.leader.rebalance.enable=true。由后台线程定期触发这种leader均衡操作。
2.5集群之间的数据复制
这里指的是不同集群之间的数据复制,而不是单个集群之间节点之间的数据复制,Kafka提供了这样一个工具来完成这种功能。这个工具从源集群读取数据并写入到目标集群当中,如下所示:
常见的使用场景比如将数据复制到另一个数据中心。你可以同时运行多个镜像实例来增加吞吐和提升容错能力(如果一个实例挂了,其它的实例会分担这份额外的负载)。
数据会从源集群的topics读取并写入到目的集群中同名的topic,事实上mirror maker就像kafka的消费者和生产者的结合。源集群和目的集群是完全独立的实体:它们有不同的partitions数目,并且offsets也不尽相同。因此,镜像集群不是一种容错机制。
这个例子展示怎么在两个集群之间复制一个topic:
>bin/kafka-mirror-maker.sh –consumer.conf consumer-1.properties –consumer.config consumer-2.properties –producer.conf producer.properties –whitelist topicname
注意,我们通过--whitelist选项指定要复制topics列表,也可以通过--blacklist选项排除不想复制的topics,这两个选项都支持正则表达式。
配置auto.create.topics.enable=true可以使复制集群能够自动创建topics并从源集群复制数据。
2.6查看消费者消费进度
有时,查看消费者的消费进度很有必要。Kafka提供了一个工具来完成这一工作:
>bin/kafka-consumer-offset-checker.sh –zookeeper zkhost:port –group groupname
2.7集群节点扩容
向kafka集群新增节点很容易,只要分配一个唯一brokerID并启动服务即可。但是这些新增的节点并不会自动被分配任何partitions,所以除非partitions被移动到节点上,否则它们不会处理任何工作直到有新的topics被创建。所以,通常在新增了节点到集群之中以后,我们会希望把已存在的数据迁移到这些节点上。
数据的迁移过程需要手动触发但自动完成,kafka会将新增的节点上的partitions作为follwer,follwer partitions会从leader partitions自动拉取数据,当新增节点上的partitions充分复制所有数据后会加入到ISR列表中。
Partition分配工具能够在brokers之间移动partitions。理想的partition分配是保证所有的broker拥有相同的partition数目和数据负载,这个partition分配工具不会自动分配partitions以使各broker负载均衡,使用者需要指出哪些topics或partitions需要移动。
Partition迁移工具能够以3种不同模式运行:
l --generate:这种模式下,提供topics列表和brokers列表,会生成将指定的topics上的partitions分配到新的broker上的分配方案。这个选项仅仅生成一个参考的分配方案。
l --execute:这种模式下,会执行指定的方案完成分配任务,通过--reassignment-json-file选项指定,可以自定义分配方案或通过--generate生成。
l --verify:这种模式下,会检验执行—execute之后的分配状况
下面的例子,会将topicsfoo1,foo2上所有的paritions移动到新的broker5和6中,最终foo1和foo2上所有的partitions只存在于brokers5,6上。该工具需要编辑json文件来输入topics信息,例如:
>cat topic-to-move.json
{“topics”:[{“topic”: ”foo1”},
{“topic”: ”foo2”}],
“version”:1
}
如果json文件已编辑好,可以先生成推荐分配方案:
>bin/kafka-reassign-partitions.sh –zookeeper zkhost:port –topics-to-move-json-file topics-to-move.json –broker-list “5,6” –generate
执行该命令之后会生成推荐分配策略,到目前为止,partition还没有开始迁移,仅仅只是告诉我们推荐的分配方案。最好将该分配方案保存下来,如果后面想回滚可以有依据。比如新的分配方案保存的json文件为expand-cluster-reassignment.json,执行该方案如下所示:
>bin/kafka-reassign-partitions.sh –zookeeper zkhost:port –reassignment-json-file expand-cluster-reassignment.json --execute
最后,--verify选项可以检测partition分配状态:
>bin/kafka-reassign-partitions.sh –zookeeper zkhost:port –reassignment-json-file expand-cluster-reassignment.json --verify
通常我们需要自定义分配策略,这就需要我们自己编辑json文件了。比如,我们想把foo1这个topic上的partition 0移动到broker5和6,把foo2的partition 1移动到broker2和3,自定义的分配方案可以如下编辑:
>cat custom-reassignment.json
{
“version”:1,
“partitions”:[{“topic”:”foo1”,”partition”:0,”replicas”:[5,6]},
{“topic”:”foo2”,”partition”:1,“replicas”:[2,3]}]
}
2.8集群节点缩容
集群缩容同样也是使用kafka-reassign-partitions.sh工具进行。比如将broker1从集群移除:
首先,编辑分配方案,将broker1上的parition迁移分配到其他broker上;然后通过工具执行方案完成分配;分配确认成功后,再将broker1下线完成集群缩容。
2.9增加副本数
为现有的partition增加副本数很简单,只需在自定义分配方案中指定新增的副本,然后执行方案即可。
比如,将foo的partition 0从副本数为1增加到3,在增加副本之前,该partition的副本只存在于broker5上,现在我们将新增的副本分布在broker6和7上:
>cat increase-replication-factor.json
{
“version”:1,
“partitions”:[{“topic”:”foo”, “partition”:0, “replicas”:[5,6,7]}]
}
2.10设置配额
可以通过broker的配置文件为每个client-ids设置配额。默认情况下,每个client-id配额没有限制,以下设置可以为每个生产者和消费者设置配额10MB/sec:
quota.producer.default=10485760
quota.consumer.default=10485760
也可以为每个客户端设置自定义配额:
>bin/kafka-configs.sh –zookeeper zkhost:port –alter –add-config “producer_byte_rate=1024,consumer_byte_rate=2048” –entity-name clientA –entity-type clients
可以查看指定的客户端的配额信息:
>bin/kafka-configs.sh –zookeeper zkhost:port –describe –entity-name clientA –entity-type clients
3.Kafka配置
3.1客户端重要配置
生产者最重要的配置:
l 压缩方式
l 同步vs异步
l Batch size批量传输大小(针对异步生产者)
消费者最重要的配置是fetch size.
3.2生产环境配置
这有linkedin其中一个生产环境上的配置:
#Replication configurations
num.replica.fetchers=4
replica.fetch.max.bytes=1048576
replica.fetch.wait.max.ms=500
replica.high.watermark.checkpoint.interval.ms=5000
replica.socket.timeout.ms=30000
replica.socket.receive.buffer.bytes=65536
replica.lag.time.max.ms=10000
controller.socket.timeout.ms=30000
controller.message.queue.size=10
#Log configuration
num.partitions=8
message.max.bytes=1000000
auto.create.topics.enable=true
log.index.interval.bytes=4096
log.index.size.max.bytes=10485760
log.retention.hours=168
log.flush.interval.ms=10000
log.flush.interval.messages=20000
log.flush.scheduler.interval.ms=2000
log.roll.hours=168
log.retention.check.interval.ms=300000
log.segment.bytes=1073741824
#ZK configuration
zookeeper.connection.timeout.ms=6000
zookeeper.sync.time.ms=2000
#Socket server configuration
num.io.threads=8
num.network.threads=8
socket.request.max.bytes=104857600
socket.receive.buffer.bytes=1048576
socket.send.buffer.bytes=1048576
queued.max.requests=16
fetch.purgatory.purge.interval.requests=100
producer.purgatory.purge.interval.requests=100
3.3Java版本
为了安全起见,推荐使用最新发布的JDK1.8,LinkedIn尝试使用JDK 1.8 u21测试,但这个版本的GC实现有一些问题,LinkedIn调优如下:
-Xmx6g –Xms6g –XX:MetaspaceSize=96m –XX:+UseG1GC –XX:MaxGCPauseMillis=20 –XX:InitiatingHeapOccupancyPercent=35 –XX:G1HeapRegionSize-16M –XX:MinMetaspaceFreeRatio=50 –XX:MaxMetaspaceFreeRatio=80
作为参考,这有LinkedIn最繁忙的集群的一些数据:60broker-50kpartitions(2副本)-800k msg/s in-300MB/s inbound,1GB/s+ outbound。这个调优看起来效果非常好,但是集群内所有的brokers有90%的GC暂停时间,大约21ms,并且yong GC少于每秒1次。
G1垃圾回收期的适用场景:
l JVM占用内存较大(至少4G)
l 应用本身频繁申请、释放内存,进而产生大量内存碎片时
l 对于GC时间较为敏感的应用
4.硬件和系统
LinkedIn使用双4核心Intel Xeon,24GB内存的机器。
Kafka需要充足的内存去缓存活跃的读写内容。可以大约估算一下需要的内存,假设需要缓存30秒,那么用write_throughput*30来计算所需的内存大小。
磁盘吞吐非常重要,LinkedIn使用8*7200 rpmSATA磁盘。通常磁盘吞吐是性能瓶颈,盘越多越好。这取决于你如何配置刷盘策略,否则也无法在昂贵的磁盘中受益。如果配置的刷盘频率越高,那么配置更高RPM的SAS磁盘会更好。
4.1操作系统
Kafka在任何unix系统都能运行良好,在windows上运行的情况较少并且对windows平台支持的并不是很好。
也许并不需要做太多的OS级调整,但有两个配置非常重要,有助于性能的提高:
l 调大文件描述符数量
l 调大socket缓冲区大小
4.2磁盘和文件系统
推荐使用多磁盘来获取更好的吞吐性能,使用独立的磁盘来存储kafka的数据。如果配置了多个数据目录,partitions会轮流分布到各个数据目录,每个partition对应一个数据目录。如果数据没有均匀的到各个paritions会导致每个磁盘的负责不均衡。当然,也可以考虑RAID。
4.3数据flush
Kafka总是立即将所有数据写入文件系统,并可以通过配置控制操作系统缓存中的数据写磁盘的策略。可以通过时间和消息数量来控制刷盘的频率。
Kafka必须调用fsync来确保数据被刷入磁盘,当从故障的log segment恢复数据的时候会通过CRC校验每个消息的正确性并重建索引文件。注意,kafka的持久性不要求同步数据到磁盘,因为失败的节点总会从其他副本恢复数据。
推荐使用默认刷盘设置,即完全禁用fsync,依赖OS的刷盘策略和kafka的后台刷盘策略,在性能和可用性上都具有良好的保证。通常感觉副本提供的保证更胜于fsync刷盘策略,然而偏执狂仍然青睐在应用中使用fsync策略。
使用应用级别的刷盘策略的缺点是磁盘使用模式效率较低(它给操作系统减少了重新排序写操作的余地),并且可能引入延迟,因为fsync在大多linux文件系统中阻塞写入,而后台刷盘能进行更细粒度的page级的锁定。
在linux中,数据写入文件系统都是保存在页缓存中直到被写入磁盘(应用程序层面的fsync或操作系统自己的flush策略)。数据的刷盘是由一组叫做pdflush或“flusher threads”的后台线程来执行。当脏页占系统内存的比例超过阈值时,write系统调用会唤醒pdflush回写脏页,直到低于阈值。
使用页缓存的几个好处是:
l IO调度器会批量合并小IO,以提升吞吐
l IO调度器会对写入排序,较少磁盘头的转动,这样可以提升吞吐
l 可以充分利用机器的所有剩余内存
4.4Ext4注意事项
Ext4也许不是kafka最佳文件系统,也许XFS文件系统能更好的处理fsync导致的阻塞情况,LinkedIn只试过Ext4。
以下的设置回优化kafka在Ext4文件系统的性能:
n data=writeback:Ext4默认data=ordered,会先记录metadata的journal,然后依次是data和metadata落盘;而data=writeback不强制要求这种写入顺序,仅要求metadata journal和metadata依次落盘,不确保data比metadata先落盘;由于kafka自身具有很强的数据恢复能力,所以不要求这种强制写入顺序,从而可以减少写入延迟。
n 禁用journaling:这回导致系统reboot时间变长,但是会减少一些额外的写入操作,从而提升写入性能。
n commit=num_secs:调整ext4提交metadata的频率。设置小的值会减少crash时数据的丢失;设置大的值会提升吞吐。
n nobh:当我们用data=writeback模式时,这会缓存磁盘block映射信息并将pages和事务关联起来以提供一些额外的顺序保证,从而弥补不足,同时拥有良好的性能和较低的延迟。
n delalloc:延迟分配意味着文件系统避免分配块直到有物理写入才分配。Ext4分配一个大的extent来替代小的pages,这个特性有助于提升吞吐,但貌似会增加一些延迟。
5.zookeeper
5.1稳定版本
在LinkedIn,我们运行的是Zookeeper3.3.*。3.3.3版本在临时接待删除和session过期方面有严重问题,并在生产中踩过坑,后来LinkedIn升级到了3.3.4版本并已经稳定的运行了一年。
5.2优化zookeeper
Ø 在硬件、网络等层面做到冗余,比如不要放到同一个机架,冗余电源和网络等等。
Ø IO隔离,比如事务日志和数据分别写入到不同的磁盘上。
Ø 应用隔离,最好将zookeeper单独部署,减少其他应用的影响。
Ø 小心使用虚拟化,这会不必要的引入虚拟化层面的影响。
Ø Zookeeper配置和监控:确保给予足够的堆空间,因为它是java的。监控方面JMX和4字命令很管用。
Ø 集群节点不要太多,最好是3-5个节点的集群。
- [Apache Kafka]Kafka运维
- kafka运维
- kafka学习七:kafka 运维
- Kafka
- kafka
- kafka
- KAFKA
- Kafka
- kafka
- kafka
- kafka
- kafka
- Kafka
- kafka
- Kafka
- Kafka
- Kafka
- kafka
- 初见Java之HelloWorld
- 关闭windows10动画效果提升计算机性能
- 565. Array Nesting
- ES6学习2章:let和const命令
- Python is同一性运算符和==相等运算符区别
- kafka运维
- 再谈同步、异步、阻塞、非阻塞
- libc-bin (2.23-0ubuntu9) 的触发器 ... 在处理时有错误发生: rsync E: Sub-process /usr/bin/dpkg returned an error c
- 采用JavaScript、AngularJS实现过滤器搜索、删除、添加、排序、常用过滤器
- 【迷你兔分享】数据恢复中的可逆与不可逆操作
- Java设计模式--工厂模式
- H5游戏开发引擎的基本使用
- Java枚举
- U3d [SerializeField]介绍