本文档适用于Apache Kudu 1.15.0版本。请参考适用于Kudu集群版本的相应版本的文档。

8.1、启动错误

8.1.1、冲孔测试过程中的误差

Kudu需要孔冲孔能力,以提高效率。穿孔支持取决于您的操作系统内核版本和本地文件系统实现。

  • RHEL或CentOS 6.4及以上版本,补丁到内核版本2.6.32-358及以上。未打补丁的RHEL或CentOS 6.4不包含支持打孔的内核。

  • Ubuntu 14.04包含Linux内核的3.13版本,它支持打孔。

  • 新版本的ext4和xfs文件系统支持穿孔。不支持打孔的旧版本会导致Kudu发出如下错误信息,无法启动:

    1. Error during hole punch test. The log block manager requires a
    2. filesystem with hole punching support such as ext4 or xfs. On el6,
    3. kernel version 2.6.32-358 or newer is required. To run without hole
    4. punching (at the cost of some efficiency and scalability), reconfigure
    5. Kudu to use the file block manager. Refer to the Kudu documentation for
    6. more details. WARNING: the file block manager is not suitable for
    7. production use and should be used only for small-scale evaluation and
    8. development on systems where hole-punching is not available. It's
    9. impossible to switch between block managers after data is written to the
    10. server. Raw error message follows

Ext4挂载点实际上可能由ext2或ext3格式的设备支持,这些设备不支持穿孔。当在这样的文件系统上运行时,穿孔测试将失败。有几种不同的方法可以确定ext4挂载点是否由ext2、ext3或ext4格式化的设备支持;详情请参阅Stack Exchange文章。

更改目录配置文档。

如果没有打孔支持,使用日志块管理器是不安全的。它永远不会删除块,并且会消耗更多的磁盘空间。

如果您不能在您的环境中使用打孔,您仍然可以尝试Kudu。通过在启动主服务器和平板服务器的命令中添加—block_manager=file标志,启用文件块管理器而不是日志块管理器。文件块管理器不能像日志块管理器那样伸缩。

众所周知,文件块管理器伸缩性和性能很差,应该只用于小规模的评估和开发,并且只用于无法打孔的系统。

文件块管理器每个块使用一个文件。由于对每个行集写入多个块,块的数量可能非常高,特别是对于主动写入的片。与只有少量数据的日志块管理器相比,这可能会导致性能问题,而且如果不清除和重新初始化平板服务器,就不可能在块管理器之间切换。

8.1.2、Already present: FS布局已经存在

当Kudu启动时,它会检查每个已配置的数据目录,希望所有数据都被初始化,或者所有数据都为空。如果服务器启动失败,日志信息如下

  1. Check failed: _s.ok() Bad status: Already present: FS layout already exists; not overwriting existing layout: FSManager roots already exist: /data0/kudu/data

那么,这个前提条件已经失败了。这可能是因为Kudu在首次启动时配置了非空的数据目录,也可能是因为之前运行的正常的Kudu进程被重启,至少有一个数据目录被删除或以某种方式损坏,可能是由于磁盘错误。如果是后一种情况,请参考更改目录配置文档。

8.1.3、NTP时钟同步

如果使用系统时间源,需要通过NTP (Network Time Protocol)同步库主机或平板服务器的本地时钟。时间源由—time_source标志控制,默认设置为system。

Kudu要求ntp同步时钟的最大时钟错误(不要与估计错误混淆)低于可配置的阈值。默认阈值是10秒,可以使用—max_clock_sync_error_usec标志进行定制。

当使用系统时间源运行时,如果报告本地时钟未同步,Kudu将不会启动,并发出如下消息:

  1. F0924 20:24:36.336809 14550 hybrid_clock.cc:191 Couldn't get the current time: Clock unsynchronized. Status: Service unavailable: Error reading clock. Clock considered unsynchronized.

如果机器的时钟是同步的,但是最大的时钟误差太高,用户会看到这样的消息:

  1. Sep 17, 8:13:09.873 PM FATAL hybrid_clock.cc:196 Couldn't get the current time: Clock synchronized, but error: 11130000, is past the maximum allowable error: 10000000

  1. Sep 17, 8:32:31.135 PM FATAL tablet_server_main.cc:38 Check failed: _s.ok() Bad status: Service unavailable: Cannot initialize clock: Cannot initialize HybridClock. Clock synchronized but error was too high (11711000 us).

在以下与NTP相关的段落中,当谈到使用NTP实现真实时间的“同步”时,我们指的是以下几点:-驱动本机本地时钟的NTP服务器的同步状态-由内核的NTP规则报告的本地机器时钟本身的同步状态

如果使用ntpd(它们包含在ntp包中),则可以使用ntpstat、ntpq和ntpdc实用程序获取前者;如果使用chronyd(它是chrony包的一部分),则可以使用chronyc实用程序获取前者。后者可以使用ntptime实用程序(ntptime实用程序也是ntp包的一部分)或使用chronyc实用程序(如果使用chronyd)获取。有关更多信息,请参阅上述实用程序的手册页和下面的段落。

8.1.3.1、NTP-related包

长期以来,推荐在Kudu节点上使用ntpd服务器同步本地机器的时钟。Linux操作系统的新版本提供了chronyd作为ntpd的替代品,用于网络时间同步。两者都经过了测试和证明,可以为Kudu集群中的时钟同步提供必要的功能。

安装和运行ntpd
ntpd是无处不在的NTP套件中的NTP服务器。

要安装ntpd和其他与ntp相关的实用程序,请使用适合您的操作系统的命令:

OS Command
Debian/Ubuntu sudo apt-get install ntp
RHEL/CentOS sudo yum install ntp

如果ntpd已经安装但没有运行,请使用以下命令启动它(不要忘记先运行ntpdate):

