RocksDB引擎載入
RocksDB引擎的載入,具體操作是透過DB:Open()方法進行的,具體實現類是DBImpl類。 1.引擎載入call stack
Rocksdb引擎註冊和載入時call stack:
###Step 1.在storage engine plugin中的宣告,在ha_rocksdb.cc原始檔中 myrocks::rocksdb_init_func, /* Plugin Entry Point */ ### Step 2.初始化plugin,在載入時被呼叫,在ha_rocksdb.cc原始檔中 static int rocksdb_init_func(void *p) ### Step 3.開啟TransactionDB,事務支援,在transaction_db.cc原始檔中 status= rocksdb::TransactionDB::Open(main_opts, tx_db_options,rocksdb_datadir, cf_descr, &cf_handles, &rdb); ###4.最終呼叫DBImpl實現類的DB::Open方法,完成引擎載入,這裡面的 ###dbname不是資料庫名,而是rocksdb的”data_dir”。在db_impl.cc原始檔中 s = DB::Open(db_options_2pc, dbname, column_families_copy, handles, &db); s = ValidateOptions(db_options, column_families); |
當DB::Open()方法被呼叫並載入引擎時,在此database中的所有CF將被初始化。 2.Column Families後設資料讀取
在上面的”Step 2”中,也就是初始化plugin時,會根據rocksdb的”data_dir”,list出所有的cf,也就是會呼叫下面的方法:
status= rocksdb::DB::ListColumnFamilies(rocksdb_db_options, rocksdb_datadir,&cf_names); |
這裡,我們詳細看一下cf是如何被全部list出來的。
在rocksdb的”data_dir”目錄下面有一個“CURRENT”檔案。我們來strings一把,發現CURRENT檔案中存放的內容為“MANIFEST-000017”,這個內容剛好是當前最新的MANIFEST檔案。
那麼,這是不是巧合呢?我們來看一下原始碼上的執行路徑:
###Step 1:找到CURRENT檔案 // Read "CURRENT" file, which contains a pointer to the current manifest file std::string current; Status s = ReadFileToString(env, CurrentFileName(dbname), ¤t); … ###Step 2:讀取CURRENT檔案 std::string CurrentFileName(const std::string& dbname) { return dbname + "/CURRENT"; } … ###Step3: 從MANIFEST檔案中讀取column families,”default”放在“slot 0“中 std::map column_family_names; // default column family is always implicitly there column_family_names.insert({0, kDefaultColumnFamilyName}); |
從原始碼分析知道,這裡的讀取只是簡單的後設資料資訊而已,並沒有真正的生成記憶體handle物件。真正生成handle物件是在引擎開啟的時候,也就是呼叫DB::Open()方法的時候。
DB::Open方法是開啟rocksdb引擎的入口,它有多個方法的過載。其中有一個過載方法的引數中並沒有”column families”,它只有DB option,dbname(實際上是data_dir)以及DB的指標。這個方法,預設只初始化了”default” CF,隨後將cf以及空的cf handles傳給第二個同名過載方法進行其它非預設CF 初始化。
Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr){ … column_families.push_back( ColumnFamilyDescriptor(kDefaultColumnFamilyName, cf_options)); std::vector handles; Status s = DB::Open(db_options, dbname, column_families, &handles, dbptr); … …}; |
這第二個帶”column_families”和“handles”引數的DB:Open過載方法是初始化和載入所有CF的關鍵。
這裡值得一提的是,如果這個過載方法呼叫後,返回的handles中只有一個元素(handle[0]永遠指向”default” CF); 那麼這個元素將從handles中刪除,因為DBImpl類永遠有一個指標指向”default” CF,不需要再透過handles來獲取。
進入DB:Open()過載方法體後,會進行一系列的檢查,主要檢查db_option和cf option。
db_option主要檢查資料庫的db_path,這個db_path就是我們存放SST Table的物理位置。如果沒有特意配置db_path,那麼一個資料庫只允許存放到一個目錄下。另外,如果指定db_path時,不允許超過4個。
Cf主要檢查各個level 的SST Table當前配置的壓縮演算法是否支援,也就是在原始碼編譯的時候,是否已經link進來。如果沒有,則在open的時候就會報錯,導致rocksdb引擎載入失敗。 3.初始化Table Cache和memTable
進入DB:Open()之後,會new出實現類DBImpl。在DBImpl的構造方法中,主要完成以下幾個功能:
l 初始化table_cache_size
如果“max_open_files==-1“,那table_cache_size的值是” 4194304”,否則就是” max_open_files-10”,保留10個用於其它用途。並按此size初始化table LRU cache佇列。
l 初始化column families 的memTable
根據上面ListColumnFamilies()方法拿到的column families,初始對應的memTable
l DUMP資料庫資訊到日誌檔案
將各種檔案資訊DUMP到rocksdb的日誌檔案中,當然也包含option資訊,還包含SST當前Table所支援的壓縮演算法等
在recover之前,會對wal_dir以及archive_dir目錄進行檢查,如果沒有就會重新建立目錄,預設在db_path下面。
###這把是instrumented鎖,用於統計資訊之類 impl->mutex_.Lock(); // Handles create_if_missing, error_if_exists ###開始恢復操作 s = impl->Recover(column_families); |
進入recover()方法後,會去檢查wal_dir和db_path目錄,並且檢查db_path目錄下的“CURRENT”,”IDENTITY”和“LOCK”檔案。
首先會檢查“LOCK”檔案;再檢查“CURRENT”檔案,此檔案主要指向當前最新的“MANIFEST”檔案,上文已經提到過;最後檢查“IDENTIFY”檔案,此檔案中存放當前rocksdb的唯一標識。
找到“MANIFEST”檔案後,讀取最近“MANIFEST“檔案中的內容。當然首先會判斷”MANIFEST”檔案是否損壞,是否以正常的”\n”結尾。如果”MANIFEST”檔案正常,則開始執行從”MANIFEST”檔案恢復操作。“MANIFEST“檔案類似於Oracle的控制檔案,因此在運維層面需要不斷的備份。
這裡的recover僅僅是檢查並恢復“MANIFEST”檔案中的記錄到記憶體中,這裡會再一次的讀取“MANIFEST”檔案中儲存的column families資訊,並跟前面ListColumnFamilies()方法中讀取到的column families做一個比對。
但是跟ListColumnFamilies()方法不同的是,這裡除了讀取column families資訊以外,還會讀取last_sequence,next_file_number,max_column_familiy等內容。
隨後在DBImpl::CheckConsistency()類中遍歷每個CF下的SST Table物理檔案,檢查實際檔案大小與“MANIFEST“檔案中的後設資料是否一致,如果不一致,則說明已經損壞。
接下來,將是recover的重要一步,就是獲取rocksdb的wal日誌進行回放,apply log的詳細過程,這需先不贅述,下次再展開。
s = RecoverLogFiles(logs, &next_sequence, read_only); |
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30088583/viewspace-2136675/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 編譯GreatSQL with RocksDB引擎編譯SQL
- 【轉載】Rocksdb壓縮詳解
- 渲染引擎的資源載入優化優化
- 編譯ROCKSDB總結編譯
- 【翻譯】rocksdb除錯指引除錯
- 基於Unity3D引擎的大地形載入研究Unity3D
- percona-server-rocksdb-8.0.32 安裝Server
- flink調優之RocksDB設定
- mysql,mariaDB,Percona Server,MongoDB,Redis,RocksDBMySqlServerMongoDBRedis
- RocksDB中文Wiki·Write Stalls的調優
- MySQL入門--儲存引擎MySql儲存引擎
- 懶載入和預載入
- Tesseract引擎的下載和安裝
- 從 RocksDB 看 LSM-Tree 演算法設計演算法
- 【UE5】虛幻引擎入門
- MySQL儲存引擎入門介紹MySql儲存引擎
- 圖片預載入和懶載入
- 載入常量-從檔案中載入
- Vue 路由按需載入(路由懶載入)Vue路由
- 類載入-載入時機學習
- Rocksdb專案中的工業級執行緒池執行緒
- RocksDB 在 vivo 訊息推送系統中的實踐
- 前端效能優化 --- 懶載入&預載入前端優化
- 懶載入
- JS載入JS
- 載入模型模型
- 類載入
- 載入pdf
- 039.Vue3入門,非同步載入元件,初始時不全部載入,使用時才載入Vue非同步元件
- 影像延遲載入 && 列表圖順序載入
- [譯] React 16.6 懶載入(與預載入)元件React元件
- Aurora Engine 遊戲引擎入門 13(新增平臺的輸入)遊戲引擎
- Nebula Graph 特性講解——RocksDB 統計資訊的收集和展示
- Laravel Eloquent中的 懶載入VS即時載入Laravel
- 頁面圖片預載入與懶載入策略
- VIM Lazy Load 懶載入/延遲載入技術
- 滾動載入圖片(懶載入)實現原理
- Java基礎-類載入器以及載入機制Java
- 探祕類載入器和類載入機制