本书为考虑是否可以使用和如何使用nosql数据库的企业提供了可靠的决策依据。它由世界级软件开发大师和软件开发“教父”Martin Fowler与Jolt生产效率大奖图书作者Pramod J. Sadalage共同撰写。书中全方位比较了关系型数据库与NoSQL数据库的异同;分别以Riak、Mongodb、Cassandra和Neo4J为代表,详细讲解了键值数据库、文档数据库、列族数据库和图数据库这4大类NoSQL数据库的优劣势、用法和适用场合;深入探讨了实现NoSQL数据库系统的各种细节,以及与关系型数据库的混用。
NoSQL技术与传统的关系型数据库相比,一个最明显的转变就是抛弃了关系模型。每种NoSQL解决方案的模型都不同:键值、文档、列族、图。前三类数据模型都有一个共同特征,我们称其为“面向聚合”。
虽然关系映射能很好地捕捉各种数据元素及其关系,但是它却没有“聚合实体”这一概念。在关系模型中,可以用外键来表达这种关系,但这样做也无法区分某个关系是否表示聚合。因此,无法使用结合结构来帮助其存储与分布数据。
选用面向聚合模型的决定性因素,就在于它非常适合在集群上运行。此时,需要把采集数据时所需的节点数降至最小。如果在数据库中明确包含聚合结构,那么它就可以根据这一重要信息,知道哪些数据需要一起操作了,这些数据应该放在同一节点中。
通常情况下,面向聚合的数据库确实不支持跨越多个聚合的ACID事务,取而代之的是,它每次只能在一个聚合结构上执行原子操作。
数据分布有两种方式,可以选中一种,也可以混合使用:
分片:将数据的不同部分存放在多个服务器中,每个数据子集由一台服务器专门负责。
复制:将数据复制到多个服务器上。
复制又分为两种形式:
主从复制减少了更新数据时的冲突几率,但会使主节点出现写入瓶颈。
一致性有多种表现形式:
集群必须容忍“网络分区”,这正是CAP定理的意义所在。当系统遭遇“分区”状况时(如分布式系统),需要在“一致性”和“可用性”之间权衡。这并不是一个二选一的决定,通常来说,我们都会略微舍弃“一致性”,以获取某种程度的“可用性”。这样产生的系统,既不具备完美的一致性,也不具备完美的可用性。但是,这两种不完美的特性结合起来,却能满足特定需求。
CP:
M和P都想预订酒店的最后一个房间,预订系统采用“对等式分布模型”,他由两个节点组成。M使用伦敦的节点,P使用孟买的节点。若要确保一致性,那么当M要通过位于伦敦的节点预订房间时,该节点在确认预订操作之前,必须先告知位于孟买的节点。两个节点必须按照相互一直的顺序来处理他们说收到的操作请求。此方案保证了已制定,但若网络发生故障,则两个“分区”系统都无法预订,于是系统失去了可用性。
权衡C与A:
改善可用性的一种办法是,指派其中一个节点作为某家旅馆的主节点,确保所有预订操作都由主节点处理。假设孟买是主节点,当发生网络故障时,它仍可处理预订工作,P将订到最后一个房间。在使用“主从复制”模型时,位于伦敦的用户看到的房间剩余情况会与孟买不一致,但是他们无法预订客房,于是就出现了更新不一致。而且当发生网络故障时,位于伦敦的节点无法预订客房。
AP:
继续提高可用性,可以让两个分区系统都接收预订请求,即使在发生网路故障时也是如此。那么,M和P有可能都预订到了最后一间客房。
在讨论分布式系统的一致性时,通常可以概括的说:参与交互操作的节点越多,一致性就越好。然而这样会导致产生交互延时,导致可用性下降。
上面预订酒店的例子,就是一步步降低参与预订操作的节点数,来逐渐提高可用性的。
为了保证强一致性,不需要所有节点都确认写入操作。
把数据放在集群之后,立刻就带来一个好处,那就是可以把运算工作分布到多台计算机。然而,此时仍要试着减少通过网络传输的数据量,把某个节点所需的数据尽可能多地放在该节点上执行。
map-reduace 模式是一种安排数据处理流程的手段。可以利用集群中的多台计算机,同时有能将某台计算机所需的数据及处理工作尽量放在本机完成。
以下部分转自https://www.jianshu.com/p/296bacba3510
以Redis为例:
优点如下:
缺点如下:
针对ACID,Redis事务不能支持原子性和持久性(A和D),只支持隔离性和一致性(I和C)
特别说明一下,这里所说的无法保证原子性,是针对Redis的事务操作,因为事务是不支持回滚(roll back),而因为Redis的单线程模型,Redis的普通操作是原子性的
大部分业务不需要严格遵循ACID原则,例如游戏实时排行榜,粉丝关注等场景,即使部分数据持久化失败,其实业务影响也非常小。因此在设计方案时,需要根据业务特征和要求来做选择
以MongoDB为例进行说明
优点如下:
相比传统关系型数据库,文档数据库的缺点主要是对多条数据记录的事务支持较弱,具体体现如下:
MongonDB还是支持多文档事务的Consistency(一致性)和Durability(持久性)
虽然官方宣布MongoDB将在4.0版本中正式推出多文档ACID事务支持,最后落地情况还有待见证。
适用场景:
不适用场景:
优点如下:
列式数据库由于其针对不同列的数据特征而发明的不同算法使其往往有比行式数据库高的多的压缩率,普通的行式数据库一般压缩率在3:1 到5:1 左右,而列式数据库的压缩率一般在8:1到30:1 左右。
比较常见的,通过字典表压缩数据:
下面中才是那张表本来的样子。经过字典表进行数据压缩后,表中的字符串才都变成数字了。正因为每个字符串在字典表里只出现一次了,所以达到了压缩的目的(有点像规范化和非规范化Normalize和Denomalize)
读取多条数据的同一列效率高,因为这些列都是存储在一起的,一次磁盘操作可以数据的指定列全部读取到内存中。
下图通过一条查询的执行过程说明列式存储(以及数据压缩)的优点
执行步骤如下:
i. 去字典表里找到字符串对应数字(只进行一次字符串比较)。
ii. 用数字去列表里匹配,匹配上的位置设为1。
iii. 把不同列的匹配结果进行位运算得到符合所有条件的记录下标。
iv. 使用这个下标组装出最终的结果集。
缺点如下:
以HBase为例说明:
《NoSQL精粹》
NoSQL 还是 SQL ?这一篇讲清楚