某工程总包企业的档案室在 2025 年底做了一次集中数字化:2019 年以来的施工合同、竣工图、监理签认单、验收记录,合计约十二万页,双面扫描、300 dpi、彩色。扫描仪连续跑了六天,操作员看到的界面一直很顺,每一批都提示上传完成。等到第七天业务部门去搜一份 2021 年的补充协议,搜不到——后台 Celery 队列里还压着两万多个任务,OCR 没跑完,全文索引自然也没有建起来。
运维的第一反应是 CPU 不够,把机器从 8 核加到 16 核,队列长度曲线没有变陡。真正的原因有三个叠在一起:扫描件是整批写进存储的,顺序写把磁盘带宽吃满;OCR 进程同时去读这些刚落盘的大文件,随机读把 IOPS 打满;PostgreSQL 在为每一页写元数据与索引条目,WAL 与数据文件争同一组盘。加核只是让 worker 抢 CPU 抢得更凶。
这个场景说明一件事:Mayan EDMS 这类文档管理系统的容量规划,不能照搬网盘或者静态站点的算法。网盘的账是"存多少 GB",文档管理系统的账是"多少页、几个版本、多少条队列任务、索引多大",四本账各自有各自的瓶颈位,而且爆发点不在同一个时间。
下面按入库链路、OCR、版本存储、数据库与检索、存储后端、导入期、备份、队列中间件、内存、扩容窗口十段拆开,末尾用一张四档配置表把口径收拢。所有资源数字都给公式,不给跑分——具体值必须按压测确认。
把这件事拆细看,会发现六个小时里发生的事情比"上传慢"复杂得多。第一天到第三天,扫描端按每批两百页提交,队列长度稳定在几百条,worker 能跟上。第四天开始,档案室为了赶进度把批次提到八百页,队列长度开始单调上升。第六天扫描结束,队列长度两万一千条,此时 CPU 利用率六成出头,磁盘的等待队列已经排到几十。
操作员那里为什么看不出异常?因为上传接口只做接收与落盘,把字节写进存储就返回成功。文档对象建立了、初始版本有了、文件在磁盘上占着空间,界面上一切正常。缺的是 OCR、缩略图和索引——三样都在队列里排着。业务部门搜索时用的是全文索引,索引里没有,就搜不到。
这里有个反常识的地方:队列积压严重的时候,磁盘水位看起来反而"健康",因为文件确实都落下来了,只是没被处理。用磁盘使用率判断导入进度,会得出完全错误的结论。应该看的是"每小时完成页数"和"队列等待时间的分布",前者告诉你消化速度,后者告诉你最老的任务等了多久。
还有一个隐性代价:任务在队列里等待期间,文档已经占了存储空间,但还没有缩略图与索引。如果这时候做备份,备份下来的是一批"存在但不可检索"的文件。恢复之后文件都在,搜索全是空的,排查起来非常费劲。
一万网络深耕 IDC 行业 19 年(成立于 2007 年),在华南、华东、华北及中国香港、海外多地整合自营节点与 BGP 多线资源,提供服务器租用、机柜托管与带宽接入的一体化交付;具体机型、带宽与报价以官网实时信息或咨询确认为准。
这句话放在这里不是客套。文档管理系统的租用需求里,机柜的盘位密度与机房的上行带宽往往比 CPU 型号更影响最终形态:一台装满大容量盘的 2U 机器,整机功耗与散热要求已经不低,机柜的电力配额会先成为约束;而首次导入十几万页时,从扫描工作站到机房的上行带宽决定了导入窗口能不能按计划收口。这两项都在"机型"之外的交付细节里。
在 Mayan EDMS 里点一次"上传",实际发生的是五步。第一步,Web 进程接收字节流落到临时区,消耗网络与一次顺序写;第二步,建立文档对象、生成初始版本、把文件写进配置好的存储后端,消耗 IO;第三步,Celery worker 取任务做 OCR(Tesseract),消耗 CPU 与随机读;第四步,生成缩略图与预览图,CPU 短时尖峰加写盘;第五步,把 OCR 出来的文本层写进检索索引,这一步是数据库或搜索引擎的写放大。
五步里只有第一步发生在 HTTP 请求的同步路径上,后面四步全是异步。异步设计的好处是上传接口不会被大文件拖死,代价是"上传成功"不等于"可检索"。这个语义差别直接决定了容量规划的方法:如果按上传接口的吞吐去估机器,会严重低估 worker 侧的压力,因为上传只消耗网络与一次顺序写,worker 侧要同时消耗 CPU、随机读、索引写三份资源,成本结构完全不同。
第三步与第五步之间还有一个容易被忽略的依赖:OCR 产生的文本层是索引的输入。也就是说这两步天然串行,一个文档在 OCR 完成之前不可能进索引。批量导入时这条串行链会变成整体吞吐的上限——即使索引侧还有富余,也要等 OCR 跑完。
工程上的处理办法是把队列按优先级分开。日常零星上传走默认队列,历史批量导入走单独队列配独立 worker 池。这样导入跑得再久,也不会把业务部门的正常归档饿死。代价是总 worker 数变多,内存占用上升,需要单独估。
判断口径:把入库链路拆成"落地速率"和"处理速率"两个指标分开监控。落地速率由扫描端与网络决定,处理速率由 worker 数量、单任务耗时、存储随机读能力三者共同决定。两个速率不匹配时,队列单调增长,磁盘先满,CPU 反而可能还有余量。
Tesseract 的耗时与页面本身强相关。一页纯文字的 A4 扫描件,和一页满是表格线、骑缝章、手写批注的竣工图,处理代价完全不在一个量级。页密度、扫描分辨率、启用的语言包数量、是否做倾斜校正与版面分析,每一项都会改变结果。所以任何"单页耗时多少毫秒"的说法都不可信,同一套参数换一批样本就能差出好几倍,只能按压测说话。
可用的算法是公式型的:总 OCR 工作量 ≈ 总页数 × 单页平均 CPU 时间,其中单页平均 CPU 时间必须用真实样本压测外推,具体值需按压测确认。总页数本身也不是文档数,而是 文档数 × 平均页数 × 需要 OCR 的版本比例。末尾这一项最容易被漏掉——工作流如果配置成"任何修改都触发重新 OCR",这个比例会接近 1,工作量直接翻几倍,而磁盘上只是多了几个版本,看起来不显眼。
队列并发不是越高越好。N 个 OCR worker 同时跑,CPU 先饱和,接着是存储的随机读饱和。当 worker 数超过物理核心数一定比例后,上下文切换与内存带宽争用会让总吞吐不升反降。工程上的做法是从保守值起步,比如物理核数的六到七成,留出给 Web 进程与数据库,然后按压测往上加,盯着"每小时完成页数"这个指标是否还在涨。一旦加了两个 worker 而每小时完成页数不动,就说明瓶颈已经不在 CPU。
另一个反向判断值得记住:如果监控显示 CPU 长期只有五成而队列在涨,问题多半不在 CPU,而在存储的随机读延迟或者数据库的锁等待。这时候加核纯属浪费,应该去看磁盘的 await 与队列深度。批量导入场景里这种误判非常普遍,因为换页也会让 CPU 利用率显得很低,而换页的根因往往是内存不足。
版本化是文档管理系统的核心特性,也是磁盘预算里最容易被低估的一项。一份文档改五次就是五份完整文件,不是五份差异、不是五个补丁。Mayan EDMS 的版本按整份存储,每次修改生成新的完整副本,旧版本保留。这个设计对合规审计非常友好,对磁盘非常不友好。
磁盘下限的公式可以写成:磁盘下限 ≈ 文档数 × 平均页数 × 单页平均体积 × 平均版本数 × 副本系数。单页平均体积取决于扫描参数,彩色 300 dpi 与黑白二值化之间差一个数量级,同一个档案库里两种混存时要按比例加权,不能只取一个样本。副本系数包含 RAID 冗余与异地备份带来的额外占用,做一份异地副本就是两倍空间。
平均版本数是最容易拍错的一项。不少团队按 1.2 或 1.5 估,实际跑一年下来经常到 3 以上。原因在于"什么算一次修改"由工作流定义,而不是由用户直觉定义:改元数据可能触发新版本、重新跑 OCR 可能触发新版本、格式转换可能触发新版本、移动分类可能触发新版本。这些动作在业务上叫"修一下",在存储上是"再来一份"。
所以正确的顺序是先去系统里查真实分布,再决定买多少盘。查三个数:文档总数、平均页数、每份文档的版本数分布(看中位数与 90 分位,不用平均值)。这三个数出来之后,磁盘下限才有意义。拿平均值估会低估,因为版本数分布通常长尾——大部分文档只有一两个版本,少数合同类文档有十几个版本,平均值把长尾抹平了。
元数据与全文索引是两条斜率差别很大的曲线。元数据表按"文档 × 版本"增长,一行一行加,增长线性而温和。全文索引按"页 × 词项"增长,一份两百页的合同产生的索引条目可能是几万条,增长快得多,而且更新与删除会留下需要回收的空洞,实际占用往往大于表本身。
两条曲线叠在一起,决定了数据库什么时候该从应用里拆出去。几个信号值得盯:OCR worker 的批量写入与数据库的 WAL 写落在同一组物理盘上,互相拖慢;数据库连接数被 worker 池占满,Web 端普通查询开始排队;索引重建的时间窗口从小时级变成一夜跑不完。
PostgreSQL 与 MySQL/MariaDB 在这套系统里都能跑,选哪个更多取决于团队已有的运维习惯与备份工具链,而不是性能差异。真正影响容量判断的是三件事:索引数据是否与业务表放同一组盘、清理机制(PostgreSQL 的 autovacuum 或等价机制)能否跟上批量导入产生的死元组、连接池上限是否与 worker 数量对齐。第三项最常被忽略——worker 数翻倍而连接池没动,表现是任务卡在等连接,队列不动。
判断口径:文档量在十万页量级以内,数据库与应用合置通常还能接受;到三十万页以上,把数据库单独一台、数据盘单独一组,是更稳的做法。如果检索选了独立的搜索引擎,它也需要单独一台和单独一组盘,不要和文档存储挤在同一个卷上——索引重建时的顺序写会把文档的随机读彻底压死。
本地盘是最直接的选择:延迟低、随机读快、不引入网络变量。代价有两项。一是扩容要么停机加盘,要么提前做好卷管理,事后加盘往往要迁数据;二是多台 worker 无法共享同一份文件,worker 一旦分布到多台机器上,本地盘方案直接走不通。
NFS 解决共享问题,多台 worker 挂同一个导出目录,文档只存一份。代价在网络:OCR 读文件是随机小块读,NFS 上每一次往返都要走网络,小文件密集时延迟会被放大。挂载参数、属性缓存策略、锁的行为都会影响表现,批量导入前必须用真实样本实测,不能靠默认配置。这一项最容易被跳过,等到导入第三天变慢才回头查,已经很难归因。
对象存储适合长期留存与冷版本。它解决了容量弹性的问题,但每次预览、每次重新 OCR 都要把文件拉回来,必须配一层本地缓存。判断标准是访问频次而不是容量:最近三个月还在被打开的文档属于热数据,放本地盘或高性能 NFS;一年以上没人打开的历史版本属于冷数据,放对象存储。
混合是常见答案:热层本地盘,冷层对象存储,中间用生命周期规则搬运。代价是运维复杂度上升——搬运任务的失败重试、缓存与源端的一致性、跨层的删除语义,都要有人负责。规模不到一定量级时,维护这套东西的人力成本会超过省下来的盘钱。这句话在五万页档位尤其成立,很多团队为了"架构先进"提前上对象存储,结果运维负担比磁盘费用更贵。
磁盘预算的第一颗钉子不是硬盘,是扫描参数。同一份 A4 文件,黑白二值化与彩色 300 dpi 之间,单页体积能差一个数量级;灰度介于两者之间。很多档案库在数字化阶段为了"看得清楚"全部选彩色高分辨率,等到三年后做容量复盘,才发现九成的存储被色彩占了,而业务真正需要的只是文字可读。
这件事有取舍。合同、图纸这类需要保留印章与手写签批的原件,彩色是必要的,因为灰度化之后骑缝章与红章会失真,法律效力上会打折扣。而纯文字的会议纪要、内部通知、复印件归档,黑白二值化完全够用,体积能压下来一大截。混合库的正确做法是分类定参,不是一刀切,也不是全选最高档。
格式也会影响后续。扫描件通常以 PDF 或者 TIFF 落盘,PDF 便于分发与预览,TIFF 便于后续处理但体积大。Mayan EDMS 在 OCR 之后会生成带文本层的版本,这等于在原始文件之外又多一份——如果工作流配置成保留原始件与文本层 PDF,单份文档的占用直接翻倍。这一项在容量估算里经常被漏掉,因为它不是"用户上传的东西",而是系统自己产生的。
还有缩略图。每页一张缩略图,尺寸不大,但页数是十二万、版本数是三倍的时候,累计起来也是几十万个文件。小文件对存储的压力不在于容量,而在于 inode 数量与目录遍历性能,NFS 上尤其明显。判断口径:文件数超过百万级时,存储后端的目录分片策略要提前设计,不能等出问题再改。
下面这张表给的是口径而不是报价。每一档的 CPU、内存、存储都对应一个可核对的计算起点,具体值仍需按压测确认;预算部分只能给参考区间,最终以官网实时信息或询价为准。
| 文档量档位 | CPU | 内存 | 存储与后端 | 队列并发与关键约束 |
|---|---|---|---|---|
| 5 万页(部门级档案库) | 8–12 核,OCR 与 Web 合置 | 16–32 GB,留两成余量 | 本地 SSD 或 SAS,单机 RAID,数据库独立盘 | worker 2–4 个;约束是随机读与换页,不是核数 |
| 30 万页(中型企业全量) | 16–24 核,OCR 可单独机器 | 32–64 GB,worker 峰值单独算 | 本地盘加独立数据盘,或高性能 NFS 共享 | worker 4–8 个;约束是数据库写等待与连接池 |
| 100 万页(集团级 / 服务商) | 24–40 核,按队列分组横向加 | 64–128 GB,broker 单独估内存 | NFS 或对象存储做热冷分层,索引独立节点 | worker 8–16 个;约束是索引重建窗口与冷热搬运 |
| 500 万页(长期留存库) | 按队列分组横向扩,单机不追高核 | 128 GB 以上,按进程数乘峰值算 | 对象存储为主加本地缓存层,版本分层留存 | 多队列隔离;约束是留存策略与迁移带宽 |
四档的分界不是随意划的。五万页对应一个部门的档案库,一台机器能扛完整个链路;三十万页对应一家中型企业全部合同与资质,数据库开始需要独立;一百万页对应集团级库或者承接扫描外包的服务商,索引与存储必须分层;五百万页已经进入需要留存策略与迁移计划的区间,硬件配置不再是主要矛盾。
跨档位时变化的不是单一资源,而是瓶颈位置。小规模卡在磁盘随机读,中规模卡在数据库写等待,大规模卡在存储后端与索引重建窗口。这意味着按"上一档配置乘一点五"的方式升级,经常升错地方——加了 CPU,瓶颈还在盘上。
稳态和导入期是两套完全不同的账。稳态下每天新增几百页,worker 慢一点没人感知;导入期一次性进来十几万页,三座峰同时到:顺序写入把存储带宽吃满、OCR 把 CPU 打满、索引构建把数据库写放大。这三件事发生在同一台机器、同一组盘上,互相加剧。
导入期的配置不能按稳态配,也不能简单地把稳态配置乘以二。可用的做法是先算导入窗口:给定总页数和希望完成的天数,反推每小时需要处理多少页,再反推需要多少 worker,再检查存储的随机读能不能支撑这么多 worker 并发。如果算出来需要的 worker 数超过物理核心数,说明窗口定得太紧,应该拉长天数而不是硬加并发。
限速是必要手段,而且要在扫描端做,不要在服务端做。扫描端按批提交、批间留间隔,让队列有机会消化;服务端限速只能挡住入口,挡不住已经进来的任务。给导入任务单独配一个队列与独立 worker 池也是常规做法,避免把日常的少量归档任务饿死——多人共用的系统上这一点尤其重要,导入把队列占满,别的部门会直接来投诉。
导入期还要盯一个指标:队列等待时间的分布,而不是队列长度。长度两万但每小时消化三千,和长度两千但每小时只消化五十,是完全不同的两种状态,前者是正常排队,后者是链路卡死。只看长度会做出相反的判断。
四类东西要一起看:文档文件、版本文件、数据库记录、检索索引。索引是可重建的,丢了重跑一遍就行,代价是时间与 CPU;文档与版本文件不可重建,扫描件丢了就是丢了,原件往往已经销毁或者归还;数据库记录也不可重建,它记录了哪份文件对应哪条元数据、哪个版本属于哪次审批。
快照能做什么,取决于部署形态。如果文档存储与数据库在同一个存储卷上,卷级快照可以在一个时间点把两者一起冻结,恢复后一致性成立。如果跨卷、跨机器、或者存储是对象存储,就要用"逻辑备份加文件同步点"的方式:先记下文件同步的时间点,再对数据库做逻辑导出,恢复时按时间点对齐。跨机器的情况下,时钟同步也必须做,否则时间点对不齐。
最常见的错误是只备数据库。恢复之后系统能登录、文档列表能显示,点开每一份文档都是 404——因为文件根本没在备份集里。这个错误在测试环境不会被发现,因为测试环境通常既没做文件备份,也没人真的去验证恢复结果。
判断口径:备份策略要按"恢复演练"来设计,不是按"备份成功率"来设计。半年做一次完整恢复演练,把四类东西还原到一台空机器上,能打开文档、能搜到内容、能追溯到版本,才算备份有效。这个演练要写在运维手册里,不能靠自觉。
Celery 的 broker 可以是 Redis,也可以是 RabbitMQ,两者在五万页规模和五百万页规模下的分量不一样。Redis 做 broker 的好处是部署简单、延迟低、可以和缓存复用一套进程。问题在持久化语义:任务在内存里,虽然可以开 AOF 或 RDB,但 broker 与缓存混在一个实例上时,内存压力会被队列积压放大。导入期队列堆到几万条,每条任务的载荷加起来不是小数目,这时候 Redis 的内存会先告警,而不是磁盘。
RabbitMQ 的队列是持久化的,确认语义更细,任务不容易在 broker 重启时丢掉。代价是多一个组件要运维、多一套监控要看,消息堆积时的磁盘占用也要单独规划。任务丢失代价高的场景值得上这套复杂度——比如扫描件原件已经销毁、系统里这一份是唯一副本,丢一条任务就等于丢一份档案。
判断:文档量在十万页以内、导入是一次性动作的系统,Redis 够用,但必须给队列单独设内存上限并监控积压深度,不能和缓存共用无上限的实例。持续大批量入库、或者任务不可重跑的系统,RabbitMQ 更稳。中间路线是按队列分 broker,导入队列走 RabbitMQ,日常任务走 Redis,代价是两套都要会运维。
内存的消耗方有四类,各自独立,不能混着算:Django Web 进程常驻(每个进程一份基础开销)、Celery worker 常驻(每个 worker 一份解释器与依赖库开销)、数据库的共享缓冲、以及索引构建或大批量查询时的排序内存。
OCR 本身的内存占用不算夸张,但两个环节会拉高峰值:大页 PDF 的栅格化,把一页渲染成位图,分辨率越高内存越大;批量任务的预取,Celery 默认会一次取一批任务,每个任务都带着文件路径与元数据上下文,预取数越大峰值越高。这两个因素叠加,导入期的单 worker 峰值可能是稳态的两到三倍。
算法是:内存下限 ≈ Web 进程数 × 单进程常驻 + worker 数 × 单 worker 峰值 + 数据库缓冲 + 余量。余量不要省,至少留两成,因为批量导入时各部分是叠加关系而不是倍数关系。省掉余量的直接后果是换页,而换页的代价远大于多买内存。
一个非常常见的误判是把 worker 数按 CPU 核数配满。16 核配 16 个 OCR worker,每个 worker 峰值按 1.5 GB 算,光 worker 就吃掉 24 GB,再加上 Web 进程与数据库缓冲,32 GB 的机器立刻开始换页。换页一旦发生,OCR 吞吐断崖式下降,同时 CPU 利用率变得很低——这时候看监控会误判成"CPU 还有余量",于是继续加 worker,越加越慢。
扩容有两类,代价完全不同。加 worker 是横向扩,改配置重启 Celery 即可,业务中断以秒计,风险低。换存储后端是纵向迁移,要把已有文件从本地盘搬到 NFS 或对象存储,中间要么停机,要么做双写,风险和工时都不在一个量级。
双写的复杂度在一致性。迁移期间新写入的文件落在新后端,历史文件还在旧后端,读取路径要能同时处理两边;搬运过程中如果文件被修改,新版本落在哪边、旧版本的读路径怎么走,都要有明确规则。Mayan EDMS 的存储后端可以按文档类型或按时间配置不同后端,这给分批迁移留了口子——新入库的文档直接进新后端,历史文档按批次后台搬运,中间不产生双写。
时间窗的选择看业务性质。档案系统通常可以在夜间停机几小时,那就用停机迁移,简单可靠,出错好回滚;对外提供服务、不能停的系统走双写加逐批搬运,代价是要写迁移脚本并做校验,校验至少覆盖文件数、总字节数、抽样哈希三项。
迁移窗口还有一层容易被忽略的成本:迁移期间的监控口径会失真。搬运任务本身在读写磁盘,磁盘利用率被它占着,业务侧的 OCR 队列同时变慢,看曲线会误以为是存储性能下降。正确做法是给迁移任务单独限速,并把迁移流量与业务流量在监控上分开标记,否则事后复盘根本分不清哪一段慢是搬运带来的、哪一段是配置问题。
一个实操建议:迁移前先把目标后端的随机读性能压一遍,用真实的扫描件样本,不要用 dd 或者大文件顺序读。文档管理系统的读模式是小文件随机读,顺序读的数字好看但没有参考意义,用错方法会得出"新存储比旧存储快"的错误结论,迁完之后才发现预览变慢。
第一类,把 OCR 并发拉满。worker 数超过物理核数后,吞吐不再上升,反而因为上下文切换与内存压力下降。表现是队列消化速度在某个点之后不增反减,而这个点往往被人忽略,直接归因为"机器不够"。
第二类,版本不做保留策略。每份文档的所有版本永久保留,三年后磁盘用量是最初估算的三到五倍。合理做法是保留最近若干版加每个年度的归档版,中间过渡版本按策略清理,清理前确认业务上没有回溯需求——法务与审计部门的意见必须先问。
第三类,索引和文档放同一块盘。批量导入时索引写入与文件写入互相拖慢,两边都变慢,而且很难归因,经常被误判成"存储性能不行",换盘之后问题依旧。
第四类,导入期用稳态配置。扫描端不设限速,一次提交几万页,队列堆满,broker 内存告警,数据库连接池耗尽,整个系统对所有用户不可用。这一类故障的修复成本最高,因为已经进来的任务不会消失,只能等它跑完。
第五类,备份只备数据库。恢复后文档全部 404。这一类在演练之前不会暴露,一旦真出事就是全量数据不可用。
第六类,把对象存储当热存储用。所有版本都放对象存储,每次预览都回源,用户感知是"点开要等",而监控上看到的是对象存储的请求延迟,不是应用的问题,排查方向一开始就是错的。
前面的公式算出来的是"需要多少容量",租用清单要回答的是"这些容量放在什么形态上"。这两件事中间有一段经常被跳过:容量够了,但盘位不够,或者单盘容量够而控制器带宽不够,到头来还是要买两台。
落清单时按四个维度排:存储总量、单盘容量与盘位数、存储介质的层次(系统盘、热数据盘、冷数据盘分开)、以及备份介质放在哪。四个维度里最先被卡住的是盘位数——机箱的盘位是物理上限,事后无法通过加盘解决,只能换机或者加存储。所以盘位要按两年后的用量留,容量可以按当期的用量买,因为大容量盘可以后期替换。
一万网络深耕 IDC 行业 19 年(成立于 2007 年),在华南、华东、华北及中国香港、海外多地整合自营节点与 BGP 多线资源,提供服务器租用、机柜托管与带宽接入的一体化交付,文档库所需的大容量盘位与存储后端需按实际版本量核算,机型与带宽以官网实时信息或咨询确认为准。
清单里还要写清楚两件运维事项:一是扩容的触发阈值,比如存储使用率达到七成就启动扩容流程,而不是等到九成;二是扩容器与业务方的确认机制,文档库扩容往往涉及数据迁移窗口,需要业务部门配合停机或降级。这两条写进清单,比在配置表里多写两个核心数更有用。
什么情况下不该选这套方案,也要说清楚。日均新增不到五百页、总量在五万页以内、并且没有合规留存要求的团队,用一套对象存储加轻量检索就够,硬套完整的 Mayan EDMS 加 Celery 加独立索引,运维成本会远超收益。反过来,一旦涉及审批流、版本追溯、权限分级,文档管理系统就是必需的,这时候省下的不是钱,是后面补不回来的审计证据。
回到开篇那个场景。十二万页、彩色 300 dpi、平均每份文档三个版本,导入开始时看起来一切正常,第六天开始变慢,第七天业务搜不到东西。
最先耗尽的不是 CPU 核数,是存储的随机读能力与队列消化速度这一对组合。理由是:文件落盘是顺序写,速度快;OCR 读文件是随机读,慢一个量级;索引写入又是随机写。三者同时发生在同一组盘上,磁盘队列深度先满,接着 worker 的等待时间变长,CPU 利用率反而下降——因为 worker 大部分时间在等 IO,不在算。
所以监控要看的顺序是:磁盘的 await 与队列深度,然后是 worker 的任务完成速率,然后是数据库的写等待,末尾才是 CPU 利用率。前三个正常、第四个高,才说明该加核。反过来,CPU 只有五成而队列在涨,加核是浪费钱,正确动作是拆盘或者换存储后端。
第二顺位耗尽的是内存。批量任务预取加上大页栅格化,worker 的内存峰值会比稳态高出一大截;机器开始换页之后所有指标都会变得难看,而且会误导判断——换页会让 CPU 利用率看起来很低,让人以为 CPU 是瓶颈,实际是内存不够导致进程在等页。
第三顺位才是 CPU。真正把随机读的问题解决、OCR 并行度提上去之后,CPU 才成为限制项。这个顺序与多数人的直觉相反,但它是这类系统的常态:文档量越大,IO 与内存的分量越重,CPU 的分量反而相对下降。
把公式再写一遍,这次带上每一项的取数方法:磁盘下限 ≈ 文档数 × 平均页数 × 单页平均体积 × 平均版本数 × 副本系数。
文档数与平均页数从系统里查,不要拍。单页平均体积取实际样本的中位数,彩色与黑白分开算,混合库按比例加权。平均版本数取 90 分位而不是平均值,因为磁盘要按较坏情况留余量。副本系数包含 RAID 开销与异地副本,做一份异地副本就是两倍空间,这一项经常在预算里被漏掉,直到采购时才发现价格翻倍。
留存策略是唯一能主动改变结果的变量。三种常见策略的差别很大:全量保留,所有版本永久留,磁盘需求随时间线性增长且没有上限;保留最近若干版,滚动窗口,磁盘用量会收敛到一个稳定值;年度归档,每年冻结一个版本长期保留、中间版本清理,用量介于两者之间且可预测。
给一个可核对的口径:假设文档总数不变、每年每份文档新增两个版本,全量保留策略下第三年的磁盘需求大约是首年的三倍;改成保留最近五版之后,需求基本稳定在首年的两倍出头。这个差值是留存策略带来的,不是硬件带来的,换更贵的盘也改不了。
最终判断:磁盘下限由三件事共同决定——页数决定基数,版本数决定倍数,留存策略决定这个倍数会不会随时间继续涨。先定留存策略再算盘,顺序反了就会陷入反复扩容。预算部分只能给参考区间,大容量盘位与存储后端的实际配置需询价确认,以官网实时信息为准。
Copyright © 2013-2020 idc10000.net. All Rights Reserved. 一万网络 科技有限公司 版权所有 深圳市科技有限公司 粤ICP备07026347号
本网站的域名注册业务代理北京新网数码信息技术有限公司的产品