hash

为了实现效率,和list一样,hash在实现的时候也是分为meta数据和field数据,meta数据实际上只有这个key下面的field数量,field数据就是存储自身的value信息。hash不像list那么复杂,每field节点不存在顺序关系,每个field都是独立存在,所以无论是在meta还是field存储的数据都是非常简单的。

数据格式

下面四个表格分别:

  • Hash meta key:
meta 原始key字符串
H(1) key(var)
  • Hash meta value:
数据成员个数
size(8)
  • Hash field key:
meta key长度 key字符串 固定 field key字符串
h(1) key size(1) key(var) =(1) field key(var)
  • Hash field value:
value字符串
value(var)

举例

hset test field1 123

hset test field2 456

  • Hash meta key:
meta 原始key字符串
H(1) key(var)
H test
  • Hash meta value:
数据成员个数
size(8)
1
2
  • Hash field key:
meta key长度 key字符串 固定 field key字符串
h(1) key size(1) key(var) =(1) field key(var)
h 4 test = field1
h 4 test = field2
  • Hash field value:
value字符串
value(var)
123
456

Hash meta key

meta 原始key字符串
H(1) key(var)
inline std::string EncodeHsizeKey(const rocksdb::Slice &name) {
    std::string buf;
    buf.append(1, DataType::kHSize);
    buf.append(name.data(), name.size());
    return buf;
}

inline int DecodeHsizeKey(const rocksdb::Slice &slice, std::string *name) {
    Decoder decoder(slice.data(), slice.size());
    if (decoder.Skip(1) == -1) {
        return -1;
    }
    if (decoder.ReadData(name) == -1) {
        return -1;
    }
    return 0;
}

Hash meta value

数据成员个数
size(8)

typedef DefaultMeta HashMeta;

struct DefaultMeta : public NemoMeta {
  int64_t len;

  DefaultMeta() : len(0) {}
  explicit DefaultMeta(int64_t _len):len(_len) {}
  virtual bool DecodeFrom(const std::string& raw_meta) {
    if (raw_meta.size() != sizeof(uint64_t)) {
      return false;
    }
    len = *(int64_t *)raw_meta.data();
    return true;
  }
  virtual bool EncodeTo(std::string& raw_meta) {
    raw_meta.clear();
    raw_meta.append((char *)&len, sizeof(int64_t));
    return true;
  }
  virtual std::string ToString() {
    char buf[32];
    std::string res("Len : ");
    Int64ToStr(buf, 32, len);
    res.append(buf);
    return res;
  }
};

Hash field key

meta key长度 key字符串 固定 field key字符串
h(1) key size(1) key(var) =(1) field key(var)
inline std::string EncodeHashKey(const rocksdb::Slice &name, const rocksdb::Slice &key) {
    std::string buf;
    buf.append(1, DataType::kHash);
    buf.append(1, (uint8_t)name.size());
    buf.append(name.data(), name.size());
    buf.append(1, '=');
    buf.append(key.data(), key.size());
    return buf;
}

inline int DecodeHashKey(const rocksdb::Slice &slice, std::string *name, std::string *key) {
    Decoder decoder(slice.data(), slice.size());
    if (decoder.Skip(1) == -1) {
        return -1;
    }
    if (decoder.ReadLenData(name) == -1) {
        return -1;
    }
    if (decoder.Skip(1) == -1) {
        return -1;
    }
    if (decoder.ReadData(key) == -1) {
        return -1;
    }
    return 0;
}

Hash field value:

value字符串
value(var)

代码实现

HSet

  • 功能:将哈希表key中的域field的值设为value。
  • 实现:
    • 获取行锁
    • DoHSet具体处理,需要写入的kv,加到writebatch
      • 首先用key和field编码出hash field key,获取这个key对应的值
        • 如果找到,说明原来就存在这个field,相当于修改,返回值设置为0
        • 如果没找到,说明原来这个filed是不存在的,相当于新增,返回值设置为0
      • 将新的hash field value写入到对应的hash field key
    • 判断返回值,如果是新增field,需要调用IncrHLen,修改hash meta value
      • key编码出hash meta key,先取出原来的值,在原来的基础上增加1,加入writebatch
    • 调用WriteWithOldKeyTTLwritebatch写入硬盘
int64_t Nemo::HLen(const std::string &key) {
    std::string size_key = EncodeHsizeKey(key);
    std::string val;
    Status s;

    s = hash_db_->Get(rocksdb::ReadOptions(), size_key, &val);
    if (s.IsNotFound()) {
        return 0;
    } else if(!s.ok()) {
        return -1;
    } else {
        if (val.size() != sizeof(uint64_t)) {
            return 0;
        }
        int64_t ret = *(int64_t *)val.data();
        return ret < 0? 0 : ret;
    }
}

int Nemo::IncrHLen(const std::string &key, int64_t incr, rocksdb::WriteBatch &writebatch) {
    int64_t len = HLen(key);
    if (len == -1) {
        return -1;
    }
    len += incr;
    std::string size_key = EncodeHsizeKey(key);
    writebatch.Put(size_key, rocksdb::Slice((char *)&len, sizeof(int64_t)));
    return 0;
}