OS Command
Debian/Ubuntu sudo service ntp restart
RHEL/CentOS sudo service ntpd restart

确保机器启动时ntpdate在正在运行的服务列表中:ntpdate应该在启动ntpd之前运行,以避免机器的本地时钟与真实时间的长时间同步延迟。本地机器的时钟与真实时间的差值越小,NTP服务器同步时钟的速度越快。

执行ntpdate命令时,请确保工具报告成功:检查其退出状态和输出。如果问题连接到NTP服务器,请确保NTP流量没有被防火墙阻塞(NTP在缺省情况下产生UDP流量123端口)或其他网络连接问题。

下面是ntpd的一些配置文件示例。默认情况下,ntpd使用/etc/ntp.conf配置文件。

  1. # Use my organization's internal NTP server (server in a local network).
  2. server ntp1.myorg.internal iburst maxpoll 7
  3. # Add servers from the NTP public pool for redundancy and robustness.
  4. server 0.pool.ntp.org iburst maxpoll 8
  5. server 1.pool.ntp.org iburst maxpoll 8
  6. server 2.pool.ntp.org iburst maxpoll 8
  7. server 3.pool.ntp.org iburst maxpoll 8
  1. # AWS case: use dedicated NTP server available via link-local IP address.
  2. server 169.254.169.123 iburst
  1. # GCE case: use dedicated NTP server available from within cloud instance.
  2. server metadata.google.internal iburst

有时,即使ntpstat实用程序报告NTP守护进程与一个参考NTP服务器同步,将机器的本地时钟与真实时间同步也需要很长时间。这表现为以下几点:公用事业NTP守护进程的同步状态报告声称一切都好,但ntptime声称本地时钟同步的状态和捻角羚平板电脑服务器和主人拒绝开始,输出一个错误就像上面提到的。如果使用-x选项运行ntpd,通常会发生这种情况。根据ntpd的手册页,-x标志设置NTP服务器只回调时钟。没有-x, NTP服务器将做一个步骤调整:

  1. -x Normally, the time is slewed if the offset is less than the
  2. step threshold, which is 128 ms by default, and stepped if
  3. above the threshold. This option sets the threshold to 600 s,
  4. which is well within the accuracy window to set the clock manually.
  5. Note: Since the slew rate of typical Unix kernels is limited to
  6. 0.5 ms/s, each second of adjustment requires an amortization
  7. interval of 2000 s. Thus, an adjustment as much as 600 s
  8. will take almost 14 days to complete.

在这种情况下,删除-x选项将有助于更快地同步本地时钟。
关于各种NTP同步问题的最佳实践和实际解决示例的更多信息可以在clock-drift中找到

使用ntp套件监控时钟同步状态
安装ntp包后,可以通过运行ntptime来监控机器的时钟同步状态。例如,一个同步了本地时钟的系统可能会报告:

  1. ntp_gettime() returns code 0 (OK)
  2. time de24c0cf.8d5da274 Tue, Feb 6 2018 16:03:27.552, (.552210980),
  3. maximum error 224455 us, estimated error 383 us, TAI offset 0
  4. ntp_adjtime() returns code 0 (OK)
  5. modes 0x0 (),
  6. offset 1279.543 us, frequency 2.500 ppm, interval 1 s,
  7. maximum error 224455 us, estimated error 383 us,
  8. status 0x2001 (PLL,NANO),
  9. time constant 10, precision 0.001 us, tolerance 500 ppm,

注意以下最重要的输出:

  • 最大错误22455 us:这个值远远低于Kudu要求的10秒最大错误。
  • status 0x2001 (PLL,NANO):表示本地时钟与真实时间同步,直到最大错误以上

相反,本地时钟不同步的系统会报告如下内容:

  1. ntp_gettime() returns code 5 (ERROR)
  2. time de24c240.0c006000 Tue, Feb 6 2018 16:09:36.046, (.046881),
  3. maximum error 16000000 us, estimated error 16000000 us, TAI offset 0
  4. ntp_adjtime() returns code 5 (ERROR)
  5. modes 0x0 (),
  6. offset 0.000 us, frequency 2.500 ppm, interval 1 s,
  7. maximum error 16000000 us, estimated error 16000000 us,
  8. status 0x40 (UNSYNC),
  9. time constant 10, precision 1.000 us, tolerance 500 ppm,

UNSYNC状态表示本地时钟未与真实时间同步。正因为如此,报告的最大误差并不表示实际误差的任何有意义的估计。

ntpstat实用程序报告一个关于NTP守护进程本身同步状态的摘要。例如,一个运行ntpd并与它的一个引用服务器同步的系统可能会报告:

  1. $ ntpstat
  2. synchronised to NTP server (172.18.7.3) at stratum 4
  3. time correct to within 160 ms
  4. polling server every 1024 s

请记住,NTP守护进程本身的同步状态并不反映本地时钟的同步状态。NTP守护进程驱动本地时钟的方式受到许多限制,在NTP守护进程本身连接到一个引用服务器之后,可能需要一些时间来同步本地时钟。

