博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ceph 中kv 存储的后端选择
阅读量:4216 次
发布时间:2019-05-26

本文共 3212 字,大约阅读时间需要 10 分钟。

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
&to_get, map
*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;}

转载地址:http://xcnmi.baihongyu.com/

你可能感兴趣的文章
iOS GitHub上常用第三方框架
查看>>
ios 隐藏cell分割线和自定义cell分割线颜色
查看>>
ios 图片保存到系统相册
查看>>
UIAlertController样式集合
查看>>
数据结构之—图
查看>>
计算机网络基础
查看>>
C++中内存(堆和栈)
查看>>
循环队列
查看>>
网络基础知识点总结1
查看>>
操作系统知识点总结1
查看>>
C++常见知识点总结
查看>>
Linux知识点小结One
查看>>
数据库知识点小结
查看>>
指针、内存和字节
查看>>
设计模式中类的关系
查看>>
策略模式、代理模式
查看>>
单例模式(singleton),工厂方法模式(factory),门面模式(facade)
查看>>
抽象模式,适配器模式(Adapter),模板方法模式(Template method)
查看>>
建造者模式(builder),桥梁模式(bridge mode),命令模式(Command mode)
查看>>
装饰模式(Decorator),迭代器模式(Iterator),组合模式(composite)
查看>>