<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小明思考

    Just a software engineer
    posts - 124, comments - 36, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
    我們知道,leveldb在寫數(shù)據(jù)的時候,除了log文件,都要在內(nèi)存中寫一份。

    先看看SkipList【跳表】這個數(shù)據(jù)結(jié)構(gòu):


    SkipList有如下特點(diǎn):
    1. 本質(zhì)上一個排序好的鏈表
    2. 分層,上層節(jié)點(diǎn)比下層的少,更具有跳躍性
    3. 查詢的復(fù)雜度是O(logn)

    SkipList跟紅黑樹等還是比較容易實(shí)現(xiàn)和理解的,主要長處是比較容易實(shí)現(xiàn)Lock free和遍歷。
    我們來看看leveldb的實(shí)現(xiàn)
    插入:
    //插入一個新的key
    template<typename Key, class Comparator>
    void SkipList<Key,Comparator>::Insert(const Key& key) {
      
    //查找插入節(jié)點(diǎn),prev為各層的前置節(jié)點(diǎn)
      Node* prev[kMaxHeight];
      Node
    * x = FindGreaterOrEqual(key, prev);

      
    // Our data structure does not allow duplicate insertion
      assert(x == NULL || !Equal(key, x->key));

      
    //生成隨機(jī)高度
      int height = RandomHeight();
      
    if (height > GetMaxHeight()) {
        
    for (int i = GetMaxHeight(); i < height; i++) {
          prev[i] 
    = head_;
        }
        
    //設(shè)置當(dāng)前最大高度
        max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
      }

      
    //生成新節(jié)點(diǎn)
      x = NewNode(key, height);
      
    for (int i = 0; i < height; i++) {
        
    //設(shè)置新節(jié)點(diǎn)的各層的下一跳
        x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
        
    //設(shè)置前節(jié)點(diǎn)的next為當(dāng)前節(jié)點(diǎn),完成插入
        prev[i]->SetNext(i, x);
      }
    }

    查詢:
    template<typename Key, class Comparator>
    typename SkipList
    <Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
        
    const {
      Node
    * x = head_;
      
    int level = GetMaxHeight() - 1//從高層開始查找,依次到0 level
      while (true) {
        Node
    * next = x->Next(level); 
        
    if (KeyIsAfterNode(key, next)) { //比next key 要大
          
    // Keep searching in this list
          x = next;
        } 
    else { //比next key小,查找下一層
          
    //標(biāo)記當(dāng)前l(fā)evel的前置節(jié)點(diǎn)
          if (prev != NULL) prev[level] = x;
          
    if (level == 0) {
            
    return next;
          } 
    else {
            level
    --;
          }
        }
      }
    }

    template
    <typename Key, class Comparator>
    bool SkipList<Key,Comparator>::Contains(const Key& key) const {
      Node
    * x = FindGreaterOrEqual(key, NULL);
      
    if (x != NULL && Equal(key, x->key)) {
        
    return true;
      } 
    else {
        
    return false;
      }
    }


    接著我們看看leveldb MemTable的實(shí)現(xiàn),很簡單了,基本是對SkipList訪問一個封裝
    <db/memtable.h>
    class MemTable {
     
    public:
      
    explicit MemTable(const InternalKeyComparator& comparator);

      
    //增加引用計(jì)數(shù)
      void Ref() { ++refs_; }

      
    //減少引用計(jì)數(shù)
      void Unref() {
        
    --refs_;
        assert(refs_ 
    >= 0);
        
    if (refs_ <= 0) {
          delete 
    this;
        }
      }

      
    //內(nèi)存使用量
      size_t ApproximateMemoryUsage();

      
    //遍歷操作
      Iterator* NewIterator();

      
    //插入
      void Add(SequenceNumber seq, ValueType type,
               
    const Slice& key,
               
    const Slice& value);

      
    //查詢
      bool Get(const LookupKey& key, std::string* value, Status* s);

     
    private:
      
    ~MemTable();  // Private since only Unref() should be used to delete it

      
    //key compartor,用于排序
      struct KeyComparator {
        
    const InternalKeyComparator comparator;
        
    explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
        
    int operator()(const char* a, const char* b) const;
      };
      friend 
    class MemTableIterator;
      friend 
    class MemTableBackwardIterator;

      typedef SkipList
    <const char*, KeyComparator> Table;

      KeyComparator comparator_;
      
    int refs_; //引用計(jì)數(shù)
      Arena arena_; //內(nèi)存分配器
      Table table_; //數(shù)據(jù)存放SkipList

      
    // No copying allowed
      MemTable(const MemTable&);
      
    void operator=(const MemTable&);
    };

    先看看插入
    <db/memtable.cc>
    void MemTable::Add(SequenceNumber s, ValueType type,
                       
    const Slice& key,
                       
    const Slice& value) {
      
    //數(shù)據(jù)結(jié)構(gòu):
      
    //1.internal key size : Varint32 (length of 2+3)
      
    //2.key data
      
    //3.SequenceNumber+Key type: 8 bytes
      
    //4 value size: Varint32
      
    //5 value data
      size_t key_size = key.size();
      size_t val_size 
    = value.size();
      size_t internal_key_size 
    = key_size + 8;
      
    const size_t encoded_len =
          VarintLength(internal_key_size) 
    + internal_key_size +
          VarintLength(val_size) 
    + val_size;
      
    char* buf = arena_.Allocate(encoded_len);
      
    char* p = EncodeVarint32(buf, internal_key_size);
      memcpy(p, key.data(), key_size);
      p 
    += key_size;
      EncodeFixed64(p, (s 
    << 8| type);
      p 
    += 8;
      p 
    = EncodeVarint32(p, val_size);
      memcpy(p, value.data(), val_size);
      assert((p 
    + val_size) - buf == encoded_len);
      table_.Insert(buf);
    }

    查詢
    <db/memtable.cc>
    bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
      Slice memkey 
    = key.memtable_key();
      Table::Iterator iter(
    &table_);
      iter.Seek(memkey.data());
      
    if (iter.Valid()) {
        
    // entry format is:
        
    //    klength  varint32
        
    //    userkey  char[klength]
        
    //    tag      uint64
        
    //    vlength  varint32
        
    //    value    char[vlength]
        
    // Check that it belongs to same user key.  We do not check the
        
    // sequence number since the Seek() call above should have skipped
        
    // all entries with overly large sequence numbers.
        const char* entry = iter.key();
        uint32_t key_length;
        
    const char* key_ptr = GetVarint32Ptr(entry, entry+5&key_length);
        
    if (comparator_.comparator.user_comparator()->Compare(
                Slice(key_ptr, key_length 
    - 8),
                key.user_key()) 
    == 0) {
          
    // Correct user key
          const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
          
    switch (static_cast<ValueType>(tag & 0xff)) {
            
    case kTypeValue: {
              Slice v 
    = GetLengthPrefixedSlice(key_ptr + key_length);
              value
    ->assign(v.data(), v.size());
              
    return true;
            }
            
    case kTypeDeletion:
              
    *= Status::NotFound(Slice());
              
    return true;
          }
        }
      }
      
    return false;
    }
    主站蜘蛛池模板: 国产精品69白浆在线观看免费| 亚洲午夜在线电影| 亚洲中文字幕无码爆乳AV| 美女的胸又黄又www网站免费| a毛看片免费观看视频| 亚洲麻豆精品国偷自产在线91| 亚洲精品一卡2卡3卡三卡四卡| 无遮挡呻吟娇喘视频免费播放| 99免费观看视频| 亚洲精彩视频在线观看| 在线看片韩国免费人成视频| 亚洲高清免费在线观看| 亚洲一区在线免费观看| 亚洲欧美日韩中文无线码| 日本午夜免费福利视频| 无码日韩人妻AV一区免费l| 无码专区永久免费AV网站| 亚洲av永久无码精品古装片 | 亚洲va久久久噜噜噜久久天堂 | 亚洲第一福利网站在线观看| 国产精品亚洲片在线花蝴蝶| 亚洲无码视频在线| 亚洲日韩国产AV无码无码精品| 日韩免费人妻AV无码专区蜜桃| 亚洲色WWW成人永久网址| 国产精品免费观看调教网| 亚洲激情视频图片| 免费人成在线观看网站视频| 久青草视频97国内免费影视| 免费国产人做人视频在线观看| 亚洲日本乱码卡2卡3卡新区| 四虎免费影院ww4164h| 老子影院午夜伦不卡亚洲| 亚洲人成网77777色在线播放| 手机永久免费的AV在线电影网| 午夜视频在线在免费| 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 久久精品国产亚洲一区二区三区| 亚洲av成人片在线观看| 亚洲国产另类久久久精品| 成年女人免费视频播放77777|