如果需要更详细的信息在NTP的同步状态服务器上(但不是本地时钟的同步状态),ntpq或ntpdc工具可以用来获取详细信息关于NTP服务器目前作为源的真实时间和视为候选人(可行或不):

  1. $ ntpq -nc lpeers
  2. remote refid st t when poll reach delay offset jitter
  3. ==============================================================================
  4. -108.59.2.24 130.133.1.10 2 u 13 64 1 71.743 0.373 0.016
  5. +192.96.202.120 129.6.15.28 2 u 12 64 1 72.583 -0.426 0.028
  6. -69.10.161.7 204.26.59.157 3 u 11 64 1 15.741 2.641 0.021
  7. -173.255.206.154 45.56.123.24 3 u 10 64 1 43.502 0.199 0.029
  8. -69.195.159.158 128.138.140.44 2 u 9 64 1 53.885 -0.016 0.013
  9. *216.218.254.202 .CDMA. 1 u 6 64 1 1.475 -0.400 0.012
  10. +129.250.35.250 249.224.99.213 2 u 7 64 1 1.342 -0.640 0.018
  11. $ ntpq -nc opeers
  12. remote local st t when poll reach delay offset disp
  13. ==============================================================================
  14. -108.59.2.24 10.17.100.238 2 u 17 64 1 71.743 0.373 187.573
  15. +192.96.202.120 10.17.100.238 2 u 16 64 1 72.583 -0.426 187.594
  16. -69.10.161.7 10.17.100.238 3 u 15 64 1 15.741 2.641 187.569
  17. -173.255.206.154 10.17.100.238 3 u 14 64 1 43.502 0.199 187.580
  18. -69.195.159.158 10.17.100.238 2 u 13 64 1 53.885 -0.016 187.561
  19. *216.218.254.202 10.17.100.238 1 u 10 64 1 1.475 -0.400 187.543
  20. +129.250.35.250 10.17.100.238 2 u 11 64 1 1.342 -0.640 187.588

lpeers和peers都可能有帮助,因为lpeers列出了refid和jitter,而peers列出了时钟色散。

安装和运行chronyd

Kudu已经过测试,并在使用chronyd version 3.2及更新版本与NTP同步的机器上支持。

操作系统包称为chrony,包含NTP服务器chronyd和命令行实用程序chronyc。要安装chronyd NTP服务器和其他实用程序,请使用适合您的操作系统的命令:

OS Command
Debian/Ubuntu sudo apt-get install chrony
RHEL/CentOS sudo yum install chrony

如果chronyd已经安装,但还没有运行,使用下面的命令启动它(不要忘记先运行chronyd -q):

OS Command
Debian/Ubuntu sudo service chrony restart
RHEL/CentOS sudo service chronyd restart

默认情况下,“chronyd”使用/etc/chrony.conf配置文件。必须在chronyc .conf中启用rtcsync选项。如果没有rtcsync,本地机器的时钟将始终报告为未同步,Kudu主机和平板电脑服务器将无法启动。下面的代码解释了在Linux上设置本地时钟同步状态时观察到的chronyd行为。

在使用chronyd 3.2及更新版本的RHEL7.5/CentOS7.5中验证过,如果运行在具有Internet访问权限的机器上,则默认配置文件足以满足系统时钟的Kudu要求。

一个最小可行配置的例子是:

  1. pool pool.ntp.org iburst
  2. driftfile /var/lib/chrony/drift
  3. makestep 1 3
  4. rtcsync

使用时钟套件监控时钟同步状态当安装了chrony包时,您可以通过运行chronyc tracking来监控机器时钟的同步状态(如果需要将IP地址解析回FQDNs,请添加-n选项:chronyc -n tracking)。

例如,在一个系统中,chronyd还没有同步本地时钟,可能会报告如下内容:

  1. Reference ID : 00000000 ()
  2. Stratum : 0
  3. Ref time (UTC) : Thu Jan 01 00:00:00 1970
  4. System time : 0.000000000 seconds fast of NTP time
  5. Last offset : +0.000000000 seconds
  6. RMS offset : 0.000000000 seconds
  7. Frequency : 69.422 ppm slow
  8. Residual freq : +0.000 ppm
  9. Skew : 0.000 ppm
  10. Root delay : 1.000000000 seconds
  11. Root dispersion : 1.000000000 seconds
  12. Update interval : 0.0 seconds
  13. Leap status : Not synchronised

一个本地时钟已经同步的系统可以报告:

  1. Reference ID : A9FEA9FE (169.254.169.254)
  2. Stratum : 3
  3. Ref time (UTC) : Tue Mar 03 06:33:23 2020
  4. System time : 0.000011798 seconds fast of NTP time
  5. Last offset : +0.000014285 seconds
  6. RMS offset : 0.001493311 seconds
  7. Frequency : 69.417 ppm slow
  8. Residual freq : +0.000 ppm
  9. Skew : 0.006 ppm
  10. Root delay : 0.000786347 seconds
  11. Root dispersion : 0.000138749 seconds
  12. Update interval : 1036.7 seconds
  13. Leap status : Normal

注意以下重要的输出:

  • Root delay:到与这个chronyd实例同步的Stratum 1服务器的网络路径延迟(往返)的总和。

  • Root dispersion:通过所有路径累积到与此同步的Stratum 1服务器的总分散度。

  • Leap status:本地时钟是否与真实时间同步到最大错误(见下)。“正常”状态表示时钟已同步,“非自然同步”状态表示时钟未同步。

上一次NTP更新时,由chronyd内部维护的时钟错误的绝对约束可以表示为:

  1. clock_error <= abs(last_offset) + (root_delay / 2) + root_dispersion

参考NTP服务器列表中的chronyc sources:报告:

要获取更多关于NTP服务器测量统计的详细信息,请使用chronyc sourcestats:

  1. 210 Number of sources = 4
  2. Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
  3. ==============================================================================
  4. 169.254.169.254 46 27 323m +0.000 0.006 +72ns 68us
  5. 64.62.190.177 12 10 224m +0.071 0.050 +1240us 154us
  6. 64.246.132.14 21 13 326m +0.012 0.030 +434us 230us
  7. 184.105.182.16 6 3 86m +0.252 0.559 -5097us 306us

