知乎作为中文互联网以高质量内容著称的问答社区,安全反作弊系统能够高效检测出自动生成的内容、无意义的评论以及异常账号活动等可疑行为,从而有效保护社区免受垃圾信息和恶意行为的侵害。
面对每天海量且结构复杂多变的数据,知乎安全反作弊系统需要进行实时深入分析。为此,知乎选择了 MongoDB 数据库来存储这些数据。随着知乎社区的蓬勃发展,帖子、评论和用户行为等数据量急剧增加,现有的基于服务器自建 MongoDB 集群的支持能力逐渐遇到瓶颈,给业务发展带来了隐患,其中主要面临以下四个问题:
存储空间快速上涨带来的持续节点扩容问题:业务的持续增长导致安全反作弊系统的存储需求不断增加,单台服务器的磁盘容量很快达到上限。为了应对这一挑战,需要频繁地手动增加集群节点,以扩展存储容量。
数据规则设置不合理导致的热点分片问题:当前集群通过人工打标签的方式,将不同操作类型和时间段的数据分配至相应的集群节点。然而,由于集群性能瓶颈,数据平衡速度较慢,导致实际数据分布与预期严重不均衡。大部分业务请求集中在少数几个分片上,形成了「热点分片」,进一步恶化了集群性能。
备份间隔越来越长,数据丢失风险大:为保障数据安全,知乎定期进行数据备份,以便在出现问题时能够迅速恢复。但随着数据量的增加,备份所需时间也随之延长,迫使知乎不得不减少备份频率,从最初的几天一次延长至几周一次,这大大增加了数据丢失的风险。
运维操作频繁,稳定性风险大:为解决上述数据存储和管理问题,知乎的运维团队每天需执行大量复杂的运维任务,如扩展集群、数据备份和恢复,以及手动调整数据分布等。这些工作不仅耗费了大量的时间和人力资源,还可能对系统的稳定性造成影响。
这些问题不仅制约了知乎安全反作弊系统的稳定,也对整个社区的健康运行构成了威胁。因此,优化现有的数据管理和存储方案,提升系统的稳定性和效率,已成为当务之急。
为了解决自建 MongoDB 集群的各种技术痛点,知乎技术团队与阿里云技术专家进行了深入讨论,并提出了以下合理的解决方案:
解耦存储和计算资源,优化数据分布策略:为了更好地适应业务发展中存储和计算需求的不均衡增长,我们需要将存储和计算资源解耦。这样可以独立扩展存储和计算能力,避免因资源不匹配而导致的分片过度增长。针对当前数据分布不均衡的问题,建议从依赖标签规则的被动调度模式转变为高版本基于 Chunk 的主动预分片模式。在集群数据迁移过程中重新调整规则,以实现更优的数据分布。
快速灵活应对业务请求负载波动,确保实例性能稳定:通过对集群性能瓶颈的分析发现,关键性能指标主要集中在存储的 IOPS(每秒输入/输出操作数)上。为了在业务高峰期间保持性能稳定,同时避免集群资源的闲置浪费,建议采用支持存储性能弹性伸缩的方案。这种方案允许我们在业务需求增加时快速提升存储的 IOPS 上限,而在业务低谷时则可以缩减,从而实现成本效益最大化。
基于快照备份保证备份恢复效率和数据的可靠性:目前自建集群采用的传统物理备份方法由于数据量和增量数据恢复速度的限制,已经无法满足知乎大规模数据体量的快速备份和恢复需求。建议转向基于云盘架构的快照备份模式来解决这个问题。此外,阿里云 MongoDB 数据库提供的高频备份能力,可以将备份频率从每日一次提升至每 15 分钟一次。结合实例、库、表、行等更细粒度的恢复能力,最大限度地保障了数据的安全性和备份恢复的性能。
综合上述讨论的升级方向,最终选择阿里云 MongoDB 数据库的云盘版本(ESSD 云盘+ AutoPL 弹性性能)和快照备份方案,替换现有的自建 MongoDB 集群。这一方案能够有效解决当前集群面临的各类技术痛点和风险问题,确保系统的稳定性和高效运行。
方案看起来很美,但如此大规模的集群平滑迁移并非易事。本次 MongoDB 集群上云的数据总容量达数百 TB,并且支撑的安全反作弊业务对社区平台至关重要。在割接迁移环节,我们仅有分钟级的时间窗口,不容有失。针对这些挑战,知乎技术团队基于多年的数据库迁移经验和对业务的深入理解,跟阿里云项目团队一起制定了几个迁移过程的基本原则:
迁移过程减少外部变量:安全反作弊数据库架构现有的上下游数据链路非常复杂。在迁移过程中引入新 MongoDB 集群和 DTS(数据传输服务)时,如果割接顺序稍有不慎,可能会导致上下游数据不一致。因此,在迁移方案设计中,项目组将 MongoDB 集群迁移和ETL上下游链路切换分开到不同的割接窗口期,避免集中割接带来的复杂性和风险。
迁移同步速率灵活可控:由于集群数据规模庞大,对迁移速率的要求非常高。同时,需要时刻关注迁移速率对源库引入的额外负载压力,以避免生产问题。因此,迁移过程中的速率动态可调显得尤为重要。阿里云 DTS 数据同步工具支持无感升降配,实现了在保障源库不受影响的情况下最高数据同步速率。
迁移执行流程脚本化:割接操作不仅流程多,而且需要批量启停 DTS 数据同步任务。为了确保在分钟级的时间窗口内完成割接,项目组将关键操作全部脚本化。这样不仅大幅缩短了割接操作时间,将原本需要 10~20 分钟的人工操作提升到秒级自动操作,还能确保割接演练的所有动作可以在正式割接中 1:1 复现,避免人为事故的发生。
提前预演并做好紧急预案:稳定割接的前提是提前识别可预见的问题,并为不可预见的问题准备预案。我们在割接前对割接脚本进行了多次预演,事实证明预演是有效的。通过预演,我们识别了诸如 MongoDB Driver 连接串更新不生效等诸多潜在问题,避免了正式割接中的意外发生。此外,还准备了完善的回滚计划,以应对无法预知的突发事件。
基于上述基本原则,经过项目团队十多次的专题会议讨论,持续优化迁移流程和关键环节,最终确定了以下详细的方案:
1、环境准备
专线施工及网络配置:确保数据传输的安全性和稳定性。
目标数据库实例创建:在阿里云上创建目标 MongoDB 数据库实例。
数据库权限配置:配置数据库访问权限和网络白名单,确保只有授权的 IP 可以访问。
2、数据同步
正向数据同步任务创建:创建 DTS 正向数据同步任务,将源数据库的数据同步到目标数据库。
反向数据同步任务创建:创建但不启动 DTS 反向数据同步任务:为回滚做准备,但暂不启动。
正向数据同步启动:先进行全量数据同步,完成后再进行增量数据同步。
3、数据校验
全量数据校验:确保全量数据同步无误。
增量数据校验:确保增量数据同步无误,并且同步时延在业务接受范围内。
割接条件确认:项目组一致确认数据完整性和时延等指标,确保满足割接条件。
4、割接准备
应用服务镜像瘦身:优化应用服务镜像,减少资源占用。
割接和回滚脚本开发:编写详细的割接和回滚脚本。
割接和回滚脚本验证:在测试环境中验证脚本,并根据测试结果进行调整。
5、正式割接
割接脚本正式执行:在业务低峰期执行生产环境割接操作,减少对用户的影响。
业务稳定性监控:业务持续监控业务运行情况一周以上,确保系统稳定。
历史资源释放:删除 DTS 数据同步任务和原 MongoDB 集群,释放服务器资源。
最终迁移整体流程图如下:
整体迁移工作从启动到全部集群迁移完成耗时一个半月,历经四次关键割接,最终实现了全程业务 0 故障的平滑迁移。这一成就离不开知乎和阿里云双方技术团队的紧密配合,严谨地做好每一次方案设计和迁移验证工作。
资源成本节省:采用基于云原生架构搭建的阿里云 MongoDB 数据库分片集群架构,相比本地盘可以更灵活地进行计算资源和存储空间的配比,实现投入产出显著提升。
运维工作提效:通过一站式的云数据库管理平台,大大减少了运维人员的工作量。运维人员不再需要关注底层操作系统、基础软件等部署和基础维护工作,从而能够更加专注于核心业务。
技术难题解决:使用阿里云 MongoDB 数据库服务获得了阿里云数据库团队和 MongoDB 原厂联合的技术支持。不仅通过本次迁移解决了数据分布不均等历史难题,还为快速应对未来业务变化可能带来的新问题提供了新的技术保障能力。
高可用性提升:从自建单机房迁移到阿里云 MongoDB 数据库三可用区部署架构上,大幅提升了集群的容灾能力。同时,利用云数据库 MongoDB 的数据备份和恢复功能,进一步保障了数据的可靠性。
在本次迁移过程中,尽管前期做了充分的准备,但仍遇到了一些未曾预料的情况。知乎数据库团队和阿里云项目团队一起沉着应对,逐一解决了这些问题,不仅保障了项目按时完成,也为后续同类项目积累了宝贵的经验。以下是具体案例及其解决方案:
1、连接串更新不生效问题:在反作弊应用程序中,测试发现 Go 语言的 MongoDB Driver 连接字符串通过 DNS 解析更改后,实际接入 IP 地址没有生效,即使杀死连接重启服务后,应用仍会连接到原集群 IP。最终,我们通过在割接过程中增加重新部署应用环节来解决这一问题。
2、预分片规则未达预期,数据依然不均衡问题:我们发现通过脚本在新分片集群预分片后,仍然存在分片数据不均的问题。经过排查,发现新分片集群未关闭 Balancer,导致局部数据同步到 chunk中后,chunk 分裂使 00 得分片上的 chunk 数不均衡。Balancer 机制进一步导致空 chunk 漂移到其他分片,最终造成分片不均衡。因此,如果需要手工预分片并精确控制数据均衡性,关闭Balancer是尤为重要的。
3、新分片策略潜在性能问题:分片集群查询范围不确定,使得更改 Chunk 后可能引入新的性能压力。例如,将按月度分片的用户行为类型修改为按周度分片,同样 2 个月周期的查询,影响的分片范围会发生变化。为了验证新分片策略下的性能,我们在分片集群完成同步后,通过脚本模拟相同压力量级的新集群读操作,重点测试分片集群对大范围查询的负载能力,验证通过后才正式进行业务割接。