leveldb数据完全性及性能问题

笑天居士 发布于 2014/10/28 10:19
阅读 1K+
收藏 1
看到leveldb的一个文档,向memtable写数据之前会先写log,那意味着每写一次内存都写LOG到磁盘,那么性能如何保证?如果LOG不到磁盘,如何保证极端情况下,如掉电后的数据不丢失呢?
加载中
0
兮风古道
兮风古道
这个问题很关键。写log 是一个顺序写的过程,速度非常快 。 
0
兮风古道
兮风古道
刚测了一下磁盘的顺序写和随机写的速度, 随机写是0.67M/s , 而顺序写是 83.24M/s。 leveldb的巧妙之处就是把原本磁盘的随机写,转换成了速度非常高效顺序写。 
0
Alex_Hark
Alex_Hark
那么高的读写效率,写数据的过程,依赖SSTable文件,(.sst)块文件块大小记得是64k,即便丢失也是很少量的

笑天居士
笑天居士
块大小是64K,也就是说会在缓存中缓存64K后再刷到磁盘 “即便丢失也是很少量的”,那就是说不能用leveldb做关键的存储了?如用户钱袋、余额等
Alex_Hark
Alex_Hark
如果追求极端 没有完美
0
仪山湖
仪山湖

LevelDB采用LSM算法加速insert这个过程的,简单的LSM由两个Tree构成,一个Tree在内存中,可以是AVL或2、3Tree,称为C0,另外一个Tree是B+Tree,位于磁盘中,称为C1, 当C0中的节点达到一定数量时,把一些叶子节点批量移到C1中,这个过程叫Merge, 因为LOG的产生都是顺序的,所以Merge的永远只会在C1点某一些叶子节点上发生,Merge过程如下,首先把C1,C0上需要的merge的节点读出来,按照B+Tree的规则,重新生两个叶子节点,这两个叶子节点追加到C1点过程中,新节点写到磁盘也是顺序的,但会更新C1中被merge节点的父节点的子节点的块引用,以及这两个新节点的父节点的块引用。复杂的LSM可以有C0, C1, C2, ..., Ck个Tree,用来减少树操作的磁盘IO开销。C1, C2, ..., Ck这些B+Tree的块信息一般存储在内存中,用于快速检索“块”。

LSM在记录插入的时候,是非常高效对,在查找纪录时,必须要分多步查找C0, C1, C2, ..., Ck,效率比传统的AVL, B+Tree低一些,综合来看,LSM在数据库系统中比前两者表现的更好。

除来LevelDB外,Casandra、HBase也采用LSM算法。

0
笑天居士
笑天居士
就是考虑极端情况,假如把用户钱袋存在leveldb,极端掉电,数据会不会丢失呢?
0
笑天居士
笑天居士

找到源码解析了:

  1.       // 将更新写入log文件,如果设置了每次写入进行sync,则将其同步到磁盘,这个操作可能比较长,  
  2.       // 防止了mutex_对象长期被占用,因为其还负责其他一些资源的同步  
  3.       status = log_->AddRecord(WriteBatchInternal::Contents(updates));  
  4.       if (status.ok() && options.sync) {  
  5.         status = logfile_->Sync();  
  6.       }  
  7.       if (status.ok()) {  
  8.         // 成功写入了log后,才写入memtable  
  9.         status = WriteBatchInternal::InsertInto(updates, mem_);  
  10.       } 

笑天居士
笑天居士
可以设置为每次更新都写入LOG,但是性能会很低
返回顶部
顶部