使用chronyc ntpdata [server]获取特定引用服务器(或所有服务器,如果省略了server参数)的信息:

  1. Remote address : 169.254.169.254 (A9FEA9FE)
  2. Remote port : 123
  3. Local address : 172.31.113.1 (AC1F7101)
  4. Leap status : Normal
  5. Version : 4
  6. Mode : Server
  7. Stratum : 2
  8. Poll interval : 10 (1024 seconds)
  9. Precision : -20 (0.000000954 seconds)
  10. Root delay : 0.000229 seconds
  11. Root dispersion : 0.000107 seconds
  12. Reference ID : 474F4F47 ()
  13. Reference time : Tue Mar 03 06:33:24 2020
  14. Offset : -0.000253832 seconds
  15. Peer delay : 0.000557465 seconds
  16. Peer dispersion : 0.000000987 seconds
  17. Response time : 0.000000001 seconds
  18. Jitter asymmetry: +0.50
  19. NTP tests : 111 111 1111
  20. Interleaved : No
  21. Authenticated : No
  22. TX timestamping : Daemon
  23. RX timestamping : Kernel
  24. Total TX : 50
  25. Total RX : 50
  26. Total valid RX : 50

有关使用chronyd进行时钟同步的故障排除技巧,请参阅这个有用的指南

8.1.3.2、NTP配置最佳实践

为了提供稳定的时间同步,同时降低最大错误,请遵循以下最佳NTP配置最佳实践。

运行NTP服务器前,执行ntpdate命令(执行ntpd -q,如果是chrony,则执行chronyd -q)。如果本地时钟与真实时间的偏差过大,即使允许进行步进调整,NTP服务器也会花费很长时间才能同步本地时钟。因此,在配置完ntpd或chronyd后,请先在同一组NTP服务器上运行ntpdate工具或执行ntpd -q/chronyd -q。假设运行ntpdate/ntpd -q/chronyd -q时NTP服务器未运行。RHEL/CentOS系统,如果使用ntp套件,需要开启ntpdate服务;如果使用计时套件,请开启计时等待服务。

在某些公有云环境中,可以使用通过链路本地IP地址访问的高可用的NTP服务器或作为服务提供的其他专用的NTP服务器。如果您的集群在公共云环境中运行,请参考云提供商的文档以获得推荐的NTP设置。AWS和GCE云都提供了专用的高可用的NTP服务器,可以通过链接本地IP地址从云实例中访问。

除非使用可通过链路本地地址访问的高可用的NTP参考服务器,否则总是在本地机器上为NTP服务器配置至少四个时间源。除了在某个时间源不可用的情况下提供冗余之外,这可能会使配置更加健壮,因为NTP的设计目的是在具有更高往返时间和抖动的网络中增加其多样性的源的准确性。

使用iburst选项来加快启动时的同步。iburst选项指示NTP服务器(ntpd和chronyd)在启动时发送一个初始的“突发”时间查询。这将导致ntpd/chronyd在启动时更快地与它们的引用服务器同步。

如果最大时钟错误超过了Kudu设置的默认阈值(10秒),可以考虑在NTP .conf/chrony.conf中为每个NTP服务器设置更低的maxpoll选项。例如,考虑将maxpoll设置为7,这将导致NTP守护进程至少每128秒向相应的NTP服务器发出请求。ntpd和chronyd的默认最大轮询间隔为10(1024秒)。

如果使用自定义的maxpoll间隔,请不要将maxpoll设置得过低(例如小于6),以免NTP服务器(尤其是公共NTP服务器)被淹。否则,他们可能会将客户端(即您机器上的NTP守护进程)列入黑名单,并停止提供NTP服务。如果有疑问,请查阅相应的ntp.conf或chrony.conf手册页。

8.1.3.3、处理NTP稳定性问题

从Kudu 1.6.0开始,Kudu -master和Kudu -tserver都能够在短暂的时钟同步丢失的情况下继续运行。如果时钟同步丢失几个小时,它们可能崩溃。如果kudu-master或kudu-tserver进程由于时钟同步问题而崩溃,请查阅ERROR日志获取相关信息转储,这些信息可能有助于诊断问题。

Kudu 1.5.0和更早的版本对NTP短暂中断的恢复能力较差。此外,它们还包含一个bug,可能会导致Kudu不正确地测量最大错误,从而导致崩溃。如果您在这些早期版本的Kudu上遇到与时钟同步相关的崩溃,并且系统的NTP配置似乎是正确的,请考虑升级到Kudu 1.6.0或更高版本。
如果使用的不是链接本地NTP服务器,在发生网络连接问题时,运行在本地机器上的NTP服务器可能需要一些时间来与其参考服务器之一同步。如果机器和参考NTP服务器之间的网络不稳定,ntpd/chronyd可能会与其参考NTP服务器不同步。如果发生这种情况,请考虑寻找其他一组参考NTP服务器:最好的选择是使用本地网络中的NTP服务器或*.pool.ntp.org服务器。

8.2、磁盘空间使用情况

