日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ceph-kvstore-tool

發布時間:2024/3/7 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ceph-kvstore-tool 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ceph-kvstore-tool 使用說明

參考鏈接:
https://github.com/ceph/ceph/blob/master/doc/man/8/ceph-kvstore-tool.rst
http://www.idcat.cn/ceph-kvstore-tool%E5%B7%A5%E5%85%B7%E7%AE%80%E5%8D%95%E4%BB%8B%E7%BB%8D.html
https://blog.csdn.net/Z_Stand/article/details/98967671

1. 簡介

ceph-kvstore-tool 是一個 kvstore 操作工具。它允許用戶離線操作 leveldb/rocksdb 的數據(就像 OSD 的 omap)。

[root@node-1 ceph-objectstore-tool-test]# ceph-kvstore-tool -h Usage: ceph-kvstore-tool <leveldb|rocksdb|bluestore-kv> <store path> command [args...]Commands:list [prefix]list-crc [prefix]dump [prefix]exists <prefix> [key]get <prefix> <key> [out <file>]crc <prefix> <key>get-size [<prefix> <key>]set <prefix> <key> [ver <N>|in <file>]rm <prefix> <key>rm-prefix <prefix>store-copy <path> [num-keys-per-tx] [leveldb|rocksdb|...] store-crc <path>compactcompact-prefix <prefix>compact-range <prefix> <start> <end>destructive-repair (use only as last resort! may corrupt healthy data)stats

使用前,關閉 mon 服務 或者 osd 服務

systemctl stop <ceph-mon@node-1>|<ceph-mon@0>

使用完,記得重啟服務

systemctl restart <ceph-mon@node-1>|<ceph-mon@0>

2. 示例

查詢數據庫表項(prefix,前綴)

# cat /var/lib/ceph/mon/ceph-node-1/kv_backend 查詢 mon 使用何種 db ceph-kvstore-tool <rocksdb|leveldb> /var/lib/ceph/mon/ceph-node-1/store.db/ listceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 list# 查看 mon 數據庫中都有哪些表項 ceph-kvstore-tool rocksdb /var/lib/ceph/mon/ceph-node-1/store.db/ list|awk '{print $1}'|uniq# bluestore 表項前綴 # const string PREFIX_SUPER = "S"; // field -> value # const string PREFIX_STAT = "T"; // field -> value(int64 array) # const string PREFIX_COLL = "C"; // collection name -> cnode_t # const string PREFIX_OBJ = "O"; // object name -> onode_t # const string PREFIX_OMAP = "M"; // u64 + keyname -> value # const string PREFIX_PGMETA_OMAP = "P"; // u64 + keyname -> value(for meta coll) # const string PREFIX_PERPOOL_OMAP = "m"; // s64 + u64 + keyname -> value # const string PREFIX_PERPG_OMAP = "p"; // u64(pool) + u32(hash) + u64(id) + keyname -> value # const string PREFIX_DEFERRED = "L"; // id -> deferred_transaction_t # const string PREFIX_ALLOC = "B"; // u64 offset -> u64 length (freelist) # const string PREFIX_ALLOC_BITMAP = "b";// (see BitmapFreelistManager) # const string PREFIX_SHARED_BLOB = "X"; // u64 offset -> shared_blob_t # const string PREFIX_ZONED_FM_META = "Z"; // (see ZonedFreelistManager) # const string PREFIX_ZONED_FM_INFO = "z"; // (see ZonedFreelistManager) # const string PREFIX_ZONED_CL_INFO = "G"; // (per-zone cleaner metadata) ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0/ list | awk '{print $1}'| uniq

打印數據庫中(kv鍵值對)的crc校驗碼

ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0/ list-crc | grep osdmap | head -10# 查詢 kv 數量 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0/ list-crc | wc -l# 查詢 crc 校驗碼數量 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0/ list-crc | awk '{print $3}'| uniq | wc -l

打印 Key-Value 鍵值對

ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 dump [prefix]

查詢表項是否存在(可指定 key)

ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0/ exists <pfefix> [key]

查詢指定 value(可選是否指定輸出文件)

ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0/ get <prefix> <key> [out <file>]# 通過 ceph-dencoder 工具反序列化解析 ceph-kvstore-tool rocksdb /var/lib/ceph/mon/ceph-node1/store.db/ get osdmap full_999 out ./osdmap.full ceph-dencoder import osdmap.full type OSDMap decode dump_json

查詢對象大小,若不指定前綴+key,則返回整個 db 大小

ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 /var/lib/ceph/osd/ceph-0/ get-size [<prefix> <key>]

更改 key 或 value

