【线上事件】Kafka关于Topic和分区数量过多问题

2019-07-19某系统kafka集群宕机,重启失败

日志

 

网上相似问题描述https://javarevisited.blogspot.com/2014/11/javaioioexception-map-failed-javalangoutofmemoryerror.html 

 

kafka官网文档参考说明http://kafka.apache.org/documentation.html

打开网页搜索关键词:Map failed

参考翻译:

Maximum number of memory map areas a process may have (aka vm.max_map_count).
进程可以具有的最大内存映射区域数(也称为vm.max_map_count)。

See the Linux kernel documentation.
You should keep an eye at this OS-level property when considering the maximum number of partitions a broker may have.
在考虑broker可能具有的最大分区数时,您应该关注此OS级属性

By default, on a number of Linux systems, the value of vm.max_map_count is somewhere around 65535.
Linux 系统 vm.max_map_count 的默认值是 65535

Each log segment, allocated per partition, requires a pair of index/timeindex files, and each of these files consumes 1 map area.
每个分区分配的每个日志段需要一对index / timeindex文件,每个文件占用1个映射区域

In other words, each log segment uses 2 map areas.
换句话说,每个日志段使用2个映射区域

Thus, each partition requires minimum 2 map areas, as long as it hosts a single log segment.
因此,每个分区至少需要2个映射区域,只要它承载单个日志段即可。

That is to say, creating 50000 partitions on a broker will result allocation of 100000 map areas
and likely cause broker crash with OutOfMemoryError (Map failed) on a system with default vm.max_map_count.
举个例子,如果你创建 50000 分区在一个 broker,将会创建 100000 个map areas 映射取;
在具有默认vm.max_map_count的系统上可能导致代理崩溃并出现OutOfMemoryError(映射失败)

Keep in mind that the number of log segments per partition varies depending on the segment size,
load intensity, retention policy and, generally, tends to be more than one.
请记住,每个分区的日志段数取决于段大小,负载强度,保留策略,通常往往不止一个

 

问题总结

  1. broker是运行在JVM上,在操作系统上作为一个进程存在,进程是操作系统的资源分配的最小单位(冯诺依曼计算机模型),每个进程需要分配内存映射区资源,内存映射区资源和物理文件资源做映射(操作系统的虚拟内存)。一句话描述就是一个进程的内存映射区资源是有限制的,受限制与OS的总数,OS默认是65535
  2.  Broker 在启动时会从磁盘上加载所有日志段信息到内存中,并创建相应的 LogSegment 对象实例,如果日志文件很多呢?那是不是磁盘IO会打爆?
  3. 在Kafka中日志文件的结构
    1. 一个topic有多一个分区
    2. 一个分区有多个副本
    3. 一个分区对应一个日志Log对象
    4. 一个日志Log对象对应一个物理文件目录
    5. Log对象对应的物理文件目录中有很多日志相关文件
    6. 一个Log对象对应多个LogSegment对象
    7. 一个LogSegment对象对应4个日志文件:包括消息日志文件(.log)、位移索引文件(.index)、时间戳索引文件(.timeindex)以及已中止(Aborted)事务的索引文件(.txnindex);LogSegment是一个抽象概念不是文件目录,该分区的所有文件都在Log对象对应的文件目录中
    8. 如果一个Broker部署在一台机器上,计算Broker需要的文件句柄=4*分区数*分区的副本数据(有可能一个Broker中有个分区的多个副本)*topic数量
  4. 我们当时遇到的问题就是业务系统使用的Topic和分区数都很多,导致Broker扛不住宕机了,然后重启,重启的时候因为Topic和分区数太多,直接内存Map failed失败,启都启来
  5. 生产环境集群实例起不来这个是多么恐怖的事情,当时用了一个备用集群切换过去先把业务跑起来
  6. 此问题的其它解决方法思考:
    1. 如果日志文件的数据是允许丢失的,那么可以删除一些文件,大批量删除文件IO直接就满了,影响机器上其它服务
    2. 如果可以修改系统的句柄参数,那么把他调大重启,物理机器上不止一个服务,生产环境重启肯定不行
    3. 长期方案就是业务使用方修改使用topic的方式
    4. 其它。。。。未完待续

 

参考附录

vm.max_map_count参数说明:https://www.cnblogs.com/duanxz/p/3567068.html

关于 ulimit 和文件句柄数量限制:https://blog.cookwhy.com/articles/ulimit-file-handles.html

举个例子,如果创建 50000 分区在一个 broker,将会创建 100000 个map areas 映射取;
在具有默认vm.max_map_count的系统上可能导致代理崩溃并出现OutOfMemoryError(映射失败)。
此次事件由于kafka的索引文件内存映射数量已经超过系统默认的65535,导致kafka crash

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值