当使用日志块管理器(Linux上的默认值)时,Kudu使用稀疏文件来存储数据。稀疏文件的外观大小与它实际使用的磁盘空间大小不同。这意味着一些工具可能会不准确地报告Kudu使用的磁盘空间。例如,ls -l列出的大小并不能准确反映Kudu数据文件使用的磁盘空间:

  1. $ ls -lh /data/kudu/tserver/data
  2. total 117M
  3. -rw------- 1 kudu kudu 160M Mar 26 19:37 0b9807b8b17d48a6a7d5b16bf4ac4e6d.data
  4. -rw------- 1 kudu kudu 4.4K Mar 26 19:37 0b9807b8b17d48a6a7d5b16bf4ac4e6d.metadata
  5. -rw------- 1 kudu kudu 32M Mar 26 19:37 2f26eeacc7e04b65a009e2c9a2a8bd20.data
  6. -rw------- 1 kudu kudu 4.3K Mar 26 19:37 2f26eeacc7e04b65a009e2c9a2a8bd20.metadata
  7. -rw------- 1 kudu kudu 672M Mar 26 19:37 30a2dd2cd3554d8a9613f588a8d136ff.data
  8. -rw------- 1 kudu kudu 4.4K Mar 26 19:37 30a2dd2cd3554d8a9613f588a8d136ff.metadata
  9. -rw------- 1 kudu kudu 32M Mar 26 19:37 7434c83c5ec74ae6af5974e4909cbf82.data
  10. -rw------- 1 kudu kudu 4.3K Mar 26 19:37 7434c83c5ec74ae6af5974e4909cbf82.metadata
  11. -rw------- 1 kudu kudu 672M Mar 26 19:37 772d070347a04f9f8ad2ad3241440090.data
  12. -rw------- 1 kudu kudu 4.4K Mar 26 19:37 772d070347a04f9f8ad2ad3241440090.metadata
  13. -rw------- 1 kudu kudu 160M Mar 26 19:37 86e50a95531f46b6a79e671e6f5f4151.data
  14. -rw------- 1 kudu kudu 4.4K Mar 26 19:37 86e50a95531f46b6a79e671e6f5f4151.metadata
  15. -rw------- 1 kudu kudu 687 Mar 26 19:26 block_manager_instance

注意,报告的总大小是117MiB,而第一个文件的大小列出为160MiB。向ls添加-s选项将导致ls输出文件的磁盘空间使用情况。
du和df工具默认报告实际磁盘空间使用情况。

  1. $ du -h /data/kudu/tserver/data
  2. 118M /data/kudu/tserver/data

视尺寸可以用-视尺寸国旗显示为du。

  1. $ du -h --apparent-size /data/kudu/tserver/data
  2. 1.7G /data/kudu/tserver/data

8.3、kudu崩溃报告

每当Kudu崩溃时,Kudu使用谷歌Breakpad库生成一个迷你转储。这些迷你转储通常只有几个MB大小,即使禁用了核心转储生成,也会生成这些转储。此时,只能在Linux构建的Kudu中生成迷你转储文件。

minidump文件包含重要调试崩溃的进程信息,包括共享库加载及其版本,运行的线程列表时崩溃,处理器的状态寄存器和一个副本为每个线程堆栈的内存,CPU和操作系统的版本信息。

也可以通过向Kudu -tserver或Kudu -master进程发送USR1信号来强制Kudu创建一个迷你转储,而不终止该进程。例如:

  1. sudo pkill -USR1 kudu-tserver

默认情况下,Kudu将其mindump文件存放在其配置的glog目录下的名为mindump的子目录中。这个位置可以通过设置——minidump_path标志来定制。Kudu在删除最老的mindump之前,只会保留一定数量的mindump文件,以避免用mindump文件填满磁盘。保留的最小转储的最大数量可以通过设置——max_mindump gflag来控制。
mindump包含特定于创建它们的二进制文件的信息,因此如果不能访问崩溃的二进制文件或非常类似的二进制文件,就不可用。有关处理和使用minidump文件的更多信息,请参见scripts/dump_breakpad_symbols.py。

一个迷你转储可以通过电子邮件发送给Kudu开发人员或附加到JIRA,以帮助Kudu开发人员调试崩溃。为了让它有用,开发人员需要知道Kudu的确切版本,以及观察到崩溃的操作系统。请注意,虽然mindump不包含堆内存转储,但它包含堆栈内存,因此应用程序数据可能出现在mindump中。如果集群中存储了机密或个人信息,请不要共享mindump文件。

8.4、性能故障诊断

8.4.1、Kudu跟踪

kudu-master和kudu-tserver守护进程包括基于开源Chromium tracing框架的内置跟踪支持。您可以使用跟踪来帮助诊断Kudu服务器上的延迟问题或其他问题。

访问跟踪接口
跟踪接口作为每个Kudu守护进程中的嵌入式web服务器的一部分,通过web浏览器访问。

表1。跟踪界面网址

Daemon URL
Tablet Server http://tablet-server-1.example.com:8050/tracing.html
Master http://master-1.example.com:8051/tracing.html

跟踪接口已知工作在谷歌Chrome的最新版本。其他浏览器可能无法正常工作。

收集一个跟踪
导航到跟踪界面后,单击屏幕左上角的Record按钮。当开始诊断一个问题时,首先选择所有类别。单击“记录”开始记录跟踪。

在跟踪收集期间,事件被收集到内存中的循环缓冲区中。这个环形缓冲区的大小是固定的,所以它最终会填充到100%。但是,在删除旧事件的同时,仍在收集新事件。在记录跟踪时,触发您感兴趣的行为或工作负载。

收集几秒钟后,单击Stop。将下载并显示收集到的跟踪信息。使用?键以显示有关使用跟踪接口浏览跟踪的帮助文本。

保存一个跟踪
您可以在收集跟踪信息后单击save,将收集到的跟踪信息保存为JSON文件,以便稍后进行分析。若要加载和分析已保存的JSON文件,请单击load并选择该文件。

8.4.2、RPC超时痕迹

