如何在香港服务器的Windows Server上部署DFS-R,解决多机房文件一致性与复制延迟?

凌晨 1:40,我站在香港将军澳机房 7 排 18 柜前,HK-FS01 的硬盘灯一串常亮。监控板上 SMB 写入时延一路红到 600 ms,dfsrdiag backlog 定格在 12,847 条;Teams 里设计部还在追问:深圳刚改过的模型,香港看到的却还是三小时前的版本,新加坡干脆把共享盘拖到本地改。继续靠临时脚本对拷、手工比时间戳只会越救越乱,我当场拍板:上 DFS 命名空间 + DFS-R,做统一入口、按站点就近命中,把复制延迟从“小时级”拉回“分钟级”。我把变更单摊在机柜门上,确定以香港 HK-FS01 为 Hub,深圳 SZ-FS01、新加坡 SG-FS01 为 Spoke,先预置数据、再分时限速——今晚先把这口子止住。
一、现场与目标
站点与链路(真实数值取平均):
| 站点 | 服务器 | 系统/角色 | 连接带宽 | 单向 RTT | 备注 |
|---|---|---|---|---|---|
| 香港(HK) | HK-FS01 |
Windows Server 2022 Datacenter,AD 成员,文件+DFS 根 | 专线 1 Gbps | 14–18 ms 到深圳;45–60 ms 到新加坡 | Hub |
| 深圳(SZ) | SZ-FS01 |
Windows Server 2019 Standard,AD 成员,文件+DFS | 专线 500 Mbps | 14–18 ms 到香港 | Spoke |
| 新加坡(SG) | SG-FS01 |
Windows Server 2022 Standard,AD 成员,文件+DFS | 专线 300 Mbps | 45–60 ms 到香港 | Spoke |
文件结构与体量:
- 共享根:\\contoso.local\Files
- 关键文件夹:Projects(~800 GB,70 万小文件 + 少量 4–20 GB 的视频/贴图)、Assets、Docs
- RPO(允许的数据滞后):10 分钟内
- RTO(现场故障切换):< 30 分钟
- 约束:不改变用户访问路径,周间白天业务高峰需限速,夜间可放开
方案目标:
- 统一入口:使用 域型 DFS 命名空间(Domain-based DFSN),站点就近访问。
- 多主复制:使用 DFS-R 在 HK⇄SZ⇄SG 之间做 Hub-and-Spoke(HK 为 Hub)。
- 复制优化:RDC 差异复制、大文件预置(pre-seeding)、分时限速、增大 staging/conflict 配额。
- 可观测性:Backlog 可视化、事件订阅、性能计数器告警。
二、前置检查(别跳过,这些坑我都踩过)
域与 DNS:三台都加入同一 AD 域;站点与子网在“Active Directory 站点和服务”里正确映射。
时间同步:域控对上上游 NTP,成员机与域控对时(DFS-R 对时钟非常敏感)。
卷与路径一致:各站点共享路径保持一致的盘符与目录(例如 D:\Shares\Projects)。
防火墙端口:SMB 445/TCP,RPC 135/TCP,WMI 与 RPC 动态端口(默认 49152–65535/TCP)。
杀软/EDR 排除:排除 D:\Shares\*\DfsrPrivate\*、System Volume Information\DFSR\*、DFS 服务进程。
USN 日志:确保 NTFS USN 日志开启且足够大(大工作集强烈建议手动扩容)。
fsutil usn queryjournal D:
fsutil usn createjournal m=1073741824 a=1073741824 D:
m 与 a 分别是最大与分配大小(此处 1GB/1GB),视体量可上 2–4GB。
不适合 DFS-R 的文件:持续打开/写入的数据库、PST、虚机磁盘(VHDX)等,建议 排除 或改用应用层复制/对象存储。
三、设计要点(为什么这么配)
拓扑:Hub-and-Spoke
- 全互联在三站点时会产生 N*(N-1) 链路与冲突复杂度;以 HK 为中心,SZ/SG 只与 HK 互联,降低冲突面,也便于限流和排障。
命名空间:域型 DFSN + 站点感知
- 客户端访问 \\contoso.local\Files\Projects,DFS 根据站点成本把就近的 \\HK-FS01\Projects$、\\SZ-FS01\Projects$、\\SG-FS01\Projects$ 下发为优先顺序。
复制策略:多主 + 边缘只读(可选)
- 设计/产出在深圳较多,我将 Projects 设为多主;Assets 在 SG 只读(防止边缘误改)。
staging 与冲突目录配额
- staging 配额建议 ≥ 1.5×最大单文件 或 ≥ 8–32 GB 起步(我们设 32 GB)。
- conflictAndDeleted 配额 8–16 GB(我们设 16 GB)。
文件筛选
- 排除临时与巨型不适合同步的文件,减少无效流量与冲突。
~$*; *.tmp; *.bak; *.iso; *.vhdx; *.pst; Thumbs.db; .git\*; .cache\*
分时限速
- 周一–周五 09:00–20:00:每连接限 25 Mbps(25600 Kbps)
- 其余时间:不限速(“无限制”)
四、实施步骤(带命令与我当时的操作手法)
1)安装角色与管理工具(所有文件服务器)
# 以管理员 PowerShell 运行
Install-WindowsFeature FS-DFS-Namespace, FS-DFS-Replication, RSAT-DFS-Mgmt-Con -IncludeManagementTools -Restart:$false
2)创建共享与权限(三台一致)
New-Item -ItemType Directory -Path 'D:\Shares\Projects' -Force | Out-Null
New-SmbShare -Name 'Projects$' -Path 'D:\Shares\Projects' -FullAccess 'CONTOSO\Domain Admins' -ChangeAccess 'CONTOSO\Designers' -ReadAccess 'CONTOSO\Domain Users'
# 启用 ABE(基于访问的枚举)
Set-SmbShare -Name 'Projects$' -FolderEnumerationMode AccessBased
注意:NTFS ACL 与共享权限要一致、可继承清晰;跨站点复制 ACL 的变更本身也会触发复制。
3)创建域型 DFS 命名空间与文件夹
# 在 HK-FS01 上执行一次即可
Import-Module DFSN
# 创建域型根:\\contoso.local\Files ,并在 HK-FS01 挂载为命名空间服务器
New-DfsnRoot -TargetPath "\\HK-FS01\Files$" -Type DomainV2 -Path "\\contoso.local\Files" -Description "Global File Namespace"
# 将 SZ 与 SG 作为命名空间服务器加入,提升可用性
New-DfsnRootTarget -Path "\\contoso.local\Files" -TargetPath "\\SZ-FS01\Files$"
New-DfsnRootTarget -Path "\\contoso.local\Files" -TargetPath "\\SG-FS01\Files$"
# 在命名空间下创建逻辑文件夹,并挂上三地实际共享作为目标
New-DfsnFolder -Path "\\contoso.local\Files\Projects" -TargetPath "\\HK-FS01\Projects$"
New-DfsnFolderTarget -Path "\\contoso.local\Files\Projects" -TargetPath "\\SZ-FS01\Projects$"
New-DfsnFolderTarget -Path "\\contoso.local\Files\Projects" -TargetPath "\\SG-FS01\Projects$"
# 启用站点感知与故障恢复
Set-DfsnRoot -Path "\\contoso.local\Files" -EnableSiteCosting $true -EnableTargetFailback $true
如果 Files$ 只是命名空间根的占位共享,可设为仅管理员可见;业务访问走 \\contoso.local\Files\Projects。
4)DFS-R 复制组与成员(Hub-and-Spoke)
这一步我用 GUI(DFS 管理器)做连接的分时限速更直观;其余用 PowerShell。
Import-Module DFSR
# 新建复制组
New-DfsReplicationGroup -GroupName "RG-Projects"
# 添加成员
Add-DfsrMember -GroupName "RG-Projects" -ComputerName "HK-FS01","SZ-FS01","SG-FS01"
# 添加要复制的文件夹(逻辑名)
New-DfsReplicatedFolder -GroupName "RG-Projects" -FolderName "Projects"
# 设定每个成员的本地路径(与共享一致)
Set-DfsrMembership -GroupName "RG-Projects" -FolderName "Projects" -ComputerName "HK-FS01" -ContentPath "D:\Shares\Projects" -PrimaryMember $true
Set-DfsrMembership -GroupName "RG-Projects" -FolderName "Projects" -ComputerName "SZ-FS01" -ContentPath "D:\Shares\Projects"
Set-DfsrMembership -GroupName "RG-Projects" -FolderName "Projects" -ComputerName "SG-FS01" -ContentPath "D:\Shares\Projects"
# 建立 Hub(HK)<-> Spoke 的连接
Add-DfsrConnection -GroupName "RG-Projects" -SourceComputerName "HK-FS01" -DestinationComputerName "SZ-FS01" -Description "HK<->SZ"
Add-DfsrConnection -GroupName "RG-Projects" -SourceComputerName "HK-FS01" -DestinationComputerName "SG-FS01" -Description "HK<->SG"
为什么把 HK 设为 PrimaryMember:初始基线(初始状态)以 HK 为准,减少首次同步冲突。
5)文件预置(Pre-seeding,极大缩短初次同步)
我在业务低谷先从 HK 拷一遍到 SZ/SG,并保留 ACL 与时间戳,DFS-R 会做哈希比对,只传差异。
:: 在 SZ-FS01 / SG-FS01 上,以管理员 CMD 运行
robocopy \\HK-FS01\Projects$ D:\Shares\Projects /MIR /COPYALL /DCOPY:T /R:0 /W:0 /MT:32 /XJ /XD "D:\Shares\Projects\DfsrPrivate" /LOG:C:\preseed_projects.log
/MIR 镜像同步;/COPYALL 保留所有属性与 ACL;/DCOPY:T 保留目录时间戳;/MT 多线程加速。
不要复制 DfsrPrivate。
可抽样对比哈希确认预置效果:
dfsrdiag filehash /path:"D:\Shares\Projects\某大文件.dat"
6)staging 与冲突目录调优
# staging 32 GB,冲突与已删除 16 GB(按容量与文件规模适当增减)
Set-DfsrMembership -GroupName "RG-Projects" -FolderName "Projects" -ComputerName "HK-FS01" -StagingPath "D:\Shares\Projects\DfsrPrivate\Staging" -StagingPathQuotaInMB 32768 -ConflictAndDeletedQuotaInMB 16384
Set-DfsrMembership -GroupName "RG-Projects" -FolderName "Projects" -ComputerName "SZ-FS01" -StagingPathQuotaInMB 32768 -ConflictAndDeletedQuotaInMB 16384
Set-DfsrMembership -GroupName "RG-Projects" -FolderName "Projects" -ComputerName "SG-FS01" -StagingPathQuotaInMB 32768 -ConflictAndDeletedQuotaInMB 16384
7)文件筛选与只读边缘(可选)
在 DFS 管理器 → 复制组 → “Projects” → 属性 → “文件筛选器”:
~$*; *.tmp; *.bak; *.iso; *.vhdx; *.pst; Thumbs.db; .git\*; .cache\*
将 Assets 文件夹在 SG 设为 Read-Only 成员(GUI 勾选),防止边缘误改。
8)分时限速(建议用 GUI 配时段图,更直观)
连接属性(HK↔SZ、HK↔SG)→ 计划:
周一–周五 09:00–20:00:自定义带宽 25600 Kbps
其它时间段:不限制
这样白天不挤占设计师的 SMB 在线编辑体验,晚上快速追平 backlog。
9)让 DFS-R 读取配置并开始跑
# 促使成员尽快拉取 AD 中的 DFS-R 配置
dfsrdiag PollAD /Member:HK-FS01
dfsrdiag PollAD /Member:SZ-FS01
dfsrdiag PollAD /Member:SG-FS01
五、验收与观测(我怎么判断“好了”)
即时 backlog(是否还有未复制的变更)
dfsrdiag backlog /rgname:RG-Projects /rfname:Projects /smem:HK-FS01 /rmem:SZ-FS01
dfsrdiag backlog /rgname:RG-Projects /rfname:Projects /smem:HK-FS01 /rmem:SG-FS01
也可 PowerShell:
Get-DfsrBacklog -GroupName "RG-Projects" -FolderName "Projects" -SourceComputerName "HK-FS01" -DestinationComputerName "SZ-FS01" | Measure-Object
复制状态快照
dfsrdiag replstate
事件日志(常用事件与含义)
| 事件 ID | 含义 | 我当时如何处理 |
|---|---|---|
| 4102/4104 | 开始/完成与伙伴的同步 | 初次建立后看到 4102→4104 基本安心 |
| 2213 | 非正常关机后复制被挂起 | 用 WMI 恢复(见下) |
| 2212/2214 | 数据库损坏/重建 | 等其重建,观察磁盘与 CPU;预置能减少概率 |
| 4012 | 拒绝连接(拓扑不一致/伙伴未准备好) | 检查 AD 复制、PollAD、连接方向 |
| 5002/5004 | staging 清理/失败 | 增大 staging 或排除巨型文件 |
快速筛选 DFSR 事件:
Get-WinEvent -LogName "DFS Replication" -MaxEvents 50 | Select TimeCreated, Id, LevelDisplayName, Message
性能计数器(PerfMon 建议)
DFS Replicated Folders:Files Installed、Staging Bytes Generated
DFS Replication Connections:Bytes Sent、Compressed Size
Network Interface:带宽利用
Logical Disk:staging/冲突分区的写入队列
六、那些夜里遇到的坑与处理手记
2213:复制停止(我们在 SZ 突发断电)
观察到 SZ 机器报 2213。解决:
# 查询卷 GUID
wmic /namespace:\\root\microsoftdfs path dfsrVolumeConfig get volumeGuid,RootPath
# 恢复复制(替换为实际 GUID)
wmic /namespace:\\root\microsoftdfs path dfsrVolumeConfig where volumeGuid="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" call ResumeReplication
恢复后 dfsrdiag replstate 出现流动,事件 4102 随后出现。
初次同步“卡 0%”
其实是我们没有 pre-seed 完整,ACL/时间戳不一致导致重复比对,改用上面 robocopy 参数后顺利推进。
白天“保存很慢”
白天限速没配,HK↔SZ 链路被 DFS-R 与 SMB 抢带宽。按上面的 分时限速 后,用户编辑明显顺畅。
staging 爆满
大视频频繁改名/剪辑,staging 清理跟不上。把 staging 从 8GB 提到 32GB,并排除 .iso/.vhdx。
杀软误杀 DFSRPrivate
SG 的 EDR 把 DfsrPrivate 扫描当作可疑高 IO,拉黑了 DFSR。将 DfsrPrivate 与 System Volume Information\DFSR 加白名单解决。
AD 站点没配对
客户端在深圳却拿到香港的目标优先,改了 AD 站点与子网映射,DFS 命名空间的站点感知才真正生效。
七、数据与效果(上线一周后的量化)
| 指标 | 上线前 | 上线后(白天限速/夜间放开) |
|---|---|---|
Projects 平均复制延迟 |
2–3 小时 | 3–8 分钟(白天) / <1 分钟(夜间) |
| 初次基线用时(800 GB) | 约 20 小时(纯复制) | 4 小时(pre-seed + 校验) |
| 白天用户 SMB 写入平均时延 | 明显抖动(> 500 ms) | 稳定在 50–120 ms |
| 事件告警(2213/5004 等) | 偶发频繁 | 趋于 0(偶有 4102/4104 正常提示) |
八、运维清单(上线/日常/变更)
上线当天
- dfsrdiag backlog 观测至 <100 条 且持续下降
- 抽查 10 个大文件的哈希一致
- 客户端随机抽样打开 \\contoso.local\Files\Projects 验证就近访问
日常(每周)
- 检查事件日志(筛 5000+ 级别)
- 观察 PerfMon:连接压缩率、staging 生成速率
- 盘空间:DfsrPrivate 所在卷保持 > 20% 可用
变更(大批量导入/重构目录前)
- 临时提高 staging 到 48–64 GB
- 改为“夜间不限速、白天 10–15 Mbps”
- 写邮件/群里发布“变更窗”与可能的延迟
九、FAQ(同事们最常问)
DFS-R 会复制文件的“打开中”状态吗?
不会,关闭后才复制;持续写入型文件建议排除。
RDC(远程差异压缩)要不要关?
大多数场景 保留开启 很值,尤其跨站点;CPU 非常弱或全是小文件时,收益有限。
能不能只读边缘?
可以,把边缘成员设为 Read-Only,用于分发类内容(例如 Assets)。
多站点冲突谁赢?
DFS-R 是“最后写入赢”(Last-Writer-Wins),冲突副本会丢到 ConflictAndDeleted,所以 staging 与冲突目录配额要足够大,避免被回收过快。
十、收尾:再回机房那天
两周后我又回到机房,不是因为报警,而是去关掉临时的高水位监控。走廊里仍然很冷,风从机柜前后穿过去。工单里设计团队留言:“现在 \\Files\Projects 随便在哪个办公室打开都一样了。”
我把三地 backlog 又看了一遍,SZ 和 SG 都是个位数,HK 的计数器时不时跳一下,然后回到 0。那一刻我知道,我们从折腾到稳定,只差一份坚持的日常运维了。
附录:常用命令速查
# 促使 DFS-R 成员立即读取配置
dfsrdiag PollAD /Member:HK-FS01
# 查看复制状态(正在传哪些文件)
dfsrdiag ReplState
# 查看 backlog(源 -> 目的)
dfsrdiag Backlog /rgname:RG-Projects /rfname:Projects /smem:HK-FS01 /rmem:SZ-FS01
# 事件快速查看
Get-WinEvent -LogName "DFS Replication" -MaxEvents 100 | Format-Table TimeCreated, Id, LevelDisplayName -Auto
# 抽样文件哈希
dfsrdiag filehash /path:"D:\Shares\Projects\bigfile.mov"
参数与配置表(可作为变更记录附件)
| 项目 | 值 |
|---|---|
| DFSN 根 | \\contoso.local\Files(域型 V2) |
| DFSN 目标 | \\HK-FS01\Files$、\\SZ-FS01\Files$、\\SG-FS01\Files$ |
| 复制组/文件夹 | RG-Projects / Projects |
| 成员路径 | 三站点均 D:\Shares\Projects |
| Primary 成员 | HK-FS01 |
| 拓扑 | Hub-and-Spoke(HK↔SZ、HK↔SG) |
| staging 配额 | 32 GB(三站点) |
| 冲突/已删除 配额 | 16 GB(三站点) |
| 文件筛选 | ~$*; *.tmp; *.bak; *.iso; *.vhdx; *.pst; Thumbs.db; .git\*; .cache\* |
| 限速(工作日 09:00–20:00) | 25 Mbps/连接 |
| 限速(其余时间) | 不限制 |
| USN 日志 | 每卷 1–2 GB |
| 监控 | backlog、事件 2213/4102/5004、PerfMon |
如果你的环境与我这里不完全一致(比如:无专线、VPN 走公网、服务器版本混用、文件量更大/更小),上面的思路依然适用:命名空间统一入口 + 复制拓扑清晰 + 差异复制与预置 + 分时限速 + 可观测性闭环。