选择使用 NoSQL 数据库通常是基于炒作,或者是错误的假设,即关系数据库的性能不如 NoSQL 数据库。在选择数据库时,工程师通常会忽略运营成本。在 Wix engineering ,我们发现在大多数情况下我们不需要 NoSQL 数据库,如果使用得当,MySQL 是一个很棒的 NoSQL 数据库。
在构建可扩展系统时,我们发现一个重要因素是使用经过验证的技术,以便我们知道在出现故障时如何快速恢复。例如,您可以使用最新最好的 NoSQL 数据库,这在理论上运行良好,但是当您遇到生产问题时,需要多长时间才能恢复正常活动?对系统及其运作的既有知识和经验——以及能够通过谷歌搜索答案——对于迅速缓解问题至关重要。关系数据库已经存在了 40 多年,并且在如何使用和维护它们方面拥有丰富的行业知识。这是我们通常默认使用 MySQL 数据库而不是 NoSQL 数据库的原因之一,除非 NoSQL 是解决问题的明显更好的解决方案——例如,如果我们需要文档存储,或者处理 MySQL 无法处理的大数据量。
但是,在大型系统中使用 MySQL 可能会遇到性能挑战。为了从 MySQL 获得出色的性能,我们采用了一些使用模式。其中之一是避免数据库级事务。事务需要数据库维护锁,这对性能有不利影响。
相反,我们使用逻辑应用程序级事务,从而减少负载并从数据库中提取高性能。例如,让我们考虑一个发票模式。如果有一个包含多个行项目的发票,我们不会在单个交易中写入所有行项目,而是简单地逐行写入而不进行任何交易。将所有行写入数据库后,我们将写入一个标头记录,其中包含指向行项目 ID 的指针。这样,如果在将各个行写入数据库时出现故障,并且未写入标头记录,则整个事务将失败。一个可能的缺点是数据库中可能存在孤立行。不过,我们不认为这是一个重大问题,因为存储很便宜,如果需要更多空间,可以稍后清除这些行。
以下是我们的一些其他使用模式,以从 MySQL 获得出色的性能:
-
不要有连接查询;仅按主键或索引查询。
-
不要使用顺序主键(自动递增),因为它们会引入锁。相反,使用客户端生成的密钥,例如 GUID。此外,当您拥有主-主复制时,自动增量会导致冲突,因此您必须为每个实例创建键范围。
-
任何没有索引的字段都没有存在的权利。相反,我们将这些字段折叠成单个文本字段(JSON 是一个不错的选择)。
我们经常将 MySQL 简单地用作键值存储。我们将一个 JSON 对象存储在其中一个列中,这允许我们在不更改数据库模式的情况下扩展模式。通过主键访问 MySQL 非常快,我们通过主键获得亚毫秒级读取时间,这对于大多数用例来说非常好。所以我们发现 MySQL 是一个很好的 NoSQL,它符合 ACID 。
在数据库大小方面,我们发现单个 MySQL 实例可以完美地处理数亿条记录。我们的大多数用例在单个实例中没有超过几亿条记录。
与 NoSQL 相比,使用关系数据库的一大优势是您无需处理大多数 NoSQL 数据库显示的最终一致性性质。我们的开发人员都非常了解关系数据库,这让他们的生活变得轻松。
不要误会我的意思,NoSQL 有一席之地;关系数据库有其局限性——单一主机大小和严格的数据结构。工程师往往会为了酷炫的新事物而忽视运营成本。如果这两个选项可行,我们认为我们需要真正考虑在生产中维护它需要什么,并做出相应的决定。