Skip to content

Dynamic Create Drop ColumnFamily

mytrygithub edited this page Jul 10, 2023 · 11 revisions

(一)背景

一直以来,SidePlugin 不支持动态创建 ColumnFamily,这主要是出于性能方面的考虑,动态创建 ColumnFamily 的应用场景很少,但是它会引发一些性能开销,例如 MyRocks 中为处理该问题还使用了对象级 TLS 以改善它引起的性能问题。

在 MyTopling 中,我们彻底禁用了动态创建 ColumnFamily,彻底消除了这个问题。

注意:

ToplingDB 默认禁用了动态创建 ColumnFamily,要启用它:

make DEBUG_LEVEL=0 # must clean to delete old *.o files
make -j`nproc` EXTRA_CXXFLAGS='-DROCKSDB_DYNAMIC_CREATE_CF' rocksdbjava DEBUG_LEVEL=0

(二)SidePlugin 支持动态创建 ColumnFamily 功能

我们在 2023-06-08 新增了该功能,该功能原本只写了个空壳,现在已经完整实现:

2.1. C++

struct DB_MultiCF { // 略去无关代码,使用动态创建 CF 功能时,仅有这些成员是可用的
  virtual Status CreateColumnFamily(const std::string& cfname,
                                    const std::string& spec,
                                    ColumnFamilyHandle**) = 0;
  virtual Status DropColumnFamily(const std::string& cfname) = 0;
  virtual Status DropColumnFamily(ColumnFamilyHandle*) = 0;
  DB* db = nullptr;
  // 使用动态创建 CF 功能时,无法安全地访问 cf_handles,用户需要自行管
  // 理 CreateColumnFamily 返回的 cf
  std::vector<ColumnFamilyHandle*> cf_handles;
};

示例代码:dyna_new_cf.cc

2.2. Java

// 省略其它方法,Java 中 无 DB_MultiCF 相应的 class,用户代码需要自行管理所有 CF 对象
public class SidePluginRepo extends RocksObject {
  public ColumnFamilyHandle createCF(RocksDB db, String cfname, String spec) throws RocksDBException;
  public void dropCF(RocksDB db, String cfname) throws RocksDBException;
  public void dropCF(RocksDB db, ColumnFamilyHandle cfh) throws RocksDBException;
}

2.3. 参数 spec

CreateColumnFamily/createCF 的参数 spec 用来指定 cf option,一般情况下是在 json/yaml 中定义的 CFOptions 对象名。

2.4. 为什么不能直接使用 DB::CreateColumnFamily

ToplingDB 通过 SidePlugin 进行配置管理,直接使用 DB::CreateColumnFamily,就会导致创建出来的 CF 在 SidePlugin 中感知不到:

  • WebView 上看不到
  • 各种元对象和配置参数也脱离了 SidePlugin 的控制

(三)打开未定义的 ColumnFamily

json/yaml 文件中可能只定义了最基础的 CF,甚至完全没有定义 CF,然后在运行中动态创建了很多 CF,但下一次 Open DB 时,又要指定所有 CF,而这几乎是不可能完成的事情。

为了解决该问题,我们在 json/yaml 中新增了一个参数 dyna_cf_opt(完整配置):

## 省略...省略...省略...省略...省略...
databases:
  db_bench_enterprise:
    method: DB::Open
    params:
      db_options: "$dbo"
      column_families:  # for multi cf db
        default: "$default"
      dyna_cf_opt: "$default"
      path: /dev/shm/db_bench_enterprise
open: db_bench_enterprise

这样,对于在 DB 中存在,但是在 json/yaml 中未定义的 CF,我们可以通过 ListColumnFamilies 获得 cf name,再将 dyna_cf_opt 作为 CFOption,来打开这些 CF。

RocksDB 原始接口中,不同的 CF 可以指定不同的 Option,ToplingDB 的 json/yaml 用 column_families 参数来实现这个目标。但是,通过 dyna_cf_opt,所有未定义的 CF 使用的就是完全相同的 Option,无法实现不同 CF 使用不同 Option。

Clone this wiki locally