-
Notifications
You must be signed in to change notification settings - Fork 6
Home
关于 ToplingDB SidePlugin 的设计动机,请参考 Motivation To Solution
将现有使用 RocksDB 的代码迁移到 ToplingDB,请参考从零开始使用 ToplingDB
ToplingDB SidePlugin 配置系统采用 json/yaml 格式定义配置项,将 ToplingDB/RocksDB 的所有元对象均纳入此配置系统。总体而言,ToplingDB 配置系统实现了以下目标:
- ToplingDB/RocksDB 的所有配置需求
- 动态、开放、解耦的插件方案
- 用户代码无需修改,即可使用第三方模块(例如 ToplingZipTable)
- 编写新的插件无需引入不相关的依赖(类似傻代码: if (is BlockBasedTable) ... else if (is PlainTable) ...)
- 可视化:通过 Web Service 展示引擎内部状态(站外文档)
- 监控:通过 Web Service 将引擎指标导出到 Prometheus,进而使用 grafana 可视化
- 通过 Web Service 使用 REST API 在线修改配置
- 简化多语言 Binding (只需要 bind conf 对象即可)
ToplingDB/RocksDB 的根配置对象是 DBOptions 和 ColumnFamilyOptions,额外的 Options 对象是 DBOptions 和 ColumnFamilyOptions(简称 CFOptions) 的结合体(从后两者继承而来)。
DBOptions 和 CFOptions 中包含二级配置对象,有些二级对象还进一步包含三级配置对象。所有这些对象,都定义为 json 中以其基类名命名的一级 json 对象的子对象,另外,json 中还有另外几个特殊的一级 json 对象(http,setenv,databases,open)。可以在 json 对象中引用其它 json 对象,这些引用将转化成 C++ 对象间的引用关系。
DBOptions 和 CFOptions 还支持用 template 指定一个作为模板的 DBOptions/CFOptions 对象,当前对象先从模板拷贝过来,然后再修改。
{
"http": {
"document_root": "/path/to/dbname",
"listening_ports": "8081"
},
"setenv": {
"DictZipBlobStore_zipThreads": 8,
"StrSimpleEnvNameNotOverwrite": "StringValue",
"IntSimpleEnvNameNotOverwrite": 16384,
"OverwriteThisEnv": { "overwrite": true,
"value": "overwrite is default to false, can be manually set to true"
}
},
"permissions": { "web_compact": true },
"Cache": {
"lru_cache": {
"class": "LRUCache",
"params": {
"capacity": "4G", "num_shard_bits": -1, "high_pri_pool_ratio": 0.5,
"strict_capacity_limit": false, "use_adaptive_mutex": false,
"metadata_charge_policy": "kFullChargeCacheMetadata"
}
}
},
"WriteBufferManager" : {
"wbm": {
"class": "Default",
"params": {
"//comment": "share mem budget with cache object ${lru_cache}",
"buffer_size": "512M", "cache": "${lru_cache}"
}
}
},
"Statistics": { "stat": "default" },
"TableFactory": {
"bb": {
"class": "BlockBasedTable",
"params": { "block_cache": "${lru_cache}" }
},
"fast": {
"class": "SingleFastTable",
"params": { "indexType": "MainPatricia" }
},
"zip": {
"class": "ToplingZipTable",
"params": {
"localTempDir": "/dev/shm/tmp",
"sampleRatio": 0.01, "entropyAlgo": "kNoEntropy"
}
},
"dispatch" : {
"class": "DispatcherTable",
"params": {
"default": "fast",
"readers": { "SingleFastTable": "fast", "ToplingZipTable": "zip", "BlockBased": "bb" },
"level_writers": ["fast", "fast", "fast", "zip", "zip", "zip", "zip"]
}
}
},
"CFOptions": {
"default": {
"max_write_buffer_number": 4, "write_buffer_size": "128M",
"target_file_size_base": "16M", "target_file_size_multiplier": 2,
"table_factory": "dispatch", "ttl": 0
},
"cf2": {
"template": "${default}",
"comments": "copy from ${default} cf, then update write_buffer_size and cf_paths",
"write_buffer_size": "256M",
"cf_paths": "/path/to/cf2/data/dir"
}
},
"databases": {
"db1": {
"method": "DB::Open",
"params": {
"options": {
"write_buffer_manager": "${wbm}",
"create_if_missing": true, "table_factory": "dispatch"
}
}
},
"db_mcf": {
"method": "DB::Open",
"params": {
"db_options": {
"create_if_missing": true,
"create_missing_column_families": true,
"write_buffer_manager": "${wbm}",
"allow_mmap_reads": true
},
"column_families": {
"default": "$default",
"custom_cf" : {
"max_write_buffer_number": 4,
"target_file_size_base": "16M",
"target_file_size_multiplier": 2,
"table_factory": "dispatch", "ttl": 0
}
},
"path": "'dbname' passed to Open. If not defined, use 'db_mcf' here"
}
}
},
"open": "db_mcf"
}
在这个示例中,第一个 json 子对象是:
"http": {
"document_root": "/", "listening_ports": "8081"
}
这个 http 对象定义了用作 Web 展示的 Http Web Server 配置。完整的 http 参数请参考:CivetWeb UserManual。
"setenv": {
"DictZipBlobStore_zipThreads" : 8
}
setenv 的每个子对象定义一个环境变量。
permissions 的每个子对象定义一个权限。
可以在 databases 之下定义多个 database 对象,database 对象分为两大类:
- 只包含默认 ColumnFamily 的 DB
- 包含多个 ColumnFamily 的 DB (
DB_MultiCF
)
这两类 database 通过其是否包含子对象 column_families
来区分。哪怕一个 database 实际上只有一个 ColumnFamily,但它将该 ColumnFamily 定义在子对象 column_families
中,那它也是 DB_MultiCF
,column_families
中必须包含子对象 default
,因为 RocksDB 必定有 default cf。
可以将 DB_MultiCF
的 DB 当作单 CF 的 DB 打开。
database 对象通过 method 指定的函数打开,C++ 代码中 method 是重载的,在 json 中 method 也是重载的,相同的 method,对 DB 和 DB_MultiCF
分别重载。
虽然我们可以在 json 中定义多个 database,但很多时候,我们只会打开其中的一个 database,当使用无 database 名字的 OpenDB api 时,这个 open 对象用来指定打开哪个 database。当用户使用了带 db 名字的 OpenDB api 时,这个 open 对象就被忽略。
json 的一级对象中,除以上 4 种特殊对象,其它都是一般对象,每个一级的一般对象的名字是 ToplingDB/RocksDB 中此类对象的基类的类名。例如示例中的 "Cache", "Statistics", "TableFactory",这些一级对象本身相当于一个容器,其中每个子对象定义了真正的 C++ 对象。这样的每个“容器”相当于一个 namespace,不同 namespace 下可以有同名的对象。
json 对象对应的 C++ 对象包含类名和参数,分别通过 "class" 和 "params" 来表达。细心的用户可以发现,对象名为 "stat" 的 json 是字符串 "default",这是为了简化,对于无参的 class,可以直接使用其类名的字符串来定义(此处"default" 是 stat 的注册类名,对应的 C++ 类是 StatisticsImpl),当然,这种对象也可以用一个包含 "class" 和 "params" 的完整正规的 json 对象来定义。
DBOptions 和 CFOptions 是比较特殊的一般对象,因为其 "class" 是确定的,所以免去了 "class" 和 "params",直接将 "params" 中的成员提升到外层。
在 C++ 对象中,一个对象引用另一个对象通过指针来实现,在 json 中,通过对象名来实现,对象引用的正式的完全的写法是 "${varname}",简化写法可以是 "$varname" 或 "varname",其中,"varname"可能会导致歧义,因为一个 json 字符串也可能表达的是 "class_name"
。我们的处理方式是:先看该字符串是否是一个已定义的对象,如果是,就按照"varname"处理,否则按照 "class_name"
处理。
除了定义命名的对象,然后按名字引用对象,我们也可以定义内嵌对象,例如示例中的:
"custom_cf" : {
"max_write_buffer_number": 4,
"target_file_size_base": "16M",
"target_file_size_multiplier": 2,
"table_factory": "dispatch", "ttl": 0
}
"custom_cf"
可以定义为一个 CFOptions 对象的引用,但是在这里,把它定义为一个内嵌对象更加方便简洁。
CFOptions 中没有 ttl 成员,但我们在 json 中为它定义了 ttl,这是因为,database 的 "method" 除了可以指定为 "DB::Open",还可以指定为其它很多函数:
"DB::OpenForReadOnly" // 等效于在 params 中定义 read_only: true
"DBWithTTL::Open" // 需要 CFOptions::ttl
"TransactionDB::Open"
"OptimisticTransactionDB::Open"
"BlobDB::Open"
用户还可以扩展定义自己的 Open 例如:MyCustomDB::Open。
"dispatch" : {
"class": "DispatcherTable",
"params": {
"default": "fast",
"readers": {"SingleFastTable": "fast", "ToplingZipTable": "zip"},
"level_writers": ["fast", "fast", "fast", "zip", "zip", "zip", "zip"]
}
}
顾名思义,DispatcherTable 用来进行实际的 Table(SST) 分发及调度,对用户来讲,最关键的是 level_writers
:在相应的 level 上使用相应的 Table。
default 用来定义当 level < 0 时(level 是 TableBuilderOptions 的成员),或者 level_writer
创建 builder 失败时,作为 fallback。
readers 用来定义 class_name
到 varname 的映射,因为在内部实现中,加载 Table 是通过 DispatcherTable::NewTableReader
实现的,作为 dispather,自然需要知道加载的 Table 具体是哪种 Table,这是通过 TableMagicNumber 来区分的,是编译期静态确定的,但是 TableFactory 是运行时创建的,并且每个具体的 TableFactory class 可以有多个(params 不同的) object,所以,我们需要在这里指定相应的 TableFactory class 使用哪个 TableFactory object 来加载。
在这个 DispatcherTable 定义中,L0~L2 使用 fast,L3~L6 使用 zip。
ToplingDB 以解压后的尺寸衡量的 wamp(写放大),DispatcherTable 会对候选 compact 进行审查,如果不符合条件,会拒绝 compact,对 trivial move 也类似,如果审查不符合 trivial move 条件,会拒绝 trivial move,从而进行实质 compact。
配置项名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
measure_builder_stats | bool | false | 测量分层统计信息 |
always_compact_max_bytes | uint | 64 MiB | 尺寸小于该值时总是 compact |
auto_compaction_max_wamp | float | 1e9 | 自动触发的 compact 写放大小于该值才会执行 |
mark_for_compaction_max_wamp | float | 1e9 | 标记触发的 compact 写放大小于该值才会执行 |
allow_trivial_move | bool | true | 是否允许 trivial move,允许时才进一步判断 |
trivial_move_always_max_output_level | int | 0 | 目标层号小于等于该值时执行 |
trivial_move_max_file_size_multiplier | float | 4.0 | 目标层的文件尺寸小于输入文件平均尺寸的这么多倍时执行 |
熟悉 Kubernetes 的用户,可能更喜欢 Yaml,作为配置文件,Yaml 的可读性更好,ToplingDB 配置系统也支持 Yaml。
企业版均包含 ToplingZipTable
,基于可检索内存压缩算法的 SST,使用多实例共享分布式 Compact 集群能通过规模效应实现降本增效。
社区版不包含 ToplingZipTable,除此之外,企业版与社区版完全相同。
Json | Yaml | 说明 |
---|---|---|
etcd_dcompaction.json | yaml | 带分布式 Compact |
lcompact_community.json | yaml | 不带分布式 Compact |
db_bench_community.yaml | yaml | db_bench 测试,无 json |
db_bench_enterprise.yaml | yaml | db_bench 测试,无 json |
todis-community.json | yaml | todis 社区版 |
todis-enterprise.json | yaml | todis 企业版 |
mytopling.json | yaml 暂无 | MyTopling 企业版 |
mytopling-2nd.json | yaml 暂无 | MyTopling 企业版,共享从库 |
mytopling-community.json | yaml 暂无 | MyTopling 社区版 |
kvtopling-community.json | yaml 暂无 | kvrocks ToplingDB 社区版 |
kvtopling-community-2nd.json | yaml 暂无 | kvrocks ToplingDB 社区版,共享从库 |