ceph 中kv 存储的后端选择

filestore的omap中会按照key-value的方式存储对象的属性信息,在ceph中按照key-value存储属性信息有三个版本,分别是levleDB/ROCKSDB/kineticstore/memDB,目前主要用的是rocksDB。这四部分的源码在src/kv中
从其makefile中可以看到
set(kv_srcs
  KeyValueDB.cc
  MemDB.cc
  RocksDBStore.cc)

if (WITH_LEVELDB)
  list(APPEND kv_srcs LevelDBStore.cc)
endif (WITH_LEVELDB)
如果要使用levelDB的话,需要打开with_leveldb这个宏
那ceph 到底是如何选择用哪个kv呢?
在src/common/options.cc 中定义了一个filestore_omap_backend。可以看到默认用的是rocksdb
 Option("filestore_omap_backend", Option::TYPE_STR, Option::LEVEL_DEV)
    .set_default("rocksdb")
    .set_description(""),
在filestore.cc 中的FileStore::mkfs() 函数中
会有如下赋值
  // superblock
  superblock.omap_backend = cct->_conf->filestore_omap_backend;
  ret = write_superblock();
  if (ret < 0) {
    derr << __FUNC__ << ": write_superblock() failed: "
	 << cpp_strerror(ret) << dendl;
    goto close_fsid_fd;
  }
 根据superblock.omap_backend 这个值可以在filestore.cc中的int FileStore::mount() 函数中有如下的code。
     KeyValueDB * omap_store = KeyValueDB::create(cct,
						 superblock.omap_backend,
						 omap_dir);
    if (omap_store == NULL)
    {
      derr << __FUNC__ << ": Error creating " << superblock.omap_backend << dendl;
      ret = -1;
      goto close_current_fd;
    }
在这个create函数中就可以看到用的kv是哪个后端
KeyValueDB *KeyValueDB::create(CephContext *cct, const string& type,
			       const string& dir,
			       void *p)
{
#ifdef WITH_LEVELDB
  if (type == "leveldb") {
    return new LevelDBStore(cct, dir);
  }
#endif
#ifdef HAVE_KINETIC
  if (type == "kinetic" &&
      cct->check_experimental_feature_enabled("kinetic")) {
    return new KineticStore(cct);
  }
#endif
#ifdef HAVE_LIBROCKSDB
  if (type == "rocksdb") {
    return new RocksDBStore(cct, dir, p);
  }
#endif

  if ((type == "memdb") && 
    cct->check_experimental_feature_enabled("memdb")) {
    return new MemDB(cct, dir, p);
  }
  return NULL;
}
从这里我们知道当前系统中所有的支持的kv的后端存储和我们当前的选择
我们看看DBObjectmap中如何读取属性值
int DBObjectMap::get_xattrs(const ghobject_t &oid,
			    const set<string> &to_get,
			    map<string, bufferlist> *out)
{
#首先加锁,说明属性值可以被多个进程同时读取。
  MapHeaderLock hl(this, oid);
  #根据oid找到对应的header,如果没有找到,则根据oid新建一个header
  Header header = lookup_map_header(hl, oid);
  if (!header)
    return -ENOENT;
  #根据header中的seq得到键值
  return db->get(xattr_prefix(header), to_get, out);
}
其中
string DBObjectMap::xattr_prefix(Header header)
{
  return USER_PREFIX + header_key(header->seq) + XATTR_PREFIX;
}
其中header_key的定义如下:
string DBObjectMap::header_key(uint64_t seq)
{
  char buf[100];
  snprintf(buf, sizeof(buf), "%.*" PRId64, (int)(2*sizeof(seq)), seq);
  return string(buf);
}
可见主要是对seq格式化成字符串输出
其中USER_PREFIX 和 XATTR_PREFIX 是两个字符串定义如下:
const string DBObjectMap::USER_PREFIX = "_USER_";
const string DBObjectMap::XATTR_PREFIX = "_AXATTR_";
从这里可以知道kv中的key主要是由seq决定的,而这里的seq是一个
我们知道在get_xattrs 中首先会根据oid新建一个header,以header中的seq为key再保存value,所以seq也是在新建header时候赋值的,具体函数如下:
DBObjectMap::Header DBObjectMap::_generate_new_header(const ghobject_t &oid,
						      Header parent)
{
#新建一个header
  Header header = Header(new _Header(), RemoveOnDelete(this));
  #从这里可以知道header中的seq是由state赋值的,并且会一直递增
  header->seq = state.seq++;
  if (parent) {
    header->parent = parent->seq;
    header->spos = parent->spos;
  }
  header->num_children = 1;
  header->oid = oid;
  assert(!in_use.count(header->seq));
  in_use.insert(header->seq);

  write_state();
  return header;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值