常见场景下的 NoSQL 最佳实践

关于 NoSQL 数据库选型,业内已经有很多文章做过系统讨论。在选择数据库产品时,通常需要重点评估这些因素:读写吞吐能力、数据持久化、一致性以及访问延迟等。在 Nathan Hurst 的文章《Visual Guide to NoSQL Systems》中,就对这些关键指标进行了较为详细的说明。
数据库选型本身就是一个复杂课题,本文不准备在这一部分展开太多,而是希望读者能主动补充相关知识。当开发者对数据库架构理解得足够深入时,最终都会得出一个核心结论:不存在任何一种数据库能够覆盖所有应用场景。本文以下内容默认以选择 MongoDB 作为数据库存储方案为前提。针对这一点,Engine Yard 提出了以下四条建议。
进行全面测试。测试必须尽量采用贴近真实业务的数据,同时要最大程度模拟线上场景中的数据读写与操作行为。否则,开发者往往会在系统上线后才暴露出性能瓶颈,甚至发现整体架构设计存在缺陷。因此,建议尽可能基于真实使用场景开展测试,并持续收集足够充分的测试数据作为判断依据。
不要认为关系型数据库的使用方式可以被直接照搬。MongoDB 并不支持部分关系型数据库中的常见功能,因此开发者首先要弄清楚 MongoDB 的能力边界。为了获得更好的数据库性能,建议重点参考 10gen 官方推荐的文档设计方式和操作实践。另外,在正式使用 MongoDB 之前,开发者应做好对现有系统架构进行重构的准备,以适应新的存储模型。若想更深入理解数据迁移带来的成本,建议阅读《The cost ofMigration》一文。
明确业务对数据一致性和可靠性的要求。对于 MongoDB 而言,可靠性不再主要依赖“数据写入磁盘”这一单一动作,更多是通过将数据同步到其他节点来提升可靠性与容灾能力。绝不建议开发者在生产环境中让没有备份的单节点独立运行。这一点非常关键,因此建议开发者认真了解其背后的技术原因。
明确你对 EBS 的性能预期。如果你是 Engine Yard 云平台用户(AWS EC2),那么应该了解 EBS 的性能表现并不总是稳定一致。因此在压力测试阶段,最好收集足够多的 EBS 设备吞吐数据作为评估依据。Engine Yard 本身并没有对用户使用 EBS 的性能做额外限制。
MongoDB 最佳实践
下面是我们在将 MongoDB 纳入服务支持列表过程中始终遵循的一些核心原则。
Replica Sets 是必选方案。它依靠自动 failover 机制,为 MongoDB 高可用部署提供保障。在实际业务场景中,一旦 primary 节点发生故障,某台 secondary 节点就会通过选举提升为新的 primary,从而保证整个 MongoDB 集群继续稳定提供服务。我们的服务不支持缺少同步机制的 MongoDB 部署方式。如果开发者在自身环境中认为同步机制成本过高,建议考虑使用相关云存储服务。Engine Yard 目前已与 MongoHQ 和 MongoLab 建立合作关系,开发者可以在合作伙伴页面获取更多信息。
持续更新版本。保持 MongoDB 版本更新非常重要,因为 10gen 会在每个新版本中修复问题并优化性能,让数据库运行得更加稳定高效。以 2.0.x 版本为例,MongoDB 在存储性能和并发处理能力方面都有明显提升,同时还包含索引优化、Bug 修复以及 compaction 命令等多项改进,帮助开发者更方便地扩展集群规模。如果你仍在使用 1.6.3 版本,那么现在就应该尽快升级。
务必不要在 32 位系统上使用 MongoDB。原因在于 32 位机器的内存地址空间限制了数据库可用容量。MongoDB 内部通过内存映射机制提升性能,因此在 32 位系统上通常只能存储约 2.5GB 数据。在 Engine Yard 云服务中,如需部署 MongoDB,务必使用 Large instance。而在实际产品环境中,我们仅支持 64 位 MongoDB 部署。
默认启用 journaling 日志。MongoDB 支持在写操作前记录 journaling 日志,以提升节点可用性和数据安全性。强烈建议在部署 MongoDB 时开启 journaling。与此同时,还要特别注意数据文件的存储位置。使用过程中,请确认数据文件位于持久化存储中(例如 /data/mongodb 目录)。当然,也可以将数据文件放在非持久化设备上,但必须格外谨慎,因为这可能对整个 MongoDB 集群架构产生影响。推荐使用 EBS 作为 MongoDB 数据文件的存储介质。热数据最好常驻内存。尽量让热数据以及索引数据始终保留在内存中,这一点对数据库集群整体性能影响极大。如果通过监控发现 page fault 数量持续增加,那么很可能意味着热数据规模已经超出可用内存。当热数据超出内存容量时,常见的解决办法通常有两种:增加内存或进行数据分片。我们的建议是,优先扩容内存,再考虑采用分片方案。
压力过大时及时升级配置。如果机器负载达到 65%,就应考虑升级服务器配置。在日常运维中,最好将负载长期控制在 65% 以下。这不仅关系到系统稳定性,也会影响数据恢复能力和纵向扩展效果。当确实需要升级配置时,AWS 建议按照以下顺序进行:Large、Extra Large、High Memory 4XL。同时,在更高配置的实例上,网络延迟通常也会更低。
分片一定要谨慎。MongoDB 分片策略会直接受到数据访问模式的影响,因此在实施数据分片之前,最好先彻底梳理清楚业务数据的访问特征,并认真判断当前是否真的需要分片。分片键会对数据库性能产生非常大的影响,所以选择合适的分片字段极其重要。Config 节点对整个 MongoDB 集群的健康运行至关重要,因此一旦使用分片机制,就必须保证有 3 个 Config 节点。永远不要删除 Config 节点上的数据,并且要确保这些数据能够被频繁、稳定地进行日常备份。如果条件允许,建议通过域名来指定节点地址,例如在 /etc/hosts 文件中配置相应的本地域名,这样能让集群配置更灵活。Config 节点负载通常较小,但仍然需要运行在 64 位机器上。切记不要把 3 个 Config 节点全部部署在同一台机器上!
另外,如果你计划部署一个 MongoDB 分片集群,也可以向 Engine Yard 专家服务预约专业咨询。
使用 Mongo MMS 图形化监控服务。如果你目前还没有建立完善的 MongoDB 监控体系,可以尝试使用 Mongo MMS。Mongo MMS 是 10gen 官方推出的监控服务,能够以图形化方式集中展示 MongoDB 集群各项健康指标,便于日常运维与性能分析。
