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/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30088583/viewspace-2136675/