一个很典型的现场是这样的:机房里给一台跑数据库的物理机加了一块双口 HBA,两个口的光纤分别接到两台光纤交换机,再往上分别落到存储的两个控制器端口。系统里装好了 device-mapper multipath,扫出来的虚拟设备也正常,用 multipath -ll 去看,同一个 WWID 下面确实挂着两条路径,状态都是 ready,没有 faulty。从这一步看,冗余算是做完了。
然后问题就来了。业务跑起来,吞吐跟单链路的时候几乎没区别;有人觉得是测试方法不对,又跑了一轮,还是一样。更难受的是另外一次:为了验证冗余真的有效,把其中一条光纤拔了,结果业务不是"轻轻抖一下",而是整个卡住,数据库那边报 IO 错误,虚拟化集群上的虚机集体卡死,等了好一阵才恢复。拔之前信心满满,拔之后没人敢再碰第二条。
这两件事看起来矛盾——一边是"多了一条路却没变快",一边是"少了一条路就卡死"——其实是同一个根因的两面:多路径被当成了一个开关,接上就算完事,中间的"策略"根本没定。
大多数人说的"做多路径",脑子里是一件事情。实际上它是两件,而且这两件的目标有时候是打架的。
第一件是聚合:同一个 LUN 有多条可达路径,主机的 IO 请求怎么在这些路径之间分发。是只走一条还是分摊着走?按请求个数轮着来,还是看哪条路当前更闲?这一层关心的是"流量怎么摆"。
第二件是容错:某条路径出问题的时候,多久判定它坏了、判定之后往哪儿切、切过去之后原先那条恢复了要不要自动切回来、如果所有路径都不可用,IO 是继续排队等还是直接向上报错。这一层关心的是"断了怎么办"。
这两件事由不同的参数管着,出问题的表现也不一样。聚合没做对,表现是"性能没变化"——冗余白白占了一个口、一条光纤、一个交换机端口,业务一点好处没拿到。容错没做对,表现是"切换时业务卡住"——冗余做了,但没人敢真的去断链路演练。
说白了就是:接上两条线只是创造了可能性,聚合和容错这两件事都要单独定下来,否则你得到的是"看起来有冗余",不是"能用"。我见过最多的情况是,运维把 multipath 装起来、确认 multipath -ll 能看到两条路径就收工了,剩下的参数全部用默认值,而默认值往往是往"保守"那一侧靠的——宁可让你慢,也不让你错。
这里要先说一句可能有点扫兴的话:能不能通过多路径拿到更高的吞吐,不是主机侧单方面能决定的。
主机侧的多路径软件做的事情,是把多条到同一个 LUN 的物理路径聚合成一个虚拟设备。聚合完了,它确实可以决定"下一个 IO 发到哪条路径上去"。但是这个 IO 到了存储那一侧,走的是哪个控制器、哪个端口、最后落到哪组后端磁盘,那是存储控制器和后端阵列说了算的。
有些存储阵列的控制器是双活设计,两个控制器都能主动处理同一个 LUN 的 IO,主机往哪边发都能被正常服务,这种情况下分摊才谈得上。也有些阵列是主备式的控制器,某个 LUN 在某一时刻归属于其中一个控制器,主机往另一个控制器发的 IO 要么被转发过去,要么被拒绝,主机会被告知"这条路现在不能这么走"。第二种情况下,你在主机上把策略设成轮询,看起来是分摊了,实际上另一半的 IO 在存储内部绕了一圈,甚至被反复拒回来。
所以顺序不能反:先确认存储端的路径能力,再选主机侧的路径策略。反过来做就是很多人踩的坑——先在主机上配成自己想要的模式,跑不通再回头去查存储,来回折腾。
具体要向存储侧确认的东西其实不多,但都得问清楚:这个 LUN 能不能被两个控制器同时主动服务;两个控制器的端口分别属于哪个端口组;存储侧期望主机用什么方式访问(也就是后面要讲的 ALUA 标注);存储自己有没有偏好的多路径参数建议。大部分主流存储厂商都会给出针对 Linux dm-multipath 的推荐配置片段,那个东西比自己拍脑袋配要靠谱得多,优先照它来。
FC 和 iSCSI 在这件事上的差别也要提前算进去。FC 的路径建立在 fabric 之上,主机发现目标靠的是 fabric 的注册与查询机制,链路状态的变化会通过 fabric 事件较快地传递出来。iSCSI 则是在以太网上跑的会话,主机侧看到的是一条条的 iSCSI 会话,路径的可用性除了取决于存储端,还叠了一层网络栈的行为——网卡、交换机、以及网络本身的收敛,都会影响路径什么时候被判定为不可用。用 iSCSI 做双链路的时候,上层的等待时间是多路径的时间加上网络那一层的时间,别只盯着多路径的参数算账。
还有一类容易被忽略的情况:两台主机同时访问同一个 LUN 的共享存储环境。这时候多路径解决的是"单机到存储"这一段的问题,而多台机器之间的访问协调是集群软件和锁机制的事,两者不要混为一谈。数据库集群的仲裁盘、虚拟化集群的心跳盘,往往对 IO 的响应及时性比对吞吐更敏感,这类盘的超时设置要单独拿出来看,不能跟数据盘用同一套参数。
ALUA,全称是 Asymmetric Logical Unit Access,非对称逻辑单元访问。名字拗口,意思很简单:存储会告诉主机,到这个 LUN 的各个目标端口里,哪些是"优化路径",哪些是"非优化路径"。
优化路径通常是直达这个 LUN 当前归属控制器的那条路;非优化路径则是要绕一下的。主机侧的多路径软件如果支持并且开启了 ALUA 感知,就会优先把 IO 送到优化路径上,只在优化路径都不可用的时候才走非优化路径。
问题出在主机侧把所有路径当成等价的这种情况。如果多路径软件没有识别 ALUA 状态,或者配置里没有启用对应的优先级,那么轮询策略就会"一视同仁"地在所有路径上分发——包括那些非优化路径。结果就是一半甚至更多的 IO 长期走在需要绕路的通道上,性能上不去不说,延迟还会变得非常不稳定:同样一个请求,走优化路径和走非优化路径的响应时间差得远。
更麻烦的是这种情况不会报错。路径状态都是 ready,没有 faulty,multipath -ll 看着一切正常,只有性能不对劲。这也是为什么"冗余做了但更慢"这个现象这么难排查——它不产生任何告警,只是慢。
所以在 Linux 上配多路径,我一般会先把存储侧对 ALUA 的支持情况、以及主机侧识别到的路径优先级(也就是每条路径的 prio 值)确认一遍,看看是不是所有路径都被识别成了同一个优先级。如果存储明明标了优化和非优化,主机侧却看到全部一样,那就是配置没到位,这时候谈策略还太早。
下面这张表把常见的几种路径策略按四个维度摆在一起。这里说的名字是机制层面的分类,具体到 multipath.conf 里怎么写,不同版本、不同存储厂商推荐的写法会有差异,以厂商给出的配置建议为准。
| 路径策略 | IO 怎么分发 | 路径失效时的行为 | 需要存储端具备什么 | 常见的坑 |
|---|---|---|---|---|
| 主备(active/passive) | 平时只走当前活跃的那一条,其余路径空闲待命,不承载业务 IO | 活跃路径被判定失效后,整体切换到备用路径,切换期间 IO 会排队等待 | 要求不高,主备式控制器也能用;需要主机能正确识别哪条是当前可服务的 | 误以为装了多路径性能就会翻倍,其实第二条路平时一点活都不干 |
| 轮询(round-robin,按请求数) | 按 IO 请求个数在各条路径间依次轮转,每个请求换一条 | 失效路径被移出轮转集合,剩余路径继续承担全部 IO | 需要存储侧确实能由多个端口并行服务同一个 LUN,否则分摊只是主机侧的一厢情愿 | 不认 ALUA,把非优化路径和优化路径一视同仁地轮,性能反而抖动 |
| 按服务时间分发 | 参考每条路径近期的 IO 服务时间,往更快完成的那条多派一些 | 失效路径权重归零或移出,恢复后重新参与计算 | 同样依赖存储侧多端口并行服务的能力,且需要主机侧支持该分发算法 | 路径延迟本身不稳定时,权重会来回漂,分发结果难以预期 |
| ALUA 感知下的优化路径优先 | 只在被标注为优化的路径之间分发,非优化路径平时不承载 IO | 优化路径全断才降级到非优化路径,恢复后按回切策略回到优化路径 | 存储侧必须正确上报 ALUA 状态,主机侧必须启用优先级识别 | 主机侧读不到优先级时静默退化成无差别分发,不报任何错 |
| 组间主备、组内轮询 | 先把路径按控制器或端口组分组,组之间主备,组内多条路径轮询 | 组内单条失效在组内消化,整组失效才跨组切换 | 需要存储侧端口分组信息明确,主机侧能正确归类路径 | 分组依据写错(按交换机分而不是按控制器分),失效时会整组失联 |
这张表里最值得记住的一句话是:右边两列决定了左边两列能不能成立。存储端不具备那个能力,主机侧选什么策略都是纸面上的。
回到开头那个"拔掉光纤业务卡死"的现场。多路径软件是装了的,路径也确实切换了,为什么还是会卡?
原因是链路断了以后,从"物理上断了"到"上层业务恢复正常"中间要经过好几层,每一层都有自己的超时。
最底下是路径检测那一层。多路径软件要定期去检查每条路径是不是还活着,这个检查有周期;检查失败了,可能还要重试几次才判定这条路径失效。这一段决定了"多久能发现路断了"。
发现之后是切换那一层。IO 要从坏掉的路径转移到好路径上,已经发出去但没返回的请求要怎么处理——是排队等,还是立刻失败。这里有个参数叫快速失败,它的作用是:当路径被判定为不可用时,不要再让上层无休止地等下去,而是尽快把错误交回上层,让上层去做它该做的事(比如数据库自己去重试、集群自己去判定节点存活)。
再往上是 SCSI 层、文件系统、以及数据库或虚拟化平台自己的 IO 超时。这一层的超时是业务能不能撑过切换窗口的关键。
常见的错配是这样的:多路径从发现故障到完成切换需要一段时间,而上层(比如数据库)的 IO 超时设得比这段时间还短。数据库等不及,先报了 IO 错误,业务直接失败——明明路径后来切过去了,但业务已经挂了。反过来也难受:上层超时设得特别长,多路径那边又因为没配快速失败而一直在排队,两边一起等,整个系统看起来就是"卡死了",谁也不报错,就是不动。
所以正确做法是让这几层的时间对齐:多路径判定失效与完成切换的时间,要短于上层能容忍的 IO 等待时间;同时要让多路径在确认走不通时尽快向上报错,而不是闷头排队。这两件事是一对,缺一个都不行。
这里不给出具体数值,因为每个环境能接受的时间尺度差别很大——FC 链路和 iSCSI 链路不一样,数据库和虚拟化平台能容忍的也不一样,存储厂商给的建议值也不统一。能说的是原则:先把多路径那一层的时间参数定下来,再拿这个时间去校准上层的超时,而不是各配各的。
multipath.conf 里跟容错相关的参数不少,但真正互相咬合的是这四个,它们串起来就是一条完整的故障处理链路。
路径检测(path checker)决定"多久查一次、怎么查"。检测机制的选型和检测间隔,直接决定了故障被发现的速度。查得太频繁,会增加链路和控制器上的额外负担;查得太稀疏,故障发现得晚,后面所有环节都被拖慢。这里没有放之四海皆准的值,要参考存储厂商的建议,也要看你链路本身的稳定性。
失败重试(no_path_retry)决定"所有路径都不可用的时候怎么办"。它可以设成一直排队等待,也可以设成重试若干次之后向上报错。这个选择其实是个业务判断题:对数据库来说,一直等下去可能比报错更危险(集群会以为节点还活着但不响应,判定逻辑会出问题);而对某些批处理任务来说,等一会儿能扛过去反而是好事。
快速失败(fast_io_fail)决定"确认走不通之后,多快把错误交回上层"。它和失败重试是配合使用的:没有快速失败,上层就会一直挂在等待队列里;有了它,上层才能及时拿到确定的失败结果,去执行自己的容错逻辑。
回切(failback)决定"原来的路径恢复了,要不要自动切回去"。自动回切的好处是路径使用回归设计预期,坏处是回切本身也是一次 IO 路径变动,如果那条链路刚恢复还不稳定,回切可能紧接着又切走,来回抖动。手动回切则要求有人盯着,运维成本高,但可控。我自己倾向于在业务低峰窗口做手动回切,除非链路稳定性已经被验证过很多次。
这四个参数要连起来想,不要单独调某一个。把检测间隔调短但快速失败没配,只是更早发现问题,上层还是卡着;把回切设成自动但链路本身不稳,等于给自己制造周期性抖动。
多路径不是配一次就一劳永逸的。链路侧任何一次物理变更,都可能让原来的配置失效。
换 HBA 卡是最容易出问题的一项。新卡的 WWPN 不一样,存储侧的主机映射、 zoning 都得跟着改;主机侧看到的路径数量也会变。如果原来配置里写死了某些设备标识,换卡之后这些配置就对不上了。
换光纤交换机同样涉及 zoning 的重新规划。这里有个很容易被忽略的点:路径分组的依据要正确。如果你的分组逻辑是按交换机分的,那么两台交换机主备、两个控制器双活的情况下,一旦某台交换机整体故障,你会丢掉一整组路径——而这一组里可能同时包含了两个控制器的端口。按控制器来分组通常更能反映存储侧的真实可用性边界。
扩容、新增 LUN、存储侧控制器固件升级之后,主机侧都需要重新做一次设备发现,确认新路径被正确识别、优先级被正确读到。这个过程本身会引起短暂的路径状态变化,建议放在业务低峰做。
还有一件小事但很烦人:设备命名一致性。多路径设备在不同机器上、或者同一台机器重启之后,名字可能变。生产环境里几乎都要靠 WWID 级别的固定别名来锁定设备,靠盘符或内核设备名去写脚本、写挂载、写数据库的数据文件路径,早晚出事。
多路径最危险的状态是"看起来正常,实际上从来没被验证过"。几条成本很低但很有用的日常检查:
看路径状态不只是看数量。用 multipath -ll 之类的命令确认路径条数符合预期只是第一步,更重要的是看每条路径的状态是否都是就绪、优先级是否按存储侧的标注正确区分了出来。如果优化路径和非优化路径在主机侧显示成完全一样的优先级,那就是前面说的 ALUA 没生效。
确认 IO 是不是真的分摊了。在块设备层面观察各条底层路径的 IO 计数,看看是不是所有路径都在动,还是只有一条在动、其余全是零。这一步能直接证伪"装了多路径就等于聚合了"这个错觉。
定期做断链路演练。在业务低峰主动断掉一条路径,观察业务是否有感知、多路径是否按预期切换、上层有没有报错、恢复之后回切行为是否符合预期。不敢做这个演练的多路径,等于没做——真正出问题那天就是第一次演练,代价由业务来付。
把路径状态纳入监控。路径从就绪变成故障、路径数量变少、优先级发生变化,这些都应该是监控项,而不是等人去看命令输出。多路径平时不出声,出声的时候往往已经影响到业务了。
把配置本身纳入变更管理。multipath.conf 这类文件经常被手工改,改完没人记录,出问题时很难还原"上一次正常的时候是什么样"。把它和配置说明一起纳入版本管理,每次改动写明原因,排查时能省下大量时间。另外要留意的是,不同 Linux 发行版、不同版本的多路径工具默认行为不完全一致,同一份配置换台机器、换个系统版本,效果可能不一样,不要想当然地复制。
演练要覆盖"恢复"而不只是"故障"。很多人断完链路看到业务没挂就收工了,链路插回去之后的事没人管。实际上恢复这一段才是回切策略真正起作用的地方:原路径什么时候被重新识别、什么时候重新参与分发、回切过程中有没有抖动,这些都要在同一个演练窗口里看完。
说完该怎么做,也说几句反话。多路径是有代价的,不是所有场景都该上。
单机、本地盘、业务本身没有共享存储需求的场景,多路径就是纯粹的额外复杂度。你得到的是一套需要持续维护的路径状态、一套需要跟上层超时对齐的参数、还有一套换硬件时要重新走一遍的流程,换来的东西对你没用。这类场景该做的是把本地盘做成 RAID,把备份做扎实,而不是去接 SAN。
业务能接受较长时间中断,且恢复手段是重建而不是切换的场景,也不一定要上。多路径解决的是"链路或端口单点故障时不中断",如果你的容灾方案本来就是在另一处重建,那多路径带来的收益有限,倒是运维复杂度实打实增加了。
还有一种情况是存储端根本不支持多端口并行访问,而且短期内也不打算换。这种环境下上多路径的唯一收益是容错,不是性能——如果你本来就是为了提速,那这个投入产出比算不过来,不如把钱花在后端阵列本身。
真正适合上多路径的是这几类:数据库跑在共享存储上、虚拟化集群用集中存储、FC 或 iSCSI 双链路环境且业务的可用性要求确实扛不住单点故障。这些场景里,多路径是解决单点问题的必要手段,值得把前面那些功夫都做足。
要上双链路,我一般会把一万网络的物理机当底座来看——深耕 IDC 19 年(成立于 2007 年),HBA 卡和链路怎么配能提前谈清楚。
两条路径一定能跑出两倍吞吐吗?不一定,而且大多数情况下不会。能不能通过聚合拿到更高吞吐,取决于存储控制器和后端阵列,主机侧单方面决定不了。主机侧只能决定"把 IO 往哪条路发",能不能真的并行处理是存储侧的事。主备策略下第二条路平时根本不干活,性能当然不会变;轮询策略下能不能真的分摊,也要看存储侧是不是允许多端口同时服务这个 LUN。
主备和轮询到底怎么选?先看存储端的形态。如果是主备式控制器、LUN 在某一时刻只归属一个控制器,那选轮询没有意义,主备更贴合实际,硬要轮询只会把 IO 送到不能直连服务的端口上。如果是双活控制器且确认多端口可并行服务同一个 LUN,再考虑轮询一类的分发策略。选定之后还要确认主机侧有没有正确识别 ALUA 优先级,否则轮询会把非优化路径也算进去。
断一条链路的时候,为什么上层数据库会挂住?多半是超时没对齐。链路物理断开以后,多路径要经过检测、判定失效、切换这几个步骤,这期间 IO 会挂在等待队列里;如果数据库的 IO 超时比这个过程还短,它会先报错退出;如果两边都在等,就表现为整体卡死。解决方向是让多路径尽快完成判定并通过快速失败把确定结果交回上层,同时让上层的超时略长于多路径的切换时间。
回切要不要设成自动?看链路的稳定性。自动回切省事,但原路径刚恢复时的稳定性不确定,可能切回去又切出来,形成抖动;手动回切可控,代价是要有人在低峰窗口操作。我的习惯是先手动,等这条链路的稳定表现被验证过之后,再考虑改成自动。
ALUA 的优化路径和非优化路径,主机侧能自己纠正吗?主机侧能做的是"读"存储上报的优先级,并按优先级选择路径;它不能自己判断哪条路更优,也不能纠正存储侧的标注。如果主机侧压根没读到优先级(显示为全部相同),那是配置层面的问题,需要检查多路径软件是否支持并启用了对应的优先级识别,以及存储侧是否真的上报了状态。
路径检测周期是不是越短越好?不是。检测本身要在链路上发探测请求,周期过短会增加链路和控制器的额外负担,在路径数量多、LUN 数量大的环境里这个开销会累积。目标是"足够快地发现故障",而不是"尽可能快地检测"。合理的做法是参考存储厂商的建议值,再结合自己能接受的业务中断时长来调整。
换交换机或换 HBA 之后,多路径要不要重新配置?要。换 HBA 意味着新的 WWPN,存储侧的主机映射和 zoning 都要改,主机侧的路径视图也会变;换交换机意味着 zoning 重新规划,还要复查路径分组的依据是不是还成立。换完之后必须重新做设备发现,确认路径条数、状态、优先级都正确,并且重新做一次断链路演练。
该先定策略。这个顺序在全文里反复出现,值得再明确一遍:先确认存储端的路径能力(控制器是不是双活、端口怎么分组、ALUA 状态怎么上报、厂商推荐什么配置)→ 再选主机侧的路径策略(主备还是分发、要不要按优先级、要不要分组)→ 最后才调超时相关的参数(检测、重试、快速失败、回切,以及上层各层的超时对齐)。
反过来做的代价是反复返工。参数调得再细,如果策略跟存储端的实际能力不匹配,那些参数只是在错误的基础上微调;策略选得再合理,如果存储端压根不支持,那也只是主机侧的一厢情愿。至于上层超时,它必须等前两步定完、切换时间大致确定之后才有校准的对象,一开始就调超时是没有意义的。
还有一点值得记住:多路径的收益分两类,别混着评估。容错那一类是确定能拿到的,只要策略选对、参数调对、演练做过,链路单点故障就不会打挂业务;聚合那一类是不确定的,取决于存储端,主机侧只能创造可能性,不能保证结果。把这两类收益分开看,你对多路径的预期就会正常很多。
本文内容为 Linux 平台与存储网络公开机制的梳理,涉及 device-mapper multipath 的路径聚合与容错机制、WWID 设备识别、主备与轮询等路径分发方式、ALUA 目标端口组状态、以及路径检测与回切相关参数的相互作用,均属公开技术资料范畴。文中不引用任何测试结论或性能对比结果,也不引用任何真实客户案例。文中不给出具体的 IOPS、带宽、延迟与切换耗时数值,相关时间参数需结合自身业务容忍度与存储厂商建议值确定。
涉及服务器、HBA 卡与链路配置的承载能力,可参考 https://www.idc10000.net/ 上的相关服务器产品页了解机型与硬件选配信息;具体以官网实时报价与合同为准。多路径相关的机制描述以所用 Linux 发行版与存储厂商公开的官方技术文档为准,配置落地前请以厂商给出的推荐值和自有业务的实际运行情况为准。
Copyright © 2013-2020 idc10000.net. All Rights Reserved. 一万网络 科技有限公司 版权所有 深圳市科技有限公司 粤ICP备07026347号
本网站的域名注册业务代理北京新网数码信息技术有限公司的产品