问题:

问题:

任何对 Linux IO 系统有一定经验的人的见解都会有所帮助。以下是我的故事:

最近启动了一个由六台 Dell PowerEdge rx720xds 组成的集群,通过 Ceph 提供文件服务。这些机器在两个插槽上有 24 个核心,带有两个 numa 区域和 70 多 GB 的内存。磁盘被格式化为每个磁盘的 raid(否则我们看不到直接公开它们的方法)。网络由 mellanox infiniband IP over IB 提供(IP 数据包在内核空间而不是硬件中转换为 IB)。

我们的每个 SAS 驱动器都像这样安装:

# cat /proc/mounts | grep osd
/dev/sdm1 /var/lib/ceph/osd/ceph-90 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdj1 /var/lib/ceph/osd/ceph-87 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdu1 /var/lib/ceph/osd/ceph-99 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdd1 /var/lib/ceph/osd/ceph-82 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdk1 /var/lib/ceph/osd/ceph-88 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdl1 /var/lib/ceph/osd/ceph-89 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdh1 /var/lib/ceph/osd/ceph-86 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdo1 /var/lib/ceph/osd/ceph-97 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdc1 /var/lib/ceph/osd/ceph-81 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdb1 /var/lib/ceph/osd/ceph-80 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sds1 /var/lib/ceph/osd/ceph-98 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdn1 /var/lib/ceph/osd/ceph-91 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sde1 /var/lib/ceph/osd/ceph-83 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdq1 /var/lib/ceph/osd/ceph-93 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdg1 /var/lib/ceph/osd/ceph-85 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdt1 /var/lib/ceph/osd/ceph-95 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdf1 /var/lib/ceph/osd/ceph-84 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdr1 /var/lib/ceph/osd/ceph-94 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdi1 /var/lib/ceph/osd/ceph-96 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdp1 /var/lib/ceph/osd/ceph-92 xfs rw,noatime,attr2,inode64,noquota 0 0

这些机器的 I/O 速度突发为几百 MB/s,但大多数时间都处于空闲状态,只存在许多小的“戳刺”:

# iostat -x -m
Linux 3.10.0-123.el7.x86_64 (xxx)   07/11/14    _x86_64_    (24 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
       1.82    0.00    1.05    0.11    0.00   97.02
Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.11    0.25    0.23     0.00     0.00    27.00     0.00    2.07    3.84    0.12   0.61   0.03
sdb               0.02     0.57    3.49    2.28     0.08     0.14    77.18     0.01    2.27    2.99    1.18   1.75   1.01
sdd               0.03     0.65    3.93    3.39     0.10     0.16    70.39     0.01    1.97    2.99    0.79   1.57   1.15
sdc               0.03     0.60    3.76    2.86     0.09     0.13    65.57     0.01    2.10    3.02    0.88   1.68   1.11
sdf               0.03     0.63    4.19    2.96     0.10     0.15    73.51     0.02    2.16    3.03    0.94   1.73   1.24
sdg               0.03     0.62    3.93    3.01     0.09     0.15    70.44     0.01    2.06    3.01    0.81   1.66   1.15
sde               0.03     0.56    4.35    2.61     0.10     0.14    69.53     0.02    2.26    3.00    1.02   1.82   1.26
sdj               0.02     0.73    3.67    4.74     0.10     0.37   116.06     0.02    1.84    3.01    0.93   1.31   1.10
sdh               0.03     0.62    4.31    3.04     0.10     0.15    67.83     0.02    2.15    3.04    0.89   1.75   1.29
sdi               0.02     0.59    3.82    2.47     0.09     0.13    74.35     0.01    2.20    2.96    1.03   1.76   1.10
sdl               0.03     0.59    4.75    2.46     0.11     0.14    70.19     0.02    2.33    3.02    1.00   1.93   1.39
sdk               0.02     0.57    3.66    2.41     0.09     0.13    73.57     0.01    2.20    3.00    0.97   1.76   1.07
sdm               0.03     0.66    4.03    3.17     0.09     0.14    66.13     0.01    2.02    3.00    0.78   1.64   1.18
sdn               0.03     0.62    4.70    3.00     0.11     0.16    71.63     0.02    2.25    3.01    1.05   1.79   1.38
sdo               0.02     0.62    3.75    2.48     0.10     0.13    76.01     0.01    2.16    2.94    0.99   1.70   1.06
sdp               0.03     0.62    5.03    2.50     0.11     0.15    68.65     0.02    2.39    3.08    0.99   1.99   1.50
sdq               0.03     0.53    4.46    2.08     0.09     0.12    67.74     0.02    2.42    3.04    1.09   2.01   1.32
sdr               0.03     0.57    4.21    2.31     0.09     0.14    72.05     0.02    2.35    3.00    1.16   1.89   1.23
sdt               0.03     0.66    4.78    5.13     0.10     0.20    61.78     0.02    1.90    3.10    0.79   1.49   1.47
sdu               0.03     0.55    3.93    2.42     0.09     0.13    70.77     0.01    2.17    2.97    0.85   1.79   1.14
sds               0.03     0.60    4.11    2.70     0.10     0.15    74.77     0.02    2.25    3.01    1.10   1.76   1.20
sdw               1.53     0.00    0.23   38.90     0.00     1.66    87.01     0.01    0.22    0.11    0.22   0.05   0.20
sdv               0.88     0.00    0.16   28.75     0.00     1.19    84.55     0.01    0.24    0.10    0.24   0.05   0.14
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     8.00     0.00    1.84    1.84    0.00   1.15   0.00
dm-1              0.00     0.00    0.23    0.29     0.00     0.00    23.78     0.00    1.87    4.06    0.12   0.55   0.03
dm-2              0.00     0.00    0.01    0.00     0.00     0.00     8.00     0.00    0.47    0.47    0.00   0.45   0.00

问题:

大约 48 小时后,连续的页面变得非常碎片化,以至于四大 (16 页,65536 字节) 分配开始失败,并且我们开始丢弃数据包(由于 SLAB 增长时 kalloc 失败)。

这是一个相对“健康”的服务器的样子:

# cat /sys/kernel/debug/extfrag/unusable_index
Node 0, zone      DMA 0.000 0.000 0.000 0.001 0.003 0.007 0.015 0.031 0.031 0.096 0.225 
Node 0, zone    DMA32 0.000 0.009 0.015 0.296 0.733 0.996 0.997 0.998 0.998 1.000 1.000 
Node 0, zone   Normal 0.000 0.000 0.019 0.212 0.454 0.667 0.804 0.903 0.986 1.000 1.000 
Node 1, zone   Normal 0.000 0.027 0.040 0.044 0.071 0.270 0.506 0.772 1.000 1.000 1.000 

当碎片化变得相当严重时,系统似乎开始在内核空间中旋转,一切都崩溃了。此故障期间的一个异常是 xfsaild 似乎使用了大量 CPU 并陷入不可中断的睡眠状态。不过,我不想在整个系统故障期间就得出任何奇怪的结论。

迄今为止的解决方法。

为了确保这些分配即使在碎片的情况下也不会失败,我设置了:

vm.min_free_kbytes = 16777216

在 SLAB 缓存中看到数百万个 blkdev_requests 后,我尝试通过以下方式减少脏页:

vm.dirty_ratio = 1
vm.dirty_background_ratio = 1
vm.min_slab_ratio = 1
vm.zone_reclaim_mode = 3

可能一次更改了太多变量,但是为了防止 inode 和 dentry 造成碎片,我决定将它们保持在最低限度:

vm.vfs_cache_pressure = 10000

这似乎有所帮助。但是碎片率仍然很高,而 inode 和 dentry 问题的减少意味着我注意到了一些奇怪的事情,这让我想到了……

我的问题:

为什么我有这么多的 blkdev_requests(它们一直处于活动状态),而当我删除缓存时它们就会消失?

我的意思是:

# slabtop -o -s c | head -20
 Active / Total Objects (% used)    : 19362505 / 19431176 (99.6%)
 Active / Total Slabs (% used)      : 452161 / 452161 (100.0%)
 Active / Total Caches (% used)     : 72 / 100 (72.0%)
 Active / Total Size (% used)       : 5897855.81K / 5925572.61K (99.5%)
 Minimum / Average / Maximum Object : 0.01K / 0.30K / 15.69K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
2565024 2565017  99%    1.00K  80157       32   2565024K xfs_inode              
3295194 3295194 100%    0.38K  78457       42   1255312K blkdev_requests        
3428838 3399527  99%    0.19K  81639       42    653112K dentry                 
5681088 5680492  99%    0.06K  88767       64    355068K kmalloc-64             
2901366 2897861  99%    0.10K  74394       39    297576K buffer_head            
 34148  34111  99%    8.00K   8537        4    273184K kmalloc-8192           
334768 334711  99%    0.57K  11956       28    191296K radix_tree_node        
614959 614959 100%    0.15K  11603       53     92824K xfs_ili                
 21263  19538  91%    2.84K   1933       11     61856K task_struct            
 18720  18636  99%    2.00K   1170       16     37440K kmalloc-2048           
 32032  25326  79%    1.00K   1001       32     32032K kmalloc-1024           
 10234   9202  89%    1.88K    602       17     19264K TCP                    
 22152  19765  89%    0.81K    568       39     18176K task_xstate

# echo 2 > /proc/sys/vm/drop_caches                                                                                                                                                   :(
# slabtop -o -s c | head -20       
 Active / Total Objects (% used)    : 965742 / 2593182 (37.2%)
 Active / Total Slabs (% used)      : 69451 / 69451 (100.0%)
 Active / Total Caches (% used)     : 72 / 100 (72.0%)
 Active / Total Size (% used)       : 551271.96K / 855029.41K (64.5%)
 Minimum / Average / Maximum Object : 0.01K / 0.33K / 15.69K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 34140  34115  99%    8.00K   8535        4    273120K kmalloc-8192           
143444  20166  14%    0.57K   5123       28     81968K radix_tree_node        
768729 224574  29%    0.10K  19711       39     78844K buffer_head            
 73280   8287  11%    1.00K   2290       32     73280K xfs_inode              
 21263  19529  91%    2.84K   1933       11     61856K task_struct            
686848  97798  14%    0.06K  10732       64     42928K kmalloc-64             
223902  41010  18%    0.19K   5331       42     42648K dentry                 
 32032  23282  72%    1.00K   1001       32     32032K kmalloc-1024           
 10234   9211  90%    1.88K    602       17     19264K TCP                    
 22152  19924  89%    0.81K    568       39     18176K task_xstate            
 69216  59714  86%    0.25K   2163       32     17304K kmalloc-256            
 98421  23541  23%    0.15K   1857       53     14856K xfs_ili                
  5600   2915  52%    2.00K    350       16     11200K kmalloc-2048           

这告诉我,blkdev_request 的构建是不是实际上与脏页有关,而且活动对象实际上并不活动?如果这些对象实际上没有被使用,如何释放它们?这是怎么回事?

作为背景介绍,以下是 drop_caches 所做的事情:

http://lxr.free-electrons.com/source/fs/drop_caches.c

更新:

算出来它们可能不是 blkdev_requests,但可能是出现在该“标题”下的 xfs_buf 条目?不确定这是如何工作的:

/sys/kernel/slab # ls -l blkdev_requests(
lrwxrwxrwx 1 root root 0 Nov  7 23:18 blkdev_requests -> :t-0000384/

/sys/kernel/slab # ls -l | grep 384
lrwxrwxrwx 1 root root 0 Nov  7 23:18 blkdev_requests -> :t-0000384/
lrwxrwxrwx 1 root root 0 Nov  7 23:19 ip6_dst_cache -> :t-0000384/
drwxr-xr-x 2 root root 0 Nov  7 23:18 :t-0000384/
lrwxrwxrwx 1 root root 0 Nov  7 23:19 xfs_buf -> :t-0000384/

我仍然不知道为什么这些会被“drop_slabs”清除,或者如何找出导致这种碎片的原因。

附加问题:有什么更好的方法可以找到这种碎片的根源?

如果您读到这里,感谢您的关注!

额外要求的信息:

内存和 xfs 信息: https://gist.github.com/christian-marie/f417cc3134544544a8d1

页面分配失败: https://gist.github.com/christian-marie/7bc845d2da7847534104

跟进:性能信息和压缩相关的事情

http://ponies.io/raw/compaction.png

压缩代码似乎有点低效,是吧?我拼凑了一些代码来尝试复制失败的压缩:https://gist.github.com/christian-marie/cde7e80c5edb889da541

这似乎重现了该问题。

我还要指出的是,事件跟踪告诉我有很多次回收失败,一遍又一遍:

<...>-322 [023] .... 19509.445609: mm_vmscan_direct_reclaim_end: nr_reclaimed=1

Vmstat 的输出也令人担忧。当系统处于高负载状态时,压缩会急剧增加(并且大多数都会失败):

pgmigrate_success 38760827 pgmigrate_fail 350700119 compact_migrate_scanned 301784730 compact_free_scanned 204838172846 compact_isolated 18711615 compact_stall 270115 compact_fail 244488 compact_success 25212

回收/压缩过程中确实存在一些问题。

目前,我正在考虑通过为 ipoib 设置添加 SG 支持来减少高阶分配。真正的问题似乎可能与 vmscan 有关。

这很有趣,并引用了这个问题:http://marc.info/?l=linux-mm&m=141607142529562&w=2

答案1

因为有很多评论,我想根据我的观察给出答案。

根据您的输出https://gist.github.com/christian-marie/7bc845d2da7847534104

我们可以确定以下内容:

  1. 尝试的内存分配的 GFP_MASK 可以执行以下操作。
    • 可以进入紧急池(I思考这意味着访问区域高水位以下的数据)
    • 不要使用紧急储备(我思考这意味着不允许访问低于最小水位的内存)
    • 从其中一个正常区域分配。
    • 可以交换以腾出空间。
    • 可以删除缓存以腾出空间。

区域碎片位于此处:

[3443189.780792] Node 0 Normal: 3300*4kB (UEM) 8396*8kB (UEM) 4218*16kB (UEM) 76*32kB (UEM) 12*64kB (M) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 151056kB
[3443189.780801] Node 1 Normal: 26667*4kB (UEM) 6084*8kB (UEM) 2040*16kB (UEM) 96*32kB (UEM) 22*64kB (UEM) 4*128kB (U) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 192972kB

当时的内存使用情况如下:

[3443189.780759] Node 0 Normal free:149520kB min:40952kB low:51188kB high:61428kB active_anon:9694208kB inactive_anon:1054236kB active_file:7065912kB inactive_file:7172412kB unevictable:0kB isolated(anon):5452kB isolated(file):3616kB present:30408704kB managed:29881160kB mlocked:0kB dirty:0kB writeback:0kB mapped:25440kB shmem:743788kB slab_reclaimable:1362240kB slab_unreclaimable:783096kB kernel_stack:29488kB pagetables:43748kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[3443189.780766] Node 1 Normal free:191444kB min:45264kB low:56580kB high:67896kB active_anon:11371988kB inactive_anon:1172444kB active_file:8084140kB inactive_file:8556980kB unevictable:0kB isolated(anon):4388kB isolated(file):4676kB present:33554432kB managed:33026648kB mlocked:0kB dirty:0kB writeback:0kB mapped:45400kB shmem:2263296kB slab_reclaimable:1606604kB slab_unreclaimable:438220kB kernel_stack:55936kB pagetables:44944kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no

在页面分配失败输出中,每个区域的碎片情况都很糟糕。有很多空闲的 0 阶页面,而高阶页面则少得多甚至没有。“好”的结果将是每个阶都有充足的空闲页面,阶数越高,空闲页面的大小就越小。如果高阶页面 5 及以上为 0,则表示高阶分配存在碎片和匮乏。

我目前没有看到令人信服的证据表明此期间的碎片与 slab 缓存有关。在生成的内存统计数据中,我们可以看到以下内容

Node 0 = active_anon:9694208kB inactive_anon:1054236kB
Node 1 = active anon:11371988kB inactive_anon:1172444kB

用户空间没有分配大页面,因此用户空间将始终占用 0 阶内存。因此,两个区域总共有超过 22GiB 的可碎片整理内存。

我无法解释的行为

当高阶分配失败时,我的理解是内存压缩是总是尝试允许高阶内存分配区域发生并成功。为什么没有发生这种情况?如果确实发生了,为什么在有 22GiB 内存可供重新排序时找不到任何内存进行碎片整理?

我认为我可以解释的行为

这需要更多研究才能正确理解,但我相信自动交换/删除一些页面缓存的分配能力可能不适用于此,因为仍然有大量可用内存,因此不会发生回收。只是在高阶中还不够。

虽然有大量可用内存每个区域中剩余一些订单 4 请求,“每个订单的所有可用内存总计并从实际可用内存中扣除”问题导致“可用内存”低于“最小”水位,这导致实际分配失败。

答案2

我们在 IP over IB 上使用 Ceph 时遇到了同样的 TX 数据包丢失问题。在我们的案例中,问题是由于 MTU 大小过大(64K)造成的。有人选择了较大的 MTU 大小(64K)来提高吞吐量。但是,当我们长时间运行 Ceph 并承受大量负载时,由于许多 TX 数据包丢失,吞吐量和 osd 延迟变得更糟。当我们将 MTU 大小更改为 9K 时,吞吐量和延迟变得稳定。我们还在考虑根据以下文章将 MTU 大小减小到 8K。 https://www.ibm.com/support/knowledgecenter/en/linuxonibm/liaag/wehs/l0wehs00_otherconfigurationconsiderationoptimalmtusize.htm

相关内容