生产环境里一张工作表突然停止保存。Pod 本身看起来完全健康:内存用量 404 MiB / 2 GiB,CPU 用量 655m / 1500m,没有重启。我不太相信这个表面状态,于是又去看了数据库:集群内只有 3 个活跃查询,CPU 12%,三个节点全部在线,一片空闲。没有资源耗尽,没有崩溃,但服务就是写不进去。
这个服务是一个协同编辑器。教师在上面制作工作表、白板和教案,同一个文档可以多人同时打开。每个文档都是一个 CRDT,基于 Loro 构建。浏览器保留一份副本,编辑时先在本地应用,然后通过 WebSocket 推给同步服务。服务端在内存里保存每份打开文档的副本,合并收到的改动,再把结果写入 CockroachDB v25.x。
最后一步是问题所在。所谓持久化,并不是追加写入 CRDT 的更新日志,而是把整个 Loro 文档导出成一份快照,写到单行单列的 BYTEA 字段里。也就是说,每次保存都是全量写入整份文档。这次停止保存的文档是 155 KiB,而它所在的 range(CockroachDB 数据分片)是 1 GiB。
一开始我以为是当天另一个故障导致的:同一个服务当天正好有一个无关的 CPU 问题,就绪探针不停抖动,节点被打满,日志里有几百条超时错误。我把它从头到尾查了一遍,一切都是真的,但都和保存失败无关。同一天、同一个服务、两个独立故障,更吵的那个并不是拒绝写入的那个。
还有一个错误线索:我发现不同文档之间的负载大小差异很大,于是以为客户端发送的是增量更新,这样写入量才代表真实编辑量。但这个推断是错的。负载大小不同并不能说明它是增量。CRDT 快照本身每次大小都会变,就像两个输入略有不同的 zip 文件,体积也不会一样。要验证这一点,只需要把一次保存的负载大小除以已存储快照的大小:如果比值接近 1,就说明每次写入的都是完整快照,而不是增量。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.