`

lsm tree@hbase

 
阅读更多

众所周知传统磁盘I/O是比较耗性能的,优化系统性能往往需要和磁盘I/O打交道,而磁盘I/O产生的时延主要由下面3个因素决定

  • 寻道时间(将磁盘臂移动到适当的柱面上所需要的时间,寻道时移动到相邻柱面移动所需时间1ms,而随机移动所需时间位5~10ms)
  • 旋转时间(等待适当的扇区旋转到磁头下所需要的时间)
  • 实际数据传输时间(低端硬盘的传输速率为5MB/ms,而高速硬盘的速率是10MB/ms)

近20年平均寻道时间改进了7倍,传输速率改进了1300倍,而容量的改进则高达50000倍,这一格局主要是因为磁盘中运动部件的改进相对缓慢和渐进,而记录表面则达到了相当高的密度。对于一个块的访问完全由寻道时间和旋转延迟所决定,所以花费相同时间访问一个盘块,那么取的数据越多越好。

由于操作磁盘的速度远远低于CPU和内存,并且差距越来越大,磁盘I/O已经成为很多系统的瓶颈;与此同时磁盘高速缓存也迅速增加,进而很大一部分读请求是直接来自文件系统高速缓存的,并不需要磁盘访问操作,I/O的优化很大程度上着手于对写操作的优化。

解决思路

I/O类型

磁盘I/O瓶颈可能出现在seek(寻道)和transfer(数据传输)上面。

根据磁盘I/O类型,关系型存储引擎中广泛使用的B树及B+树,而Bigtable的存储架构基础的会使用Log-Structured Merge Tree。

B树

B树是与红黑树类似的一颗平衡查找树,但在降低磁盘I/O操作次数方面更好一些,B树具有较低的深度,查找一个元素只需将很少节点从磁盘Load到内存,很快便能访问到要查找的数据。

  1. 每个节点x有以下域:
    • x.n,节点x包含的关键字个数。
    • x.n keys本身,以非降序排列,因此
    • x.leaf,布尔值,如果x是叶节点,则为TRUE,若为内节点,则为FALSE
  2. 每个内节点x包含x.n+1个指向其子女的指针,叶节点没有子女,故他们子女的指针域无定义。
  3. 如果ki为存储在节点x子节点内的关键字则:
  4. 每个叶节点具有相同的深度,即树的高度h
  5. 每个节点所包含的关键字个数x.n包含一个上界和下界,用一个固定的整数t>=2来表式;
    • 每个非根的节点至少包含t-1个关键字。每个非根的内节点至少有t个子女,如果树是非空的,则根节点至少包含一个关键字。
    • 每个节点至多包含2t-1个关键字,所以说一个内节点至少包含2t个子女,我们说一个节点是满的,如果这个节点恰好包含2t-1个关键字。

一棵高度为3的B树,它包含最小可能的关键字数,在每个节点x内显示的是n[x]一棵高度为3的B树,它包含最小可能的关键字数,在每个节点x内显示的是n[x]

B+树是B树的一个变种,B+树比B树更适合实现外存储索引结构,MySQL存储引擎普遍使用B+Tree实现其索引结构。内节点只包含键值以及指向子节点的指针,数据存储在叶子节点,所有记录节点都是按照键值的大小顺序存放在同一层的叶节点中,各节点指针进行连接(双向链表)。
一棵高度为2的B+树一棵高度为2的B+树

如图:所有记录都在叶节点中,井且是顺序存放的,如果我们从最左边的
叶节点开始顺序遍历,可以得到所有镗值的顺序排序15、10、15、20、25、30、50、55、60、 65、 75、 80、 85、 90

B+树索引在数据库中有一个特点就是其高扇出性,因此数据库中B+树的高度一般都在2~3层*,也就是说对于查找某一键值的行记录,最多只需要2到3次IO。

性能分析

如果没有太多的写操作,B+树可以工作的很好,它会进行比较繁重的优化来保证较低的访问时间。而写操作往往是随机的,随机写到磁盘的不同位置上,更新和删除都是以磁盘seek的速率级别进行的。RDBMS通常都是Seek型的,主要是由用于存储数据的B树或者是B+树结构引起的,在磁盘seek的速率级别上实现各种操作,通常每个访问需要log(N)个seek操作.

 

而LSM-tree工作在磁盘传输速率的级别上,可以更好地扩展到更大的数据规模上,保证一个比较一致的插入速率,因为它会使用日志文件和一个内存存储结构1,把随机写操作转化为顺序写2,读操作与写操作是独立的,这样这两种操作之间就不会产生竞争


在传输等量数据场景下,随机写I/O的时延大部分花费在了seek操作上,数据库对磁盘进行零碎的随机写会产生多次seek操作;而顺序存取只需一次seek操作,便可以传输大量数据,针对批量写入大量数据的场景,顺序写比随机写具有明显的优势。


lsm树的一个重要思想就是通过使用某种算法,该算法会对索引变更进行延迟及批量处理,并通过一种类似于归并排序的方式高效地将更新迁移到磁盘适,进行批量写入,利用磁盘顺序写性能远好于随机写这一特点,将随机写转变为顺序写,从而保证对磁盘的操作是顺序的,以提升写性能,同时建立索引,以获取较快的读性能,在读和写性能之间做一个平衡。

 

LSM-Tree适用于那些写入频率远大于读取频率的场景,很多Nosql的比如HBase、LevelDB等系统都借鉴了LSM-Tree的思想实现的.

lsm-tree

LSM树的本质就是将大量的随机写转化为批量的顺序写,这样可以极大提升磁盘写入速度,所以lsm树非常适用于对写操作有高要求的场景,但是付出的代价是读效率有所降低。

算法介绍

LSM-Tree由多个组件组成,下面以2个组件的情形为例做简单介绍:

Schematic picture of an LSM-tree of two components
Schematic picture of an LSM-tree of two components

如上图所示:一个两组件的LSM-Tree包含一个内存组件C0和一个较大的被持久化在磁盘上面的组件C1。写入或者更新某条记录时,首先会预写日志,用于数据写入失败时进行数据恢复。之后该条记录会被插入到驻留在内存中的C0树,在符合某个条件的时候从被移到磁盘上的C1树中。

 

记录从C0移到C1中间肯定存在一定时间的延迟,由于这段时间内更新未做持久化,为了防止意外情况下内存中的数据丢失,所以记录恢复该插入操作的日志是很有必要的。

 

C0树不一定要具有一个类B-树的结构。首先,它的节点可以具有任意大小:没有必要让它与磁盘页面大小保持一致,因为C0树永不会位于磁盘上,因此我们就没有必要为了最小化树的深度而牺牲CPU的效率,一个2-3树或者是AVL树就可以作为C0树使用的一个数据结构,HBase中采用了线程安全的ConcurrentSkipListMap数据结构。

 

向内存中的C0树插入一个条目速度是非常快的,因为操作不会产生磁盘I/O开销。然而用于C0的内存成本要远高于磁盘,通常做法是限制它的大小。采用一种有效的方式来将记录迁移到驻留在更低成本的存储设备上的C1树中。为了实现这个目的,在当C0树因插入操作而达到接近某个上限的阈值大小时,就会启动一个rolling merge过程,来将某些连续的记录段从C0树中删除,并merge到磁盘上的C1树中。

Conceptual picture of rolling merge steps, with result written back to diskConceptual picture of rolling merge steps, with result written back to disk

合并过程如上图所示:Rolling merge实际上由一系列的merge步骤组成。首先会读取一个包含了C1树中叶节点的multi-page block,这将会使C1中的一系列记录进入缓存。之后,每次merge将会直接从缓存中以磁盘页的大小读取C1的叶节点,将那些来自于叶节点的记录与从C0树中拿到的叶节点级的记录进行merge,这样就减少了C0的大小,同时在C1树中创建了一个新的merge好的叶节点。

磁盘上的C1树是一个类似于B-树的数据结构,但是它是为顺序性的磁盘访问优化过的,所有的节点都是满的,为了有效利用磁盘,在根节点之下的所有的单页面节点都会被打包放到连续的多页面磁盘块(multi-page block)上,将对一个页面的寻道时间分摊到多个页面上面。

 

merge后新的blocks会被写入到磁盘新的位置上,这样老的blocks就不会被覆盖,在crash发生后的恢复中就是可用的。C1中的父目录节点也会被缓存在内存中,此时也会被更新以反映出叶节点的变动,同时父节点还会在内存中停留一段时间以最小化IO;当merge步骤完成后,C1中的老的叶节点就会变为无效状态,之后会被从C1目录结构中删除。通常,每次都是C1中的最左边的叶节点记录参与merge,因为如果老的叶节点都是空的那么merge步骤也就不会产生新的节点,这样也就没有必要进行。除了更新后的目录节点信息外,这些最左边的记录在被写入到磁盘之前也会在内存中缓存一段时间,用于提供在merge阶段的并发访问和从crash后的内存丢失中进行恢复,为了减少恢复时的重构时间,merge过程需要进行周期性的checkpoints,强制将缓存信息写入磁盘。

 

随着时间的推进将会有更多的flush操作发生,会产生很多存储文件,一个后台进程负责将这些文件聚合成更大的文件,这样磁盘seek操作就限制在一定数目的存储文件上。存储在磁盘上的树结构也可以被分割成多个存储文件。因为所有的存储数据都是按照key排序的,因此在现有节点中插入新的keys时不需要重新进行排序。

 

查找通过merging的方式完成,首先会搜索内存存储结构,接下来是磁盘存储文件。通过这种方式,从客户端的角度看到的就是一个关于所有已存储数据的一致性视图,而不管数据当前是否驻留在内存中。删除是一种特殊的更新操作,它会存储一个删除标记,该标记会在查找期间用来跳过那些已删除的keys。当数据通过merging被重新写回时,删除标记和被该标记所遮蔽的key都会被丢弃掉。

 

用于管理数据的后台进程有一个额外的特性,它可以支持断言式的删除。也就是说删除操作可以通过在那些想丢弃的记录上设定一个TTL(time-to-live)值来触发。比如,设定TTL值为20天,那么20天后记录就变成无效的了。Merge进程会检查该断言,当断言为true时,它就会在写回的blocks中丢弃该记录。

不足之处

存在写放大问题,同一份数据随着合并的过程,可能会被写入多次。

hbase的实现

在HBase中,HFile要求写入的数据是按照KeyValue排好序的,而HDFS本身被设计为顺序读写(sequential reads/writes),写完之后便不允许修改。为了解决这个问题,HBase将最近接收到的数据缓存在内存中(in Memstore),在持久化到HDFS之前完成排序,然后再批量快速的顺序写入HDFS。

MemStore

MemStore是HBase中C0的实现,向HBase中写数据的时候,首先会写到内存中的MemStore,当达到一定阀值之后,这个MemStore会被冻结,不再响应写请求,产生一个新的MemStore来响应写请求,之前的MemStore会flush(顺序写)到磁盘,形成新的StoreFile,StoreFile又会进行merge.

hbase memstore and storefilehbase memstore and storefile

用到Memstore最主要的原因是:HFile要求写入的数据是按照KeyValue排好序的,而HDFS本身被设计为顺序读写(sequential reads/writes),不允许修改。为了解决这个问题,HBase将最近接收到的数据缓存在内存中(in Memstore),在持久化到HDFS之前完成排序,然后再批量快速的顺序写入HDFS,相比传统数据库随机写来说,实际上只要一次寻址便可以将大量数据写到磁盘,加快了数据持久化的速度。

memstore内部维护了一个数据结构:ConcurrentSkipListMap<keyvalue, keyvalue=""> 实现了SortedMap接口,数据存储是按照Key排好序的跳跃列表是在很多应用中有可能替代平衡树而作为实现方法的一种数据结构。跳跃列表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。

skip listskip list

Skip list的性质:

  • 由很多层结构组成,level是通过一定的概率随机产生的。
  • 每一层都是一个有序的链表,默认是升序,也可以根据创建映射时所提供的Comparator进行排序,具体取决于使用的构造方法。
  • 最底层(Level 1)的链表包含所有元素。
  • 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
  • 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素

除(O(logn))完成写入、读取操作之外,还可以根据提供的Comparator进行顺序遍历,进而实现顺序写磁盘生成StoreFile。

HFile

HFlile是lsm tree中C1的实现,其数据结构和leveldb基本一致,采用sstable,为了分析方便:逻辑上将HFile分成Index节点和Data节点;

索引记录和数据记录都是按照key(row,family,coqualifier,ts)字典序排好序的
其中Index节点的每条记录,分别指向到不同的Block,包含以下信息:

  • 如果是最底层的索引则指向数据块的第一个key,否则指向Index块的第一个key
  • 数据块在HFile中的偏移(指针)
  • 磁盘中数据块的大小,如果经过压缩,则是压缩后的大小

下面是索引记录样例。


key=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaZI/info:city/LATEST_TIMESTAMP/Put
  offset=2155038, dataSize=38135 

key=aaaaaaaaaaaaaaaaabbbabbaaaabbbbaTU/info:city/LATEST_TIMESTAMP/Put
  offset=4343199, dataSize=38358

key=aaaaaaaaaaaaaaaabbbababbbbababaaxe1T70L5R6F2/info:city/LATEST_TIMESTAMP/Put
  offset=6539008, dataSize=38081

HFile逻辑上面是一棵满的B+树,发现如果root_index的size达到一定阀值(128K),便会加一级索引;

用pi来表式每条索引记录,则大体可以划出如下逻辑图:

HFile组织结构HFile组织结构

较小的数据量,索引的深度会只有一层,随着表的不断变大,root_index的size达到一定阀值(128K),便会加一层索引。

对于查找过程,HFile中的KeyValue是排好序的,sorted意为数据的存储顺序是按照key的字符串的字典排列顺序升序组织的,并且对key构建了索引。检索时,把index block加载到内存中,通过二分查找找到对应的datablock,即在data index中查找当前查询的key可能在哪个data block中,之后将datablock装载到内存(为了提升性能会有缓存策略),接着顺序遍历这个data block,找到key及value。

search storefilesearch storefile

通过对这些索引以树状结构进行组织,只让顶层索引常驻内存,其他索引按需读取并通过LRU cache进行缓存,这样就不需要将全部索引加载到内存。

删除操作

由于同一个key可能存在内存或者磁盘上面的多个文件中,所以执行删除操作相对复杂些,hbase中删除操作并不是真正的删除,只是简单的做下标记,所以性能极快,并在合并过程中进行真正的物理删除。

性能因素

  1. 如果建表时,一个row对应多个列,或者多个版本,那么一个HFileBlock所能存放的keyvalue就会越少,尤其是寻找最新数据时,可能跨越多个块。
  2. 扫描操作会不停地将块加到缓存,如果多个进行扫描缓存块,而只有一个进程来淘汰块,那么很可能会发生内存溢出,所以在线下计算需要大量扫描的情况下,一定关闭cache.
  3. StoreFile过多会影响读性能,因为一个读操作很可能会需要打开多个HFile,io次数太多,会影响性能
  4. HFile block越大越适合顺序扫描(大的快解压速度会变慢)但是随机读写性能降低,小的HFile block更加适合随机读写,但是需要更多地内存来存放index 默认(128KB)
  5. HFileV2的索引分成多层,虽然可以减少内存的使用量,加快启动速度,但是多了1-2次IO,尤其是HFile文件较大时,随机读很可能比V1要多2次IO操作,进而读取速度变慢。

参考:

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.44.2782&rep=rep1&type=pdf

http://duanple.blog.163.com/blog/static/7097176720120391321283/

分享到:
评论

相关推荐

    LSM_Tree实验报告1

    LSM Tree,全称为Log-Structured Merge Tree,是一种优化过的数据结构,主要应用于高性能的数据库系统,例如Google的levelDB、Facebook的RocksDB以及Apache的HBase等。相较于传统的B+树,LSM Tree的设计目标是提高...

    12 LSM 树在 Apache HBase 等存储系统中的应用1

    LSM 树(Log-Structured Merge-Tree)是 HBase 等存储系统中的一种核心数据结构,通过巧妙地优化数据写入和读取流程,实现了高效的数据管理。 LSM 树的核心思想是将随机写入转化为顺序写入,从而极大地提高了磁盘的...

    Hadoop(四)C#操作Hbase.doc

    LSM Tree(Log-Structured Merge Tree)是HBase为解决B+Tree写入慢的问题而采用的一种数据结构。在LSM Tree中,写入首先被记录在WAL(Write-Ahead Log)中,保证数据安全,同时数据被存入内存中的数据结构(如跳表)...

    HBase内核及能力.pdf

    HBase的特性与生态:自动分区、LSM Tree、存储计算分离、HBase生态;全新的HBase2.0版本新功能:小对象存储MOB、读写链路Off-heap 、Region Replica 、In Memory Compaction 、Assignment MangerV2 、其他;HBase未来...

    高可用HBase的技术实践

    3. **LSM-Tree**:采用Log-Structured Merge Tree (LSM-Tree)模型来优化写操作性能,适合于写密集型应用。 4. **基于K-V的行组织**:数据按照键值对的方式存储,支持高并发读写。 5. **存储计算分离**:HBase基于...

    HBase专场:阿里云HBase产品体系架构及特性解析(封神).pdf

    最后,文档中提到了一些技术术语和组件,例如HDFS、LSM-Tree、Phoenix、Kylin等,这些是HBase生态系统中重要的组件和概念,它们与HBase紧密配合,扩展了HBase的功能和应用范围。例如,HDFS作为Hadoop的分布式文件...

    Hbase架构简介、实践

    - **LSM树(Log-Structured Merge Tree)**:这是一种数据结构,用于提高读取性能。通过将写入操作记录到磁盘上的日志文件中,然后周期性地合并这些日志文件来减少磁盘访问次数。这种结构非常适合大数据环境下的读...

    阿里巴巴HBase的一些实践与探索.pdf

    2. **LSM Tree(Log Structured Merge Tree)**:HBase采用LSM Tree数据结构,将随机写入转化为顺序写入,提高了写入性能,降低了SSD随机写入放大的影响,同时减少了存储空间的开销。 3. **存储计算分离**:这种...

    《HBASE系统运维实践》淘宝资深数据库工程师许飞飞

    HBase的LSMTree(Log-Structured Merge-Tree)是一种存储结构,它把数据的插入操作转化为追加写操作,这种方式可以提高写入速度,并且保证写入的稳定性。与传统数据库的B+树相比,LSM-Tree在处理追加写、合并读操作...

    HBase应用与发展之ApacheHBase的现状和发展.pdf

    #### LSM-Tree(Log Structured Merge Tree) - **数据写入机制**:所有写操作首先记录在一个内存中的日志结构中,随后周期性地刷新到磁盘上。 - **随机写变顺序写**:这种方式避免了传统B+树在随机写入时遇到的...

    HBase概述——HBase的存储模型.pdf

    《HBase概述——HBase的存储模型》这篇文章深入解析了HBase的核心存储机制,即LSM树(Log-Structured Merge Tree)。LSM树是一种优化的存储结构,它旨在解决大数据场景下的高性能写入和读取需求。在HBase中,LSM树的...

    HBase在淘宝的应用和优化

    - **高性能读写**:利用LSM-Tree设计确保即使在数据量巨大的情况下也能保持较快的写入速度; - **灵活的数据模型**:支持灵活的列族和列定义,允许动态增加列; - **强一致性**:保证数据的一致性,满足业务系统对...

    Hbase配置.docx

    它采用Log-Structured Merge Tree(LSM树)作为索引结构,允许快速的插入和删除操作,并且数据以列族的形式存储,提高了数据检索效率。 3. **内存优化**: HBase将热点数据缓存在内存中,提高读取速度。当内存不...

    DB总结

    LSM Tree(Log-Structured Merge Tree)是一种磁盘存储结构,常用于键值存储系统,如HBase。LSM Tree通过牺牲一部分随机写性能来提高顺序写性能,从而在大容量数据存储中提供高效性能。 7. **HBase常用配置**: ...

    大数据云存储HBase实践与探索.pptx

    - **LSM-Tree**: 使用LSM-Tree(Log-Structured Merge Tree)数据结构,优化写入性能并降低磁盘IO。 - **自动分区**: 自动分区策略允许数据根据键值自动分布,实现数据的均衡分布。 - **多版本**: 支持多版本特性,...

    藏经阁-大数据时代的存储 ——HBase的实践与探索.pdf

    首先,HBase 的自动分区和LSM_Tree 存储计算分离特点使得它能够高效地存储和处理大数据。其次,HBase 的存储计算分离设计使得它能够更好地扩展和优化存储资源。最后,HBase 的高可靠性和高可用性使得它能够满足...

    基于日志结构合并树的轻量级分布式索引实现方法.pdf

    通过使用LSM-Tree,HBase能够有效地管理和存储大量数据。查询优化是指通过优化数据库的索引策略和查询算法以提高数据检索速度的过程。在分布式数据库中,合理的索引策略对于提高查询性能至关重要。 文章的主要内容...

    Hbase.docx

    1. **LSM树(Log-Structured Merge Tree)** - **定义**:LSM树是一种特殊的树形数据结构,被设计用于提高磁盘数据写入效率。它的设计理念是在内存中维护最新的数据变更,然后批量地将这些变更写入磁盘,以此减少随机...

    大数据技术基础培训-HBase技术介绍.pptx

    与传统的关系型数据库B+树不同,HBase采用了Log-Structured Merge-Tree(LSM树)的数据结构,这种设计优化了写操作,通过先将数据写入日志,然后批量写入内存,当内存满时再flush到磁盘。后台线程会定期合并磁盘上的...

Global site tag (gtag.js) - Google Analytics