kafka 磁盘写满导致 InternalError

tailf kafka/log/server.log

[2019-12-19 17:19:05,121] FATAL (main kafka.server.KafkaServerStartable 116) Fatal error during KafkaServerStartable startup. Prepare to shutdown
java.lang.InternalError: a fault occurred in a recent unsafe memory access operation in compiled Java code
        at kafka.log.FileMessageSet$$anon$1.makeNext(FileMessageSet.scala:264)
        at kafka.log.FileMessageSet$$anon$1.makeNext(FileMessageSet.scala:251)
        at kafka.utils.IteratorTemplate.maybeComputeNext(IteratorTemplate.scala:64)
        at kafka.utils.IteratorTemplate.hasNext(IteratorTemplate.scala:56)
        at kafka.log.LogSegment.recover(LogSegment.scala:179)
        at kafka.log.Log$$anonfun$loadSegments$4.apply(Log.scala:199)
        at kafka.log.Log$$anonfun$loadSegments$4.apply(Log.scala:171)
        at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:733)
        at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
        at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
        at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:732)
        at kafka.log.Log.loadSegments(Log.scala:171)
        at kafka.log.Log.<init>(Log.scala:101)
        at kafka.log.LogManager$$anonfun$loadLogs$2$$anonfun$3$$anonfun$apply$10$$anonfun$apply$1.apply$mcV$sp(LogManager.scala:152)
        at kafka.utils.CoreUtils$$anon$1.run(CoreUtils.scala:56)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

看日志查询资料发现是磁盘满了。

[kafka@datanode15 kafka]$ du -sh /data11/kafka/
3.4T    /data11/kafka/
[kafka@ngsoc15 kafka]$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        126G     0  126G   0% /dev
/dev/sda2       880G   14G  823G   2% /
/dev/sda1       190M  126M   51M  72% /boot
/dev/sdj        3.6T  2.8T  618G  83% /data09
/dev/sdf        3.6T  2.0T  1.5T  59% /data05
/dev/sdd        3.6T  2.5T  954G  73% /data03
/dev/sdi        3.6T  1.7T  1.8T  50% /data08
/dev/sdk        3.6T  2.4T  1.1T  69% /data10
/dev/sde        3.6T  2.5T  986G  72% /data04
/dev/sdb        3.6T  1.1T  2.4T  32% /data01
/dev/sdg        3.6T  1.4T  2.1T  40% /data06
/dev/sdh        3.6T  2.5T  948G  73% /data07
/dev/sdl        3.6T  3.4T     0 100% /data11
/dev/sdm        3.6T  3.0T  473G  87% /data12
/dev/sdc        3.6T  2.3T  1.2T  66% /data02

解决思路:

{3节点*12盘=36 ; 36/2副本=18分区}

sh bin/kafka-topics.sh --zookeeper zookeeper.host:2181 --alter --topic flow_dns --partition 18

* 为什么不直接报IO异常,而是内部错误不安全的内存操作?-----来自网络描述

此错误表示或内存访问导致SIGBUS错误,然后被 JVM 捕获并转换为异步 。sun.misc.Unsafe.getX()putX()InternalError

更多细节:

sun.misc.Unsafe是 JDK 私有 API,允许直接从 Java 访问本机内存。此 API 是直接字节缓冲区的基础,特别是映射字节缓冲区的基础。
在某些情况下,对文件的内存映射区域的访问可能会导致 OS 级异常,即 。典型的示例包括:SIGBUS

在基础文件被截断后,将访问内存映射缓冲区。
网络驱动器上的文件已映射到内存,并且在网络连接断开后访问映射的缓冲区。
尝试写入映射到文件系统上的文件的页面会导致内存不足(默认情况下,空间受总 RAM 的 50% 限制)。tmpfstmpfs
热点 JVM 无法提前有效地检测这些问题。它编译对简单内存访问指令的调用。查看内存区域是否有效的其他检查将过于昂贵。Unsafe.getX / putX

相反,JVM 处理信号。如果它看到调用中发生了错误,它将发布到当前线程并继续执行。SIGBUGUnsafeInternalError
IOException更合适,但 JVM 不能引发它或任何其他异常,因为公共协定不允许其方法引发任何异常。ByteBufferget/put
如果 JIT 编译方法中的内存访问失败,JVM 不会立即引发异常(同样,对于此类热字节缓冲区 API 来说,这太贵了)。相反,它将异步发布到当前线程。这意味着错误实际上将扔到最近的本机方法或最接近 VM 运行时的调用处。因此,错误消息中的"最近"一词。UnsafeInternalError

参考:

https://zh.wikipedia.org/wiki/%E6%80%BB%E7%BA%BF%E9%94%99%E8%AF%AF

https://bugs.openjdk.java.net/browse/JDK-4454115

原文地址:https://www.cnblogs.com/shwang/p/12069108.html