如果客户端应用程序遇到RPC超时,Kudu平板服务器WARNING级别的日志应该包含一个包含RPC级别跟踪的日志条目。例如:

  1. W0922 00:56:52.313848 10858 inbound_call.cc:193] Call kudu.consensus.ConsensusService.UpdateConsensus
  2. from 192.168.1.102:43499 (request call id 3555909) took 1464ms (client timeout 1000).
  3. W0922 00:56:52.314888 10858 inbound_call.cc:197] Trace:
  4. 0922 00:56:50.849505 (+ 0us) service_pool.cc:97] Inserting onto call queue
  5. 0922 00:56:50.849527 (+ 22us) service_pool.cc:158] Handling call
  6. 0922 00:56:50.849574 (+ 47us) raft_consensus.cc:1008] Updating replica for 2 ops
  7. 0922 00:56:50.849628 (+ 54us) raft_consensus.cc:1050] Early marking committed up to term: 8 index: 880241
  8. 0922 00:56:50.849968 (+ 340us) raft_consensus.cc:1056] Triggering prepare for 2 ops
  9. 0922 00:56:50.850119 (+ 151us) log.cc:420] Serialized 1555 byte log entry
  10. 0922 00:56:50.850213 (+ 94us) raft_consensus.cc:1131] Marking committed up to term: 8 index: 880241
  11. 0922 00:56:50.850218 (+ 5us) raft_consensus.cc:1148] Updating last received op as term: 8 index: 880243
  12. 0922 00:56:50.850219 (+ 1us) raft_consensus.cc:1195] Filling consensus response to leader.
  13. 0922 00:56:50.850221 (+ 2us) raft_consensus.cc:1169] Waiting on the replicates to finish logging
  14. 0922 00:56:52.313763 (+1463542us) raft_consensus.cc:1182] finished
  15. 0922 00:56:52.313764 (+ 1us) raft_consensus.cc:1190] UpdateReplicas() finished
  16. 0922 00:56:52.313788 (+ 24us) inbound_call.cc:114] Queueing success response

这些跟踪可以指示请求的哪一部分比较慢。请将它们包含在与RPC延迟异常值相关的bug报告中。

8.4.3、内核堆栈看门狗跟踪

每个Kudu服务器进程都有一个名为Stack Watchdog的后台线程,该线程监视服务器中的其他线程,以防它们阻塞的时间超过预期。这些跟踪可以指示操作系统问题或存储瓶颈。

