为啥 NoSQL 比 RDBMS 更擅长“横向扩展”?

Posted

技术标签:

【中文标题】为啥 NoSQL 比 RDBMS 更擅长“横向扩展”?【英文标题】:Why NoSQL is better at "scaling out" than RDBMS?为什么 NoSQL 比 RDBMS 更擅长“横向扩展”? 【发布时间】:2012-02-02 12:38:01 【问题描述】:

我在technical blog 中阅读了以下文字,讨论了 NoSQL 的优缺点

" 多年来,为了提高数据库服务器的性能,数据库管理员不得不随着数据库负载的增加(向上扩展)购买更大的服务器,而不是随着负载的增加(向外扩展)将数据库分布在多个“主机”上。 RDBMS 通常不容易横向扩展,但较新的 NoSQL 数据库实际上旨在轻松扩展以利用新节点,并且通常在设计时考虑到低成本商品硬件。 "

我对 RDBMS 和 NoSQL 的可扩展性感到困惑。

我的困惑是:

    为什么 RDBMS 的横向扩展能力较差?以及购买更大服务器而不是购买更便宜的服务器的原因。 为什么 NoSQL 的横向扩展能力更强?

【问题讨论】:

【参考方案1】:

RDBMS 具有 ACID (http://en.wikipedia.org/wiki/ACID) 并支持事务。由于这些概念,使用 RDBMS“向外”扩展更难实现。

NoSQL 解决方案通常提供记录级原子性,但不能保证一系列操作(事务)成功。

归结为:为了保持数据完整性和支持事务,多服务器 RDBMS 需要有一个快速的后端通信通道来同步所有可能的事务和写入,同时防止/处理死锁。

这就是为什么您通常只看到 1 个主(写入器)和多个从(读取器)的原因。

【讨论】:

RavenDB supports transactions,虽然不是传统意义上的。 谢谢,这对我来说很有意义。请问缺乏对事务的支持是否是NoSQL的一个缺点?是否有任何情况下对事务的支持不是那么重要或用处不大,所以这种缺乏支持并不是一个缺点? 如果您需要它,这将是一个不利因素:( NoSql 与 sql 是可扩展性的易用性与事务管理的易用性之间的权衡。因此,如果您说我需要事务并使用 sql,可扩展性会变得更加困难,如果你使用 nosql,然后想要密集的事务支持,那么生活将变得一团糟。 您始终可以使用混合系统。例如:电子商务。 RDBMS 用于实际会计部分,mongodb 用于其余部分。 “为了保持数据完整性和支持事务,多服务器 RDMBS 需要有一个快速的后端通信通道来同步所有可能的事务和写入,同时防止/处理死锁。” 【参考方案2】:

典型的 RDBMS 对一致性做出强有力的保证。这需要为每个事务在一定程度上扩展节点之间的通信。这限制了横向扩展的能力,因为更多的节点意味着更多的通信

NoSql 系统做出不同的权衡。例如,他们不保证第二个会话将立即看到第一个会话提交的数据。从而将存储某些数据的事务与使该数据对每个用户可用的过程分离。谷歌“最终一致”。因此,单个事务不需要等待任何(或更少)节点间通信。因此,他们能够更轻松地利用大量节点。

【讨论】:

这种不同的取舍也可以在RDBMS系统中配置,但知道这一点的人并不多。见:tqdev.com/2016-trading-durability-for-performance-without-nosql【参考方案3】:

因此,我自己一直在尝试找出 NoSQL 与 RDBMS 的真正底线,但最终得到的回应并不完全正确。在我的搜索中,NoSQL 和 SQL 之间确实有 2 个主要区别,只有 1 个是真正的优势。

    ACID 与 BASE - NoSQL 通常会忽略 SQL 的一些 ACID 功能,有点“欺骗”它通过将这一抽象层留给程序员来提高性能的方式。这已经在之前的海报中介绍过了。

    水平扩展 - NoSQL 的真正优势在于水平扩展,也就是分片。考虑到 NoSQL 的“文档”是一种“自包含”对象,对象可以位于不同的服务器上,而不必担心连接来自多个服务器的行,就像关系模型一样。

假设我们要返回一个像这样的对象:

post 
    id: 1
    title: 'My post'
    content: 'The content'
    comments: 
      comment: 
        id: 1
      
      comment: 
        id: 2
      
      ...

    views: 
      view: 
        user: 1
      
      view: 
        user: 2
      
      ...
    

在 NoSQL 中,该对象基本上会按原样存储,因此可以作为一种自包含对象驻留在单个服务器上,而无需与可能驻留在其他数据库服务器上的其他表中的数据进行连接。

但是,对于关系数据库,帖子需要与 comments 表中的 cmets 以及 views 表中的视图连接。这在 SQL ~UNTIL~ 中不会有问题,数据库被分成碎片,在这种情况下,“评论 1”可能在一个数据库服务器上,而“评论 2”可能在另一台数据库服务器上。这使得在水平扩展的 RDBMS 中创建完全相同的对象比在 NoSQL DB 中要困难得多。

那里的任何数据库专家会证实或争论这些观点吗?

【讨论】:

如果在RDBMS中有一个单独的表来保存posts数据,包括cmets,views? 是的,对数据库进行非规范化是连接性能问题的一种可能的解决方法,显然是以任何数据非规范化(冗余、更新成本、大小等)为代价的。顺便说一句,这是面向聚合的 noSQL 解决方案(如键值、面向列和文档)的漏洞。 那么如果我们对 RDBMS 进行反规范化,我们会获得与 NO-SQL 相同的性能吗?【参考方案4】:

对于 NO SQL, 1.与一个集合相关的所有子节点都在同一个地方等同一个服务器,并且没有从另一个服务器查找数据的连接操作。

2.没有架构,因此任何服务器都不需要锁,事务处理留给客户端。

以上 2 节省了大量 NO-SQL 中的扩展开销。

【讨论】:

【参考方案5】:

在 RDBMS 中,当数据变得庞大时,可能会发生表分布在多个系统中的情况,在这种情况下,执行诸如 JOIN 之类的操作会非常缓慢。

在一般 NoSQL 的情况下,相关数据一起存储在同一台机器上(在单个文档中 - 在面向文档的数据库中,或者在宽列数据存储的情况下,相关列在同一台机器上)。因此它很容易在许多低端机器上扩展,显然在这种情况下会在多个地方存在重复数据,而在 RDBMS 中不是这种情况

【讨论】:

【参考方案6】:

为什么 NoSQL 数据库比 SQL 数据库更容易横向扩展?我一直在试图弄清楚为什么人们一直这么说。我遇到了许多文章,这些文章只是让我与他们不熟悉的行业术语和模糊的假设混淆了。我建议您阅读 Martin Kleppman 的 Designing Data-intensive applications。另外,我将分享我对这个主题的一些理解。

JOINS - 在多对一或多对多关系的情况下,迄今为止发明的任何数据库都无法将数据一起保存在一个表或文档中,所以如果数据被分片(或分区),无论是 SQL 还是 NoSQL,延迟都是一样的,数据库必须同时查找这两个文档。 NoSQL 似乎只在一对多关系的情况下占主导地位。例如:

NoSql

学生


  "name": "manvendra",
  "education": [
    
      "id": 1,
      "Degree": "High School"
    ,
    
      "id": 2,
      "Degree": "B.Tech"
    
  ]

教育学院收藏

[
  
    "id": "1",
    "name": "army public school"
  ,
  
    "id": "2",
    "name": "ABES Engineering College"
  
]

Sql

学生桌

id | name        
1  | Manvendra

教育学院

id | Name
1  | Army public school
2  | ABES Engineering college

研究表

student  | education institute | degree
1        | 1                   | high school
1        | 2                   | B.tech

现在假设在 NoSql 的情况下,如果两个集合的数据都在不同的节点上,则需要一些额外的时间来解析教育机构的 id,而这种情况在 SQL 数据库的情况下类似,那么好处在哪里?我想不出来。

另外,你一定在想为什么我们不能将教育机构信息也存储在同一个学生集合中,那么它会是这样的:


  "name": "manvendra",
  "education": [
    
      "name": "Army public school",
      "Degree": "High School"
    ,
    
      "name": "ABES Engineering College",
      "Degree": "B.Tech"
    
  ]

这真的是一个糟糕的设计,因为学生和教育机构之间存在多对多的关系,很多学生可能在同一个学院学习,所以明天如果学院名称或任何信息发生变化在所有地方进行更改将是一个非常艰巨的挑战。

但是,在一对多关系的情况下,我们可以将所有信息组合在一起,例如: 考虑客户和订单关系


  "name": "manvendra",
  "order": [
    
      "item": "kindle",
      "price": "7999"
    ,
    
      "item":"iphone 12",
      "price":"too much"
    
  ]

由于订单只属于一个客户,因此将订单信息存储在一个地方是有意义的,但是无论如何存储商品 ID 或名称是另一种选择,如果我们在这里使用 SQL 数据库,将会有两个包含订单和客户的表如果数据没有存储在同一个节点中,则不会给查询带来好的结果。

所以说加入一个关于为什么 NoSql 数据库更容易水平扩展的争论是没有意义的。

交易

SQL(Postgres、mysql 等)和 NoSQL(MongoDB、Amazon 的 DynamoDB 等)都支持事务,所以没有什么好讨论的了。

ACID 就像 CAP 一样被过度使用,实际上它只是向客户端显示一个数据副本,而不是实际上可能有多个数据副本(以提高可用性、容错性等)以及数据库使用什么策略来去做。例如,在主从分布式系统的 Postgres 中,可以选择同步或异步复制,并且可以使用 WAL(预写日志)进行复制,在 MongoDB 中也是如此,只是代替了 WAL有 oplog(Operations Log),都支持流式复制和故障转移。 那么区别在哪里呢?实际上,我找不到一个非常有力的理由说明 NoSql 数据库可以轻松扩展。我能说的是 NoSql 是最新的,所以数据库提供了对水平扩展的现成支持,例如考虑 MongoDB 中的 Mongos,它们完成了分片文档、将请求路由到特定分片等所有脏活。所以明天如果 Postgres或者 MySQL 提出了一些智能分表机制,因此所有相关数据大部分都保存在一个节点中,然后它可能会结束这场争论,因为关系数据库中没有任何内在的东西可以阻止它水平扩展。

乐观地说,我相信在不久的将来,一切都将与策略有关。您计划如何扩展以及这些策略将独立于您在表格或文档中存储数据的方式。例如,在 Amazon 的 DocumentDB 中,有一个自动伸缩的概念,但是如果您想通过分片来实现这一点,那么每次伸缩时复制数据将是一个负担。在 DocumentDB 中,这被视为共享集群卷(数据存储与计算分离),它只不过是所有实例(主或辅助)的共享磁盘,并避免共享磁盘故障的风险 DocumentDB 复制数据共享磁盘到不同可用区中的其他六个磁盘。所以这里需要注意的一点是DocumentDB混合了共享磁盘的概念和标准的复制策略来实现它的目标。因此,重要的是您在数据库中使用的策略

【讨论】:

以上是关于为啥 NoSQL 比 RDBMS 更擅长“横向扩展”?的主要内容,如果未能解决你的问题,请参考以下文章

mongodb应用

NoSQL与移动应用开发

MongoDB与RDBMS之优势对比

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?

一页纸精华 | HBase

用于留言板站点的 RDBMS 与 NoSQL