LSM Tree(Log-structured merge-tree)广泛应用在HBase,TiDB等诸多数据库和存储引擎上,我们先来看一下它的一些应用:
这么牛X的名单,你不想了解下LSM Tree吗?装X之前,我们先来了解一些基本概念。
设计数据存储系统可能需要考虑的一些问题有:ACID,RUM(Read,Write,Memory)。
ACID
ACID 相信小伙伴都被面试官问过,我想简单讨论的一点是:如何 持久化数据 才能保证数据写入的 事务性 和 读写性能?
事务性可简单理解为:1.数据必须持久化。2.一次数据的写入返回给用户 写入成功就一定成功,失败就一定失败。
读写性能可简单理解为:一次读 或 一次写 需要的IO次数,因为访问速率:CPU>>内存>>SSD/磁盘。
对于单机存储,最简单的方式当然是:写一条就持久化一条,读一条就遍历一遍所有数据,然后返回。当然没人这么干,在内存中我们都还知道用个HashMap呢。
拿Mysql InnoDB举例子:读性能体现在数据的索引在磁盘上主要用B+树来保证。写性能体现在运用 WAL机制 来避免每次写都去更新B+树上的全量索引和数据内容,而是通过redo log记录下来每次写的增量内容,顺序将redo log写入磁盘。同时在内存中记录下来本次写入应该在B+树上更新的脏页数据,然后在一定条件下触发脏页的刷盘。
redo log是数据增删改的实时增量数据,顺序写入保证了写性能和事务性。磁盘上的B+树是数据增删改的全量数据,通过定时脏页刷盘保证这份数据的完整性。
这里的问题是:虽然通过WAL机制,提高了写入性能,但是仍然避免不了脏页数据定时刷盘的随机IO写入。因为数据在磁盘上是以block为单位存储的(比如4K,16K),假如你更新了Order表一条数据,又更新了Product表一条数据,脏页刷盘时,这两条数据在磁盘上的block位置可能差了十万八千里,就变成了随机IO的写入。
RUM
RUM(Read,Write,Memory)类似分布式领域的CAP定理。如果想得到三者中的两者性能,必须以牺牲第三者的性能为代价。衡量这三者的性能指标有:读放大、写放大、空间放大。
**读放大:**是指每次查询读取磁盘的次数。如果每次查询需要查询5个page (或block),则