《代码的未来》读书笔记——支撑大数据的数据存储技术之键-值存储

代码的未来键-值存储(Key-value store)是数据库的一种。在云计算愈发流行的今天,键-值存储正在受到越来越多的关注。以关系型数据库管理系统(RDBMS)为代表的现有数据库系统正接近其极限,而键-值存储则拥有超越这种极限的可能性。

键-值存储是通过由键对象到值对象的映像来保存数据的。

使用键-值存储方式的数据库,大多数都在数据查找技术上使用了散列表这种数据结构。散列表是通过调用散列函数来生成由键到散列值(一个和原始数据一一对应的固定位数的数值)的映射,通过散列值来确定数据的存放位置。散列表中的数据量无论如何增大,其查找数据所需的时间几乎是固定不变的,因此是一种非常适合大规模数据的技术。

数据库的ACID特性

“为什么在云计算时代键-值存储模型会收到关注”。

问题的关键在于RDBMS数据库所具备的ACID这一性质,我们就从这里开始讲起。ACID是4个单词首字母的缩写,它们分别是:Atomicity(原子性)、Consistency(一致性)、Isolation(隔离型)和Durability(持久性)。

所谓Atomicity,是指对于数据的操作只允许“全部完成”或“完全未做改变”这两种状态中的一种,而不允许任何中间状态。因为操作无法进一步进行分割,所以用了“原子”这个词来表现。

所谓Consistency,是指数据库的状态必须永远满足给定的条件这一性质。

所谓Isolation,是指保持原子性的一系列操作的中间状态,不能由其他事务进行干涉这一性质,由此可以保持隔离型而避免对其他事务产生影响。

所谓Durability,是指当保持原子性的一系列操作完成时,其结果会被保存并且不会丢失这一性质。
整体来看,ACID非常重视数据的完整性,而RDBMS正式保持着这样的ACID特性而不断进化至今的。
但近年来,要满足这样的ACID特性却变得越来越困难。这正是RDBMS的极限,也就是我们希望通过键-值存储来克服的问题。

CAP原理

近年来,人类可以获得的信息量持续增加,如此大量的数据无法存放在单独一块硬盘上,也无法由单独一台计算机进行处理,因此通过多台计算机的集合进行处理成为了必然的趋势。这样一来,在实际运营时就会发生延迟、故障等问题。多台计算机之间的通信需要通过网络,而网络一旦饱和就会产生延迟。

计算机的台数越多,机器发生故障的概率也随之升高。在万台数量级的数据中心中,据说每天都会有几天计算机发生故障。当由于延迟、故障等原因导致“计算机的集合”之间的连接被切断,原本的集合就会分裂成若干的小的集合。

当组成计算环境的计算机数量达到几百台以上(有些情况下甚至会达到万台规模)时,ACID特性就很难满足,换句话说,ACID是不可扩展的。

对此,有人提出了CAP原理,即在大规模环境中:

  • Consistency(一致性)
  • Availability(可用性)
  • Partition Tolerance(分裂容忍性)

这三个性质中,只能同时满足其中的两个。

在大规模数据库中如何保持CAP,很难从一般系统的情况进行类推。因为在大规模系统中,延迟、故障、分裂都是家常便饭。

在我们平常所接触的数台规模的网络环境中,计算机的故障是很少发生的,但对于数万、数十万台规模的集群来说,这样的“常识”是无效的。在这样的数量级上,就会像墨菲定律所说的一样,“只要存在故障的可能性就一定会发生故障(而且是在最坏的时间点上)”。

据说CAP原理已经通过数学方法得到了证明。CAP中的C是满足ACID的最重要因素,如果CAP原理真的成立的话,我们就可以推断,像RDBMS这样传统型数据库,在大规模环境中无法达到期望值(或者说无法充分发挥其性能)。这可真是个难题。

CAP解决方案——BASE

根据CAP原理,C(一致性)、A(可用性)和P(分裂容忍性)这三者之中,必须要舍弃一个。

如果舍弃分裂容忍性的话,那么只有两个选择:要么根本不会发生分裂,要么在发生分裂时能领其中一方失效。

根本不会发生分裂,也就意味着需要一台能够处理大规模数据的高性能计算机。而且,如果这台计算机发生故障,则意味着整个系统将停止运行。现代的数据规模靠一台计算机来处理是不可能完成的,因此从可扩展性的角度来看,这并不是一个有效的方案。

此外,当发生分裂时,例如大的计算机集群被分割为两个小的集群,要区分哪一个才是“真身”也并非易事。如果准备一台主控机,以主控机所在的集群为“真身”,这的确可以做到。但如果主控器发生故障的话,就等于整个系统发生了故障,风险也就大大增加了。

在分布式系统中,像这样“局部故障会导致整体故障”的要害,被称为Single point of failure(单一故障点),在分布式系统中是需要极力避免的。

不能舍弃可用性

那么,舍弃A(可用性)这个选择又如何呢?这里的关键字是“等待”。也就是说,当发生分裂时,服务需要停止并等待分裂的恢复。另外,为了保持一致性,也必须等待所有的数据都确实完成了记录。

然而,用户到底能够等待多长时间呢?仅仅作为一个用户的我,是相当没有耐心的,等上几秒钟就开始感到烦躁了,如果几分钟都没有响应,我想我就再也不会使用这个服务了。假设分裂和延迟的原因是由于机器故障,即便是准备了完善的备份机制,想要在几秒钟之内恢复也几乎是不可能的。所以结论就是,除非是不怎么用得上的服务,否则是不能舍弃可用性的。

那么现在就只剩下C(一致性)了,舍弃一致性是否现实呢?仔细想想的话,在现实世界中严密的一致性几乎是不存在的。例如,A要送个包裹给B,在现实世界中是不可能瞬间送到的。A需要将包裹交给物流公司,然后通过卡车等途径再送到B的手上,这个过程需要消耗一定的时间(无Atomicity)。而且,配送中的状态是可以追踪的(无Isolation),运输过程中如果发生事故包裹也可能会损害(无Consistency)。再有,即便对损坏和遗失上了保险,此次运输交易行为本身也不可能“一笔勾销”。

即便现实世界如此残酷,我们却还是进行着各种交易(事务)。这样看来,即便是在某种程度上无法满足一致性的环境,数据处理也是能够完成的。例如,网上商城的商品信息页面上明明写着“有货”,到实际提交订单的时候却变成了“缺货”,这种事已经是家常便饭了,倒也不会产生什么大问题。和银行汇款不同,其实大多数处理都不需要严格遵循ACID特性。

在这样的环境中,BASE这样的思路也许会更加合适。BASE是下列英文的缩写:

  • Basically Available
  • Soft-state
  • Eventually consistent

ACID无论在任何情况下都要保持严格的一致性,是一种比较悲观的模式。而实际上数据不一致并不会经常发生,因此BASE比较重视可用性(Basically Available),但不追求状态的严密性(Soft-state),且不管过程中的情况如何,只要最终能够达成一致即可(Eventually consistent)。这种比较乐观的模式,也许更适合大规模系统。说句题外话,一开始我觉得BASE这个缩写似乎有点牵强,但其实BASE(碱)是和ACID(酸)相对的,这里面包含了一个文字游戏。

P225

发表评论

您的电子邮箱地址不会被公开。