当watchdog线程识别出线程阻塞的情况时,它会在WARNING日志中记录一条记录,如下:

  1. W0921 23:51:54.306350 10912 kernel_stack_watchdog.cc:111] Thread 10937 stuck at /data/kudu/consensus/log.cc:505 for 537ms:
  2. Kernel stack:
  3. [<ffffffffa00b209d>] do_get_write_access+0x29d/0x520 [jbd2]
  4. [<ffffffffa00b2471>] jbd2_journal_get_write_access+0x31/0x50 [jbd2]
  5. [<ffffffffa00fe6d8>] __ext4_journal_get_write_access+0x38/0x80 [ext4]
  6. [<ffffffffa00d9b23>] ext4_reserve_inode_write+0x73/0xa0 [ext4]
  7. [<ffffffffa00d9b9c>] ext4_mark_inode_dirty+0x4c/0x1d0 [ext4]
  8. [<ffffffffa00d9e90>] ext4_dirty_inode+0x40/0x60 [ext4]
  9. [<ffffffff811ac48b>] __mark_inode_dirty+0x3b/0x160
  10. [<ffffffff8119c742>] file_update_time+0xf2/0x170
  11. [<ffffffff8111c1e0>] __generic_file_aio_write+0x230/0x490
  12. [<ffffffff8111c4c8>] generic_file_aio_write+0x88/0x100
  13. [<ffffffffa00d3fb1>] ext4_file_write+0x61/0x1e0 [ext4]
  14. [<ffffffff81180f5b>] do_sync_readv_writev+0xfb/0x140
  15. [<ffffffff81181ee6>] do_readv_writev+0xd6/0x1f0
  16. [<ffffffff81182046>] vfs_writev+0x46/0x60
  17. [<ffffffff81182102>] sys_pwritev+0xa2/0xc0
  18. [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b
  19. [<ffffffffffffffff>] 0xffffffffffffffff
  20. User stack:
  21. @ 0x3a1ace10c4 (unknown)
  22. @ 0x1262103 (unknown)
  23. @ 0x12622d4 (unknown)
  24. @ 0x12603df (unknown)
  25. @ 0x8e7bfb (unknown)
  26. @ 0x8f478b (unknown)
  27. @ 0x8f55db (unknown)
  28. @ 0x12a7b6f (unknown)
  29. @ 0x3a1b007851 (unknown)
  30. @ 0x3a1ace894d (unknown)
  31. @ (nil) (unknown)

这些跟踪对于由低于Kudu的系统(如磁盘控制器或文件系统)引起的根本原因延迟问题的诊断非常有用。

8.4.4、内存限制

Kudu有硬内存和软内存限制。硬内存限制是允许一个Kudu进程使用的最大数量,由—memory_limit_hard_bytes标志控制。软内存限制是硬内存限制的一个百分比,由标志memory_limit_soft_percentage 控制,默认值为80%,它决定了进程在开始拒绝某些写操作之前可能使用的内存量。

如果日志或RPC跟踪包含以下消息

  1. Service unavailable: Soft memory limit exceeded (at 96.35% of capacity)

那么Kudu就会因为内存反压而拒绝写操作。这可能会导致写超时。有几种方法可以缓解Kudu上的内存压力:

  • 如果主机有更多可供Kudu使用的内存,请增加—memory_limit_hard_bytes。
  • 通过增加磁盘数量或增加维护管理器线程的数量(maintenance_manager_num_threads)来提高Kudu从内存向磁盘刷新写操作的速度。一般情况下,维护管理器线程与数据目录的比例建议为1:3。
  • 减少应用程序端流向Kudu的写量。

最后,在1.8之前的Kudu版本中,检查—block_cache_capacity_mb的值。这个设置决定了Kudu块缓存的最大大小。在一个更高的价值可以帮助读写性能,不提高,—block_cache_capacity_mb内存压力阈值之上,这是—memory_pressure_percentage —memory_limit_hard_bytes(默认60%),因为这将导致捻角羚冲洗积极即使写吞吐量较低。建议—block_cache_capacity_mb低于内存压力阈值的50%。使用默认值,这意味着—block_cache_capacity_mb不应该超过—memory_limit_hard_bytes的30%。在Kudu 1.8及更高版本上,如果块缓存容量超过内存压力阈值,服务器将拒绝启动。

8.4.5、块缓存大小

Kudu对最近读的数据使用LRU缓存。在重复扫描数据子集的工作负载上,提高这个缓存的大小可以提供显著的性能好处。要增加专用于块缓存的内存量,请增加标志—block_cache_capacity_mb的值。缺省值为512MiB。

Kudu提供了一套评估块缓存性能的有用指标,可以在web UI的/metrics端点上找到。一个例子:

  1. {
  2. "name": "block_cache_inserts",
  3. "value": 64
  4. },
  5. {
  6. "name": "block_cache_lookups",
  7. "value": 512
  8. },
  9. {
  10. "name": "block_cache_evictions",
  11. "value": 0
  12. },
  13. {
  14. "name": "block_cache_misses",
  15. "value": 96
  16. },
  17. {
  18. "name": "block_cache_misses_caching",
  19. "value": 64
  20. },
  21. {
  22. "name": "block_cache_hits",
  23. "value": 0
  24. },
  25. {
  26. "name": "block_cache_hits_caching",
  27. "value": 352
  28. },
  29. {
  30. "name": "block_cache_usage",
  31. "value": 6976
  32. }

要判断平板服务器上的块缓存的效率,首先要等待服务器运行并服务正常请求一段时间,这样缓存才不是冷的。除非服务器存储的数据很少或空闲,否则block_cache_usage 应该等于或接近等于block_cache_capacity_mb。一旦缓存达到稳定状态,将block_cache_lookups 与block_cache_misses_caching进行比较。后一个指标计算Kudu期望从缓存中读取但在缓存中没有找到的块的数量。如果大量的查找导致未命中预期的缓存命中,并且block_cache_evictions指标与block_cache_inserts相比非常重要,那么提高块缓存的大小可能会提供性能提升。然而,块缓存的效用高度依赖于工作负载,因此有必要测试更大块缓存的好处。

不要提高块缓存大小—block_cache_capacity_mb 高于内存压力阈值(默认为—memory_limit_hard_bytes的60%)。由于这将导致糟糕的刷新行为,当以这种方式配置错误时,Kudu服务器的1.8版及更高版本将拒绝启动。

8.4.6、堆抽样

对于内存使用的高级调试,发布的Kudu版本默认启用堆抽样。这允许Kudu开发人员将内存使用与特定的代码行和数据结构关联起来。当报告与内存使用相关的错误或明显的内存泄漏时,堆分析可以提供定量数据来查明问题。

如果启用了堆抽样,则可以通过访问http://tablet-server.example.com:8050/pprof/heaphttp://master.example.com:8051/pprof/heap通过HTTP检索当前抽样的堆占用率。输出是一个机器可读的堆栈跟踪及其相关的堆使用情况转储。

比起在web浏览器中直接访问堆配置文件页面,使用作为gperftools开源项目一部分分发的pprof工具通常更有用。例如,拥有本地构建树的开发人员可以使用以下命令收集采样的堆使用情况并输出SVG图:

  1. thirdparty/installed/uninstrumented/bin/pprof -svg 'http://localhost:8051/pprof/heap' > /tmp/heap.svg

生成的SVG可以在web浏览器中可视化,或者发送给Kudu社区以帮助解决内存占用问题。
堆示例只包含关于分配的摘要信息,不包含来自堆的任何数据。在公共场合共享堆样本是安全的,不必担心暴露机密或敏感数据。

8.4.7、缓慢的DNS查找和nscd

为了在承载许多副本的节点上获得更好的可伸缩性,我们建议您使用nscd(名称服务缓存守护进程)来缓存DNS名称解析和静态名称解析(通过/etc/hosts)。

当DNS查找缓慢时,您将看到类似如下的日志消息:

  1. W0926 11:19:01.339553 27231 net_util.cc:193] Time spent resolve address for kudu-tserver.example.com: real 4.647s user 0.000s sys 0.000s

NSCD(名称服务缓存守护进程)可以通过为最常见的名称服务请求(如密码、组和主机)提供缓存来缓解名称解析的缓慢情况。
关于如何安装和启用nscd,请参考您的操作系统文档。

8.5、使用kudu的问题

8.5.1、ClassNotFoundException: com.cloudera.kudu.hive.KuduStorageHandler

当用户试图通过Hive使用Kudu表时,会遇到此异常。这不是jar丢失的情况,而是Impala在Hive中存储Kudu元数据的格式是其他工具(包括Hive本身和Spark)无法读取的。Hive用户没有任何变通方法。Spark用户需要创建临时表。

8.5.2、运行时错误:无法创建线程:资源暂时不可用(错误11)

当Kudu无法创建更多线程时,用户会遇到这个错误,通常是在超过1.7版本的Kudu上。这种情况发生在平板电脑服务器上,这表明平板电脑服务器承载了太多的平板电脑副本。要解决这个问题,用户可以在其操作系统或发行版的文档中详细说明nproc ulimit。然而,更好的解决方案是减少平板服务器上的副本数量。这可能需要重新考虑表的分区模式。关于每台平板服务器的副本数量的推荐限制,请参阅相应的Kudu版本的已知问题和扩展限制文档。发布页面有以前版本Kudu的文档链接;有关最新版本,请参见已知问题页面。

8.5.3、删除或停止的tablet 副本