# 這條命令含義是:把指定【前綴+key】的 key 替換為 N,或者把該指定【前綴+key】的內容替換為 file ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 set <prefix> <key> [ver <N>lin <file>]

壓縮數據庫(緩解 rocksdb 寫放大)

# rocksdb 數據分為多層,并且每層都可能有重復數據,啟用 compact 可以把數據層層壓縮到最底層,并且刪除重復數據,起到壓縮空間的作用 # 壓縮整個數據庫 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 compact# 壓縮指定前綴的數據 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 compact-prefix <prefix># 壓縮指定前綴的 key=[start~end] 范圍的數據 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 compact-range <prefix> <start> <end>

刪除

ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 rm <prefix> <key># 刪除整個前綴下的數據 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 rm-prefix <prefix>

備份

# path:備份到指定路徑,num-keys-per-tx:每次事務中進行備份的 kv 數量 ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 store-copy <path> [num-keys-per-tx] [leveldb|rocksdb|...] # 備份所有 kv 的 crc ceph-kvstore-tool bluestore-kv /var/lib/ceph/osd/ceph-0 store-crc <path>

3. 源碼分析

main

int main(int argc, const char *argv[]) {// 參數解析vector<const char*> args;argv_to_vec(argc, argv, args);// global 初始化auto cct = global_init(&defaults, args,CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);common_init_finish(g_ceph_context);// 根據 store-type 初始化 storetoolStoreTool st(type, path, to_repair, need_stats);// 根據命令行 cmd 參數,執行對應的函數if (cmd == "destructive-repair") {... }else if(cmd == "rm")... }

StoreTool

StoreTool::StoreTool(const string& type,const string& path,bool to_repair,bool need_stats): store_path(path) {// 根據 type,創建 kv 句柄,其中 bluestore-kv,需要調用 bluestore->open_db_environmentif (type == "bluestore-kv") {if (load_bluestore(path, to_repair) != 0)exit(1);} else {// 創建 kv 句柄 auto db_ptr = KeyValueDB::create(g_ceph_context, type, path);} }int StoreTool::load_bluestore(const string& path, bool to_repair) {// 創建 bluestoreauto bluestore = new BlueStore(g_ceph_context, path);KeyValueDB *db_ptr;// 通過 bluestore 獲取 kvdbint r = bluestore->open_db_environment(&db_ptr, to_repair);db = decltype(db){db_ptr, Deleter(bluestore)};return 0; }

destructive-repair

數據因為宕機發生遺失時,可以嘗試通過 repair 修復,注意:沒有寫入日志文件的數據無法恢復。

int StoreTool::destructive_repair() {return db->repair(std::cout); } /*目前 ceph 后端的 kvdb 一般使用 rocksdb,其修復過程分為以下4步驟:查找文件把日志轉化為表導出metadata寫描述符 */

list/list-crc

void StoreTool::list(const string& prefix, const bool do_crc,const bool do_value_dump) {traverse(prefix, do_crc, do_value_dump,& std::cout); }uint32_t StoreTool::traverse(const string& prefix,const bool do_crc,const bool do_value_dump,ostream *out) {// 獲取數據庫迭代器KeyValueDB::WholeSpaceIterator iter = db->get_wholespace_iterator();// 如果設置了 prefix,則把迭代器調到第一次出現 prefix 的位置 if (prefix.empty())iter->seek_to_first();elseiter->seek_to_first(prefix);uint32_t crc = -1;// 循環查詢,直到迭代器為 invalidwhile (iter->valid()) {pair<string,string> rk = iter->raw_key();// 設置跳出循環條件if (!prefix.empty() && (rk.first != prefix))break;if (out)*out << url_escape(rk.first) << "\t" << url_escape(rk.second);if (do_crc) {bufferlist bl;bl.append(rk.first);bl.append(rk.second);bl.append(iter->value());// 計算 crc 值crc = bl.crc32c(crc);if (out) {*out << "\t" << bl.crc32c(0);}}if (out)*out << std::endl;iter->next();}return crc; }

exist

bool StoreTool::exists(const string& prefix, const string& key) {// 未指定 key,調用 StoreTool::exists(const string& prefix)if (key.empty()) {return exists(prefix);}bool exists = false;// 在指定 key,則調用 get(),下文介紹該方法get(prefix, key, exists);return exists; }bool StoreTool::exists(const string& prefix) {KeyValueDB::WholeSpaceIterator iter = db->get_wholespace_iterator();// 通過迭代器去查詢第一次出現 prefix 位置,查不到則為 invaliditer->seek_to_first(prefix);return (iter->valid() && (iter->raw_key().first == prefix)); }

get

bufferlist StoreTool::get(const string& prefix,const string& key,bool& exists) {map<string,bufferlist> result;std::set<std::string> keys;keys.insert(key);// 獲取指定 prefix、key 的 value,結果保存在 resultdb->get(prefix, keys, &result);// result 中的鍵值對數量大于0,則表示存在該 key if (result.count(key) > 0) {exists = true;return result[key];} else {exists = false;return bufferlist();} }// rocksdb get 查詢使用方法如下 int RocksDBStore::get(const string &prefix,const std::set <string> &keys,std::map <string, bufferlist> *out) {rocksdb::PinnableSlice value;if (cf_handles.count(prefix) > 0) {for (auto &key : keys) {// 若指定 prefix,則需要創建 cf(columfamily)列族句柄auto cf_handle = get_cf_handle(prefix, key);// 調用 Get 方法查詢auto status = db->Get(rocksdb::ReadOptions(),cf_handle,rocksdb::Slice(key),&value);if (status.ok()) {(*out)[key].append(value.data(), value.size());} else if (status.IsIOError()) {ceph_abort_msg(status.getState());}value.Reset();}} else {for (auto &key : keys) {string k = combine_strings(prefix, key);// 未指定 prefix,使用默認句柄:rocksdb::ColumnFamilyHandle *default_cf = nullptr;auto status = db->Get(rocksdb::ReadOptions(),default_cf,rocksdb::Slice(k),&value);if (status.ok()) {(*out)[key].append(value.data(), value.size());} else if (status.IsIOError()) {ceph_abort_msg(status.getState());}value.Reset();}}return 0; }

get-size

// 返回 bl 大小 bufferlist bl = st.get(prefix, key, exists); std::cout << "(" << url_escape(prefix) << "," << url_escape(key)<< ") size " << byte_u_t(bl.length()) << std::endl;

set

// 解析命令行參數 if (subcmd == "ver") {version_t v = (version_t) strict_strtoll(argv[7], 10, &errstr);encode(v, val);} else if (subcmd == "in") {int ret = val.read_file(argv[7], &errstr);} // 調用 StoreTool::set 方法bool ret = st.set(prefix, key, val);bool StoreTool::set(const string &prefix, const string &key, bufferlist &val) {// rocksdb 支持事務提交,步驟如下:/* rocksdb::WriteBatch bat;* rocksdb::WriteOptions woptions;* woptions.sync = !disableWAL;* auto cf = db->get_cf_handle(prefix, k);* put_bat(bat, cf, k, to_set_bl);* int result = submit_common(woptions, t);*/KeyValueDB::Transaction tx = db->get_transaction();tx->set(prefix, key, val);int ret = db->submit_transaction_sync(tx);return (ret == 0); }

store-copy

int StoreTool::copy_store_to(const string &type, const string &other_path,const int num_keys_per_tx,const string &other_type) {// 在參數路徑位置新建或者打開 kvdb// open or create a leveldb store at @p other_pathboost::scoped_ptr <KeyValueDB> other;KeyValueDB *other_ptr = KeyValueDB::create(g_ceph_context,other_type,other_path);if (int err = other_ptr->create_and_open(std::cerr); err < 0) {return err;}other.reset(other_ptr);// 獲取舊 db 的迭代器KeyValueDB::WholeSpaceIterator it = db->get_wholespace_iterator();// 調整迭代器位置it->seek_to_first();// 循環提交事務,直到舊 db 的迭代器遍歷完數據庫do {int num_keys = 0;// 創建新 db 事務KeyValueDB::Transaction tx = other->get_transaction();// 通過舊迭代器查詢,向新 db 的單次事務中寫入 num-keys-per-tx 數量的寫操作while (it->valid() && num_keys < num_keys_per_tx) {auto[prefix, key] = it->raw_key();bufferlist v = it->value();tx->set(prefix, key, v);num_keys++;total_size += v.length();it->next();}// 提交事務if (num_keys > 0)other->submit_transaction_sync(tx);} while (it->valid());print_summary(total_keys, total_size, total_txs, store_path, other_path,duration());return 0; }

compact

void RocksDBStore::compact() {logger->inc(l_rocksdb_compact);rocksdb::CompactRangeOptions options;// 壓縮db->CompactRange(options, default_cf, nullptr, nullptr);for (auto cf : cf_handles) {for (auto shard_cf : cf.second.handles) {db->CompactRange(options,shard_cf,nullptr, nullptr);}} }

總結

以上是生活随笔為你收集整理的ceph-kvstore-tool的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。