SSD和内存数据库技术

本文为阅读书籍Next Generation Databases: NoSQL, NewSQL, and Big Data 第7章: The End of Disk? SSD and In-Memory Databases的笔记。

磁盘已死?

比尔.盖茨在1981年曾说过:

640K of memory should be enough for anybody.

在2001年,他意识到之前的说法是错误的:

I’ve said some stupid things and some wrong things, but not that.

从第一个数据库诞生以来,数据库专家就一直努力尽量避免磁盘I/O,因为磁盘比内存,CPU慢好几个数量级。
在CPU,内存和磁盘的密度遵循摩尔定律飞速发展时,由于磁盘的机械特性,磁盘速度的进展却远远滞后。
SSD的产生使磁盘的性能带来了飞跃,最近几年价格下降使得其成为了提升数据库性能的主流技术。与此同时,内存容量的增加以及价格的下降也使得内存技术成为加速数据库性能的另一选择,一些小的数据库可以完全放置于内存中,通过内存集群也可以容纳更大的数据库。在对性能要求严苛的环境下,内存比SSD更具吸引力。

磁盘发展于上世纪50年代,尽管磁盘密度不断提升,但磁盘的核心架构却基本未变,还是机械臂移动磁头到盘片的磁道上读取数据而已。

机械磁盘之后,又有了固态硬盘(SSD),SSD没有移动部件,I/O延迟低。目前,大部分的SSD都是用NAND flash实现的。
SSD对于读的性能实现了较大的提升,例如,机械磁盘的随机读需要4毫秒,而高端SSD只需要25微秒,快了150倍。
但SSD并不能适用所有的工作负载,对于修改操作,SSD就表现一般了。
SSD将信息存于cell中,对于SLC,每一个cell存一个bit信息,对于MLC,每一个cell通常存两个bit,或3个bit信息。cell组织成4k的page,256 page又组织成block。

Read operations, and initial write operations, require only a single-page IO. However, changing the contents of a page requires an erase and overwrite of a complete block.

这就是SSD的软肋了,SSD对于写的性能远低于读,比物理磁盘也许也快不了多少。

flash SSD is significantly slower when performing writes than when performing reads.

由于SSD有一定的擦写寿命,为了避免erase操作的开销,厂商使用了’wear leveling’的技术,通过均匀的分布写来延长磁盘寿命。解释如下,详见NAND Flash FAQ。

Wear-leveling is a technique that spreads the memory use evenly to different physical pages so that the entire NAND Flash devices is used evenly to maximize the life span of the device and the system.

SSD会替代磁盘吗? 目前应不会,虽然SSD的成本在降,磁盘的成本也同时在降。SSD的单位I/O能力强,磁盘具更好单位成本优势。比较合理的结果是内存,SSD和磁盘的结合。

SSD适合于随机写,物理磁盘适合于顺序写,在SSD上运行数据库性能未必会提升。例如当交易提交时,会写redo log,这就是顺序写。因此对于写密集的数据库是不适合SSD的。

内存数据库

