小明思考

Just a software engineer
posts - 124, comments - 36, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

leveldb研究5- Snapshot

Posted on 2012-03-13 16:54 小明 阅读(4466) 评论(0)  编辑  收藏 所属分类: 分布式计算
所谓snapshot就是一个快照,我们可以从快照中读到旧的数据。

先写一个测试程序来看看snapshot的使用:

#include <iostream>
#include 
"leveldb/db.h"

using namespace std;
using namespace leveldb;


int main() {
    DB 
*db ;
    Options op;
    op.create_if_missing 
= true;
    Status s 
= DB::Open(op,"/tmp/testdb",&db);

    
if(s.ok()){
        cout 
<< "create successfully" << endl;
        s 
= db->Put(WriteOptions(),"abcd","1234");
        
if(s.ok()){
            cout 
<< "put successfully" << endl;
            
string value;
            s 
= db->Get(ReadOptions(),"abcd",&value);
            
if(s.ok()){
                cout 
<< "get successfully,value:" << value << endl;
            }
        }
        
if(s.ok()){
            
string value;
            
const Snapshot * ss =db->GetSnapshot();
            ReadOptions rop;
            db
->Put(WriteOptions(),"abcd","123456");
            db
->Get(rop,"abcd",&value);
            
if(s.ok()){
                    cout 
<< "get successfully,value:" << value << endl;
            }
            rop.snapshot 
= ss;
            db
->Get(rop,"abcd",&value);
            
if(s.ok()){
                    cout 
<< "get from snapshot successfully,value:" << value << endl;
            }
            db
->ReleaseSnapshot(ss);
        }
    }
    delete db;
    
return 0;
}

程序运行的输出结果是:
create successfully
put successfully
get successfully,value:1234
get successfully,value:123456
get from snapshot successfully,value:1234

可以看出,即使在数据更新后,我们仍然可以从snapshot中读到旧的数据。

下面我们来分析leveldb中snapshot的实现。

SequenceNumber(db/dbformat.h)
SequenceNumber是leveldb很重要的东西,每次对数据库进行更新操作,都会生成一个新的SequenceNumber,64bits,其中高8位为0,可以跟key的类型(8bits)进行合并成64bits。
typedef uint64_t SequenceNumber;

// We leave eight bits empty at the bottom so a type and sequence#
// can be packed together into 64-bits.
static const SequenceNumber kMaxSequenceNumber =
    ((0x1ull << 56) - 1);

SnapShot(db/snapshot.h),,可以看出snapshot其实就是一个sequence number
class SnapshotImpl : public Snapshot {
 
public:
  
//创建后保持不变
  SequenceNumber number_;  

 
private:
  friend 
class SnapshotList; 

  
//双向循环链表
  SnapshotImpl* prev_;
  SnapshotImpl
* next_;

  SnapshotList
* list_;                 // just for sanity checks
};

创建snapshot:
const Snapshot* DBImpl::GetSnapshot() {
  MutexLock l(
&mutex_);
  
return snapshots_.New(versions_->LastSequence());
}

删除snapshot:
void DBImpl::ReleaseSnapshot(const Snapshot* s) {
  MutexLock l(
&mutex_);
  snapshots_.Delete(reinterpret_cast
<const SnapshotImpl*>(s));
}





只有注册用户登录后才能发表评论。


网站导航: