简要理解数据库

来源:互联网 发布:棉花期货天狼星软件 编辑:程序博客网 时间:2024/04/30 02:54

数据库会遇到问题主要是在高并情况下,读取的数据不一致或者是出现异常。给数据库三个指标把 C(consistency)A(Available)P(Persistence)

CAP,BASE和最终一致性是NoSQL数据库存在的三大基石。而五分钟法则是内存数据存储了理论依据。这个是一切的源头。

CAP

NoSQL数据库

  • C: Consistency 一致性
  • A: Availability 可用性(指的是快速获取数据)
  • P: Tolerance of network Partition 分区容忍性(分布式)

10年前,Eric Brewer教授指出了著名的CAP理论,后来Seth Gilbert 和 Nancy lynch两人证明了CAP理论的正确性。CAP理论告诉我们,一个分布式系统不可能满足一致性,可用性和分区容错性这三个需求,最多只能同时满足两个。
熊掌与鱼不可兼得也。关注的是一致性,那么您就需要处理因为系统不可用而导致的写操作失败的情况,而如果您关注的是可用性,那么您应该知道系统的read操作可能不能精确的读取到write操作写入的最新值。因此系统的关注点不同,相应的采用的策略也是不一样的,只有真正的理解了系统的需求,才有可能利用好CAP理论。

作为架构师,一般有两个方向来利用CAP理论
  1. key-value存储,如Amaze Dynamo等,可根据CAP三原则灵活选择不同倾向的数据库产品。
  2. 领域模型 + 分布式缓存 + 存储 (Qi4j和NoSql运动),可根据CAP三原则结合自己项目定制灵活的分布式方案,难度高。
我准备提供第三种方案:实现可以配置CAP的数据库,动态调配CAP。

  • CA:传统关系数据库
  • AP:key-value数据库

而对大型网站,可用性与分区容忍性优先级要高于数据一致性,一般会尽量朝着 A、P 的方向设计,然后通过其它手段保证对于一致性的商务需求。架构设计师不要精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。
不同数据对于一致性的要求是不同的。举例来讲,用户评论对不一致是不敏感的,可以容忍相对较长时间的不一致,这种不一致并不会影响交易和用户体验。而产品价格数据则是非常敏感的,通常不能容忍超过10秒的价格不一致。

CAP理论的证明:Brewer's CAP Theorem

最终一致性

一言以蔽之:过程松,结果紧,最终结果必须保持一致性

为了更好的描述客户端一致性,我们通过以下的场景来进行,这个场景中包括三个组成部分:
  • 存储系统
存储系统可以理解为一个黑盒子,它为我们提供了可用性和持久性的保证。
  • Process A
ProcessA主要实现从存储系统write和read操作
  • Process B 和ProcessC 
ProcessB和C是独立于A,并且B和C也相互独立的,它们同时也实现对存储系统的write和read操作。

下面以上面的场景来描述下不同程度的一致性:

  • 强一致性
强一致性(即时一致性) 假如A先写入了一个值到存储系统,存储系统保证后续A,B,C的读取操作都将返回最新值
  • 弱一致性
假如A先写入了一个值到存储系统,存储系统不能保证后续A,B,C的读取操作能读取到最新值。此种情况下有一个“不一致性窗口”的概念,它特指从A写入值,到后续操作A,B,C读取到最新值这一段时间。
  • 最终一致性
最终一致性是弱一致性的一种特例。假如A首先write了一个值到存储系统,存储系统保证如果在A,B,C后续读取之前没有其它写操作更新同样的值的话,最终所有的读取操作都会读取到最A写入的最新值。此种情况下,如果没有失败发生的话,“不一致性窗口”的大小依赖于以下的几个因素:交互延迟,系统的负载,以及复制技术中replica的个数(这个可以理解为master/salve模式中,salve的个数),最终一致性方面最出名的系统可以说是DNS系统,当更新一个域名的IP以后,根据配置策略以及缓存控制策略的不同,最终所有的客户都会看到最新的值。

变体

  • Causal consistency(因果一致性)
如果Process A通知Process B它已经更新了数据,那么Process B的后续读取操作则读取A写入的最新值,而与A没有因果关系的C则可以最终一致性。
  • Read-your-writes consistency