SSD对于数据库架构的改变是渐进式的,随着内存价格的下降和容量的增加,将整个数据库置于内存中则带来革命性的架构变化。 (参见http://www.jcmit.com/memoryprice.htm)

对于中小型的数据库,已经可以完全置于内存中,更大容量的数据库则可以通过内存集群技术来利用内存的性能。
传统的数据库利用内存作为缓存来提升性能,但一些操作如commit和checkpoint还是会访问物理磁盘,因此内存数据库需要架构上的改变,即不使用cache和新的持久化模式。

内存数据通常使用以下的技术来保证数据不丢失:
1. 数据复制
2. 将整个数据库映像写盘(snapshot或checkpoint)
3. 将事务写入事务日志或journal

TimesTen

TimesTen是发展较早的关系型内存数据库,成立于1995年,2005年被Oracle收购。
TimesTen早期遵循ANSI-SQL标准,被收购后,又扩展了PL/SQL。
TimesTen数据库的整个数据库都置于内存中,通过checkpoint和事务日志技术保证数据不丢失。
和Oracle不同,缺省模式下,写是异步的,这可能会造成数据丢失,因此ACID中的Durability并不能保证。虽然也可以指定同步模式,但这样会影响性能。
TimesTen的架构如下图:

Redis

和TimesTen的关系型内存数据库不同,Redis (Remote Dictionary Server)采用的是key-value内存存储。
Redis产生于2009,之后VMware和Pivotal对其进行了资助。
Redis的查询只支持主键作为key,不支持二级查询。value方面通常是string集合, 如list, hash map等。
虽然Redis的设计是将整个数据库置于内存中,但也可以结合磁盘来容纳更大的数据库。 此功能TimesTen不具备。

it is possible for Redis to operate on datasets larger than available memory by using its virtual memory feature. When this is enabled, Redis will “swap out” older key values to a disk file. Should the keys be needed they will be brought back into memory. This option obviously involves a significant performance overhead, since some key lookups will result in disk IO.

Redis持久化的策略和TimesTen类似,也是使用snapshot和Journal(redis的术语称为Append Only File 或AOF)。Redis也支持异步的数据复制,但也不能完全保证数据不丢失。
Redis的AOF可以配置为每一个操作后都写,这类似于TimesTen的Durable Commit,对性能有影响。
Redis的架构如下图:

Redis is popular among developers as a simple, high-performance key-value store that performs well without expensive hardware. It lacks the sophistication of some other nonrelational systems such as MongoDB, but it works well on systems where the data will fit into main memory or as a caching layer in front of a disk-based database.

HANA

SAP在2010年推出了HANA,主要用于BI,但也可用于OLTP。
HANA也是关系型数据库,数据表可以选择列式或行式存储,两者只能选一,通常OLTP选用行式,而BI选用列式。后面会提到Oracle 12c中的In-memory对于一个表同时支持行式和列式。
行式数据确保在内存中,列式数据缺省从磁盘中加载。而对于Oracle In-memory,行式数据使用以前的缓存技术,列式数据和HANA类似。
HANA的持久化策略和TimesTen,Redis类似,也是定期将内存写入Savepoint文件中,之后与数据文件合并。
事务一致性通过事务日志保证,在commit时写日志,为避免I/O性能影响,HANA建议将日志置于SSD盘上。
HANA的架构如下图:

此图需要说明的是,对于列式存储表的写首先是存为非压缩的行式(L1 Data Store),然后转化为压缩的列式(L2 Data Store)

Transactions to columnar tables are buffered in this delta store. Initially, the data is held in row-oriented format (the L1 delta). Data then moves to the L2 delta store, which is columnar in orientation but relatively lightly compressed and unsorted. Finally, the data migrates to the main column store, in which data is highly compressed and sorted.

HANA在commit和列式表按需从磁盘载入内存时会涉及到磁盘操作。

VoltDB

TimesTen,HANA,Redis都不可避免的有磁盘读写,而VoltDB号称纯内存数据库,交易在内存中提交,然后通过内存复制实现持久化。例如如果要保证 K-safety为2,则需要至少复制到两台机器。
VoltDB也支持磁盘日志,可以是同步或异步的。
VoltDB支持关系型模式,不过最适合的还是基于key将数据分片或分区分布。如果数据间没有关联可以大大提高并非性,如果需要聚集操作则需访问多个节点,存在开销。
更多的细节可以参见文章。

Oracle 12c “in-Memory Database”

In-Memory是12的一个option,是用列式存储来补充基于磁盘的行式存储的,主要是用来应对HANA的。 所以并非所有数据都在内存中。每个表都有行式和列式两种格式,对于用户是透明的,应用无需更改。
Oracle 12c In-Memory的架构如下:

上图中IMCU表示列式存储,In-Memory Columnar Unit,而Snapshot Metadata Unit (SMU) 是用来跟踪IMCU中数据的有效性的(是否被OLTP应用修改),以与行式数据同步。
Oracle的这篇文章Oracle’s In-Memory Database Strategy for OLTP and Analytics很好的阐述了TimesTen和In-Memory的区别。

Berkeley Analytics Data Stack and Spark

如果说TimesTen和HANA适合内存关系型,Redis适合内存key-value,则Spark适合内存Hadoop。
Hadoop已成为大数据处理的基石,传统的MapReduce基于磁盘,适合于批量处理非结构化和半结构化数据。而Spark的出现则将Hadoop带人实时处理的领域。
2011年,AMPlab在加州伯克利大学成立,来解决大数据环境下的高级分析和机器学习的问题,随后推出的Berkeley Data Analysis Stack (BDAS)包括Spark,Mesos(内存集群管理,类似于YARN)和Tachyon(内存分布式文件系统),其中Spark得到了大量采用。
Spark是基于内存的具有容错的分布式处理框架,它将MapReduce做了上层抽象,从而提高了开发效率,同时解决了传统MapReduce的磁盘I/O问题。
Spark和Hadoop紧密配合,并使用HDFS做持久化。
Spark也支持SQL,

Spark SQL provides a Spark-specific implementation of SQL for ad hoc queries, and there is also an active effort to allow Hive— the SQL implementation in the Hadoop stack—to generate Spark code.

Spark, Hadoop, and the Berkeley Data Analytics Stack的框架如下:

Cloudera, Hortonworks和MapR都集成了Spark。
Spark基于JVM实现,Spark可以存储string, Java对象,主要还是key-value存储。
Spark虽希望将数据在内存中处理,但Spark还是主要用于无法将所有数据完全置于内存中的情形。
Spark并非面向OLTP,因此也就没有事务日志的概念。
Spark也可以访问JDBC兼容的数据库,包括几乎所有的关系型数据库,以及NoSQL数据库如HBase 或 Cassandra。
Spark的处理流程如下图:

结论

断言磁盘已死还为时过早,毕竟磁盘对于冷数据和温数据具成本优势,特别是在大数据时代。
当性能的需求比存储成本更重要时,就可以考虑SSD和内存数据库,特别是当数据库可以整个置于内存中时,内存数据库具有更大的吸引力。
总之,没有一种技术可以解决所有问题,这取决于你的需求,预算等因素,更多看到的应是磁盘,SSD和内存技术的结合。

你可能感兴趣的:(内存数据库,In-Memory,Computing,Technology)