现在的位置: 首页 > 数据库 > 正文

Append only和Reuse block之间该怎么选择

2020年07月01日 数据库 ⁄ 共 1658字 ⁄ 字号 评论关闭

  毫无疑问,正如每一种NoSQL都有其适用场景,这里每一种访问需求都有不同的答案,针对用户的访问需求做决定和测试产品是唯一正确的选择。下面学步园小编来讲解下Appendonly和Reuseblock之间该怎么选择?

  Appendonly和Reuseblock之间该怎么选择

  简单来说,antirez的观点就是:

  Appendonlybtree不会出现数据不一致的情况。因为它是只追加的,没有重用文件中的失效块。因为在blockI/Olayer,内核会做一些IO上的调度,以致我们的IO请求会和我们预期的不一致。(FIXME)这一点我后面会开一篇文章详细讲解。

  Appendonlybtree的过期数据清理会是很大的问题,很可能会出现compaction永远赶不上write,这样就会一直在做compaction。

  关于这一点,我曾经在内部邮件里跟人探讨过,过期数据清理如何才能不影响系统性能。

  最重要的两点:

  数据文件分多文件。在这一点上除了BerkeleyDBJavaEdition(以下简称JE)我还没有见到哪个NOSQL产品是如此设计的。

  Btree的数据结构。这一点其实要略次,不如上一点重要。

  下面就JE的compaction(官方称clean)操作进行讲解:

  目前JE里面的clean操作即这里的compaction,后台clean线程会根据其记录的数据目录下每个文件的utilization(利用率)判断是否需要对该文件执行clean操作,默认的配置是5%,如果某个文件有效数据低于了5%,那么clean线程将会读取这个文件里面的有效数据,append到目录下的最后一个文件(这个操作是可以在内存中的,叫deferwrite),最后直接删除这个文件,整个流程是可以多线程并行的(每个线程对应当前的若干文件)。另外,最重要的是,因为b+tree的设计读取某个节点需要将其父节点load到内存(父节点维护了到子节点的指针及子节点的key),因此即使进行所有数据的clean,那么只需要其b+tree非叶节点在内存中,你只需要在父节点上删除指向该节点的指针即可,除了最后拷贝文件的那5%的有效数据(这些数据还很有可能在Cache里),基本不会存在任何的io操作(删除文件并不耗时)。以1亿数据量为例,假设单条记录是1kb,默认每个非叶子节点可以有128个子节点,也就是说只要你为JE分配4.5GB内存,那么你的B+tree所有索引(非叶子节点,100w个左右)都可以在内存中了,此时你做clean的话,其IO消耗几乎可以不计了。这一设计在JE中叫Lazymigration。

  看到这里我想大家应该就能明白,对于appendonlyfile,为什么多文件的设计会更好,这也算是解决了去年我的海量数据存储之Key-Value存储简介一文中的伏笔。

  Appendonly和Reuseblock之间该怎么选择

  而选择B+tree而不使用Hash的原因又多了一个-_-。

  至于Reuseblocks为什么不好,下面给出几条数据:

  SSD盘上读、写、擦除操作耗时依次是:

  20microseconds,200microseconds,1500microseconds

  擦除操作是写操作的7倍多。也就是说在SSD上,我们重用块的代价远大于重写节点,这还没有考虑写入放大以及SSD寿命的因素,众所周知,SSD在随机写多的情况下性能损耗非常厉害。

  结论,这里虽然appendonly胜出,但是并不是说reuseblock不好,至少innodb的成功证明了它是正确的,而如此选择的前提是,数据如果用纯内存去装太不明智了,因为互联网数据访问是有热点的,在“内存是新的硬盘硬盘是新的磁带“到来之前,SSD毫无疑问是这个过度时期的最佳选择。

  以上就是关于“Appendonly和Reuseblock之间该怎么选择”的内容,希望对大家有用。更多资讯请关注学步园。学步园,您学习IT技术的优质平台!

抱歉!评论已关闭.