如果Process A写入了最新的值,那么Process A的后续操作都会读取到最新值。但是其它用户可能要过一会才可以看到。
  • Session consistency
此种一致性要求客户端和存储系统交互的整个会话阶段保证Read-your-writes consistency.Hibernate的session提供的一致性保证就属于此种一致性。
  • Monotonic read consistency
此种一致性要求如果Process A已经读取了对象的某个值,那么后续操作将不会读取到更早的值。
  • Monotonic write consistency
此种一致性保证系统会序列化执行一个Process中的所有写操作。

BASE

说起来很有趣,BASE的英文意义是碱,而ACID是酸。真的是水火不容啊。

  • Basically Availble --基本可用
  • Soft-state --软状态/柔性事务
"Soft state" 可以理解为"无连接"的, 而 "Hard state" 是"面向连接"的
  • Eventual Consistency --最终一致性
最终一致性, 也是是 ACID 的最终目的。

BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性: Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库) Soft state软状态 状态可以有一段时间不同步,异步。 Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时一致。

BASE思想的主要实现有
1.按功能划分数据库
2.sharding碎片 

BASE思想主要强调基本的可用性,如果你需要高可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲,BASE思想的方案在性能上还是有潜力可挖的。

从个概念去理解单节点和集群方式数据库:

比较其优缺点:

单节点:主要是关系型数据库,mysql oracle,postger等。

             优点:就是CP 能保证。

             缺点:A可用性不能保证,处理的数据容量较小,性能也是比较低。

集群:NOSQL,mongo(文档型数据库),redis (key-value)内存数据库,tips:git 也是基于key-value键值对,采用的是内容寻址文件系统。

            Zookeeper,主要是用于配置管理,和服务注册应用,其实有一个模型就是记录在



下面主要介绍的是编程过程中用的比较多的单节点数据库:

单节点数据一般都是关系型数据库,因为关系型数据库才有事务管理。

主要是为了实现一致性:ACID,主要就是原子,一致(主要是通过constraint, 例如 check,not null,unique),隔离和持久化(write ,ahead,log,这就类似与个git add 和log命令一般只有数据写入硬盘不管你的数据是在内存崩溃还是系统死机,通过log都能复原 )。

需要的深刻了解的是隔离级别:主要是多个事务之间的数据增删改查,出现的问题。两个事务为例T1 和T2


TA

ID

f2

id1

old1

id2

old2




中间为时间轴

T1

T2

Set f2 = 'new' where ID = 'id1'



Select f2 from TA where ID ='id'

commit



Select f2 from TA where ID ='id'



1,read uncommit: T2查询的到是new ,这就是传说中的脏读,就是在为提交之间就已经修改了。

2 read commit:T2,执行查询语句的时候是old1,出现变化的是commit 之后,不是之前,可以对照理解git commit和git add。commit之后就是为new

3,repeat read :我们应该使用第三个,应该这个能保证不怎么会出现问题。就是T1,T2事务是隔离的,不存在在事务还为完成之后,数据就发生变化,针对每一个事务commit ,变化的都只是这个事务,其他的事务都是针对开启事务的快照,其他事务的commit 与本事务无关,基准点是开启事务快照这个很中要,例如一个页面分页的两步:1,计算出现的total .2,现实5列数据。假如另外一事务删除了,使之total 发生变化,如果采用read commit,则就有可能出现错误,但是我们使用repeat read就不存在这样的问题,因为每个事务都是隔离的,开启的事务都是第一次数据使用的快照,不变。

4,serial,这个就是事务之间完全隔离。

事物有7种传播特性 (事务是可以传播的...)

(1)propagation_required 支持当前事务如果当前的逻辑处理有事务 则用当前的事物 没有就开启一个事物

(2)propagation_support 支持当前事务 有就用 没有就不用

(3)propagation_new_required 总是开启新的事务

(4)propagation_mondatory 必须要有事务没有就抛异常

(5)propagation_never 不要事务 有的话就抛异常

(6)propagation_not_support 总是非事务执行 有事物就挂起

(7)如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

0 0
原创粉丝点击