int Nemo::DoHSet(const std::string &key, const std::string &field, const std::string &val, rocksdb::WriteBatch &writebatch) {
    int ret = 0;
    std::string dbval;
    Status s = HGet(key, field, &dbval);
    if (s.IsNotFound()) { // not found
        std::string hkey = EncodeHashKey(key, field);
        writebatch.Put(hkey, val);
        ret = 1;
    } else {
        if(dbval != val){
            std::string hkey = EncodeHashKey(key, field);
            writebatch.Put(hkey, val);
        }
        ret = 0;
    }
    return ret;
}

Status Nemo::HSet(const std::string &key, const std::string &field, const std::string &val) {
    if (key.size() >= KEY_MAX_LENGTH || key.size() <= 0) {
       return Status::InvalidArgument("Invalid key length");
    }
    Status s;
    RecordLock l(&mutex_hash_record_, key);
    rocksdb::WriteBatch writebatch;
    int ret = DoHSet(key, field, val, writebatch);
    if (ret > 0) {
        if (IncrHLen(key, ret, writebatch) == -1) {
            return Status::Corruption("incrhlen error");
        }
    }
    s = hash_db_->WriteWithOldKeyTTL(rocksdb::WriteOptions(), &(writebatch));
    return s;
}

HGet

  • 功能:返回哈希表key中给定域field的值
  • 实现:
    • 用key和field编码出hash field key,调用Get接口返回
Status Nemo::HGet(const std::string &key, const std::string &field, std::string *val) {
    if (key.size() >= KEY_MAX_LENGTH || key.size() <= 0) {
       return Status::InvalidArgument("Invalid key length");
    }
    std::string dbkey = EncodeHashKey(key, field);
    Status s = hash_db_->Get(rocksdb::ReadOptions(), dbkey, val);
    return s;
}

HDel

  • 功能:删除哈希表key中的一个指定域,不存在的域将被忽略。
  • 实现:
    • 获取行锁
    • DoHDel具体处理,需要写入的kv,加到writebatch
      • 根据keyfield编码出hash field key,获取hash field value
        • 如果存在,则删除,返回值为1
        • 如果不存在,返回值为0
    • 判断是否删除了field
      • 如果删除了,需要修改hash meta value
int Nemo::DoHDel(const std::string &key, const std::string &field, rocksdb::WriteBatch &writebatch) {
    int ret = 0;
    std::string dbval;
    Status s = HGet(key, field, &dbval);
    if (s.ok()) { 
        std::string hkey = EncodeHashKey(key, field);
        writebatch.Delete(hkey);
        ret = 1;
    } else if(s.IsNotFound()) {
        ret = 0;
    } else {
        ret = -1;
    }
    return ret;
}

Status Nemo::HDel(const std::string &key, const std::string &field) {
    if (key.size() >= KEY_MAX_LENGTH || key.size() <= 0) {
       return Status::InvalidArgument("Invalid key length");
    }
    Status s;
    RecordLock l(&mutex_hash_record_, key);
    rocksdb::WriteBatch writebatch;
    int ret = DoHDel(key, field, writebatch);
    if (ret > 0) {
        if (IncrHLen(key, -ret, writebatch) == -1) {
            return Status::Corruption("incrlen error");
        }
        s = hash_db_->WriteWithKeyTTL(rocksdb::WriteOptions(), &(writebatch));
        return s;
    } else if (ret == 0) {
        return Status::NotFound(); 
    } else {
        return Status::Corruption("DoHDel error");
    }
}

HExists

  • 功能:查看哈希表key中,给定域field是否存在。
  • 实现:
    • 用key和field编码出hash field key,调用Get接口,判断返回值
bool Nemo::HExists(const std::string &key, const std::string &field) {
    Status s;
    std::string dbkey = EncodeHashKey(key, field);
    std::string val;
    s = hash_db_->Get(rocksdb::ReadOptions(), dbkey, &val);
    if (s.ok()) {
        return true;
    } else {
        return false;
    }
}

HKeys

  • 功能:返回哈希表key中的所有域。
  • 实现:
    TODO
    

HGetall

  • 功能:返回哈希表key中,所有的域和值。
  • 实现:
    TODO
    

HLen

  • 功能:返回哈希表 key 中域的数量。
  • 实现:
    TODO
    

HMSet

  • 功能:同时将多个field-value(域-值)对设置到哈希表key中。
  • 实现:
    TODO
    

HMGet

  • 功能:返回哈希表key中,一个或多个给定域的值。
  • 实现:
    TODO
    

HSetnx

  • 功能:将哈希表key中的域field的值设置为value,当且仅当域field不存在。
  • 实现:
    TODO
    

HStrlen

  • 功能:哈希表key中域field的value的长度
  • 实现:
    int64_t Nemo::HStrlen(const std::string &key, const std::string &field) {
      Status s;
      std::string val;
      s = HGet(key, field, &val);
      if (s.ok()) {
          return val.length();
      } else if (s.IsNotFound()) {
          return 0;
      } else {
          return -1;
      }
    }
    

HVals

  • 功能:返回哈希表key中所有域的值。
  • 实现:
    TODO
    

HIncrby

  • 功能:为哈希表 key中的域field的值加上增量increment 。
  • 实现:
    TODO
    

HIncrbyfloat

  • 功能:为哈希表key中的域field加上浮点数增量increment。
  • 实现:
    TODO
    

results matching ""

    No results matching ""