用户可能会注意到tablet服务器上的一些副本处于STOPPED状态,并无限期地保留在服务器上。这些复制品是墓碑。墓碑表示平板电脑服务器曾经拥有其平板电脑的真实副本。例如,如果一个平板服务器宕机,它的副本被重新复制到其他地方,如果平板服务器重新加入集群,它的副本将成为墓碑。墓碑将一直保留,直到它所属的表被删除,或者同一片剂的新副本被放置在片剂服务器上。一个tomboned副本的计数和每个副本的详细信息可以在平板服务器web UI的/tablet页面上找到。

Kudu用于复制的Raft共识算法在某些罕见的情况下需要墓碑来保证正确性。它们消耗最少的资源并且不保存任何数据。不能删除它们。

8.5.4、损坏:CFile块上的校验和错误

在Kudu 1.8.0之前的版本中,如果磁盘上的数据损坏了,用户在扫描带有损坏的CFile块的平板电脑时,会在平板服务器日志中遇到包含“损坏:CFile块上的校验和错误”的警告,以及客户端错误。修复这种损坏是一个手动过程。

要修复此问题,用户首先可以使用ksck工具对受影响的表或片运行校验和扫描来识别所有受影响的片。

  1. sudo -u kudu kudu cluster ksck <master_addresses> -checksum_scan -tables=<tables>
  2. sudo -u kudu kudu cluster ksck <master_addresses> -checksum_scan -tablets=<tablets>

如果每个tablet至少有一个不返回损坏错误的副本,则可以通过删除它们并使用remote_replica delete工具从leader重新复制它们来修复这些坏副本。

  1. sudo -u kudu kudu remote_replica delete <tserver_address> <tablet_id> "Cfile Corruption"

如果所有的副本都损坏了,那么就会发生一些数据丢失。在KUDU-2526完成之前,如果损坏的副本成为leader,而现有的follower副本被替换,就会发生这种情况。
如果数据丢失,可以使用unsafe_replace_tablet工具将损坏的tablet替换为空的tablet来修复表。

  1. sudo -u kudu kudu tablet unsafe_replace_tablet <master_addresses> <tablet_id>

从版本1.8.0开始,Kudu将把受影响的副本标记为失败,导致它们在其他地方自动重新复制。

8.5.5、象征着堆栈跟踪

有时你可能会在日志中看到以下内容:

  1. 0323 03:59:31.091198 (+607857us) spinlock_profiling.cc:243] Waited 492 ms on lock 0x4cb0960. stack: 0000000002398852 0000000000ad8c69 0000000000aa62ba 000000000221aaa8 000000000221b1a8 00000000023a8f83 00007fa8b818be24 00007fa8b646a34c

这通常是线程之间争用锁的标志,在这种情况下,报告的时间显示了线程在获取锁之前在CPU上花费的时间。列出的调用堆栈地址有助于恢复等待线程的堆栈跟踪,并查明代码中的问题。
可以将地址转换为具有产生输出的二进制文件的代码中的函数名和行名(在本例中为kudu-master)。如果二进制文件去掉了符号和调试信息,那么如果二进制文件有单独的调试信息,也可以这样做。

假设剥离后的发布二进制文件和调试信息都可以作为rpm使用,将它们解压缩到一个目录中(例如sysroot):

  1. $ mkdir sysroot && cd sysroot
  2. $ rpm2cpio ../kudu-1.10.0.el7.x86_64.rpm | cpio -idmv
  3. $ rpm2cpio ../kudu-debuginfo-1.10.0.el7.x86_64.rpm | cpio -idmv

使用addr2line在代码中找到堆栈地址的行(如果二进制文件没有去掉调试信息,使用-e选项代替调试信息文件):

  1. addr2line -C -f -e usr/lib/debug/usr/lib/kudu/sbin-release/kudu-master.debug 0x0000000000aa62ba
  2. kudu::master::MasterServiceImpl::ConnectToMaster(kudu::master::ConnectToMasterRequestPB const*, kudu::master::ConnectToMasterResponsePB*, kudu::rpc::RpcContext*)
  3. /usr/src/debug/kudu-1.10.0/src/kudu/master/master_service.cc:504

要用gdb实现同样的目的,首先在符号文件中找到.text部分的地址(在示例中是0000000000a2cdb0):

  1. $ readelf -S usr/lib/debug/usr/lib/kudu/sbin-release/kudu-master.debug | grep .text
  2. [13] .text NOBITS 0000000000a2cdb0 000002c0

然后启动gdb,将它指向kudu-master可执行文件(即在日志文件中生成输出的可执行文件):

  1. gdb usr/lib/kudu/sbin-release/kudu-master

现在使用上面找到的地址将.debug符号加载到gdb中,告诉gdb在哪里找到源文件,并设置sysroot:

  1. (gdb) add-symbol-file usr/lib/debug/usr/lib/kudu/sbin-release/kudu-master.debug 0x0000000000a2cdb0
  2. (gdb) set substitute-path /usr/src/debug/kudu-1.10.0 usr/src/debug/kudu-1.10.0
  3. (gdb) set sysroot .

要将地址转换为行号和函数信息,使用info line *

:

  1. gdb) info line * 0x0000000000aa62ba
  2. Line 504 of "/usr/src/debug/kudu-1.10.0/src/kudu/master/master_service.cc"
  3. starts at address 0xaa62af <kudu::master::MasterServiceImpl::ConnectToMaster(kudu::master::ConnectToMasterRequestPB const*, kudu::master::ConnectToMasterResponsePB*, kudu::rpc::RpcContext*)+47>
  4. and ends at 0xaa62bb <kudu::master::MasterServiceImpl::ConnectToMaster(kudu::master::ConnectToMasterRequestPB const*, kudu::master::ConnectToMasterResponsePB*, kudu::rpc::RpcContext*)+59>.