Skip to content

Latest commit

 

History

History
203 lines (164 loc) · 16 KB

README-zh_CN.md

File metadata and controls

203 lines (164 loc) · 16 KB

分布式 Compact

概述

ToplingDB 中,dcompact(Distributed Compaction) 在形式上是作为一个 SidePlugin 实现的,也就是说,要使用分布式 Compact,用户代码不需要任何修改,只需要改 json/yaml 配置文件。

在分布式 Compact 的实现中:

  1. 运行 ToplingDB/RocksDB 的一方称为 Hoster,在 Server/Client 模型中,是 Client
  2. 运行 dcompact_worker 的一方称为 Worker,在 Server/Client 模型中,是 Server
  3. 同一个 worker 可以同时为多个 hoster 服务,同一个 hoster 也可以把自己的 compact 任务发给多个 worker 执行
  4. 编译 ToplingDB 时,本模块(topling-dcompact)由 ToplingDB 的 Makefile 中从 github 自动 clone 下来

用户自定义的插件,例如 MergeOperator, CompactionFilter 等需要编译成动态库,运行 dcompact_worker.exe 时通过 LD_PRELOAD 加载。使用这种方式,相同进程可以加载多个不同的动态库,从而为多个不同的 DB 提供 compact 服务,例如 MyTopling(MySQL)Todis(Redis) 就使用这种方式共享相同的 dcompact_worker 进程。

分布式 Compact 的实现类名是 DcompactEtcd,这是因为 ToplingDB 分布式 Compact 最初是通过 etcd-cpp-api 使用 etcd 用作 Hoster 与 Worker 的交互,后来因为 etcd-cpp-api 的 bug #78 而不得不弃用 etcd。目前 etcd 相关代码已经无用,仅有 DcompactEtcd 作为类名保留下来。

1. 配置

1.1. json 配置示例

分布式 Compact 在 json 配置文件中进行设置:

  "CompactionExecutorFactory": {
    "dcompact": {
      "class": "DcompactEtcd",
      "params": {
        "allow_fallback_to_local": true,
        "hoster_root": "/nvmepool/shared/db1",
        "instance_name": "db1",
        "nfs_mnt_src": ":/nvmepool/shared",
        "nfs_mnt_opt": "nolock,addr=192.168.31.16",
        "http_max_retry": 3,
        "http_timeout": 1,
        "http_workers": [
          "http://active-host:8080",
          { "url": "http://worker.for.submit.compact.job",
            "base_url": "http://worker.for.probe.and.shutdown.compact.job",
            "web_url": "https://web.page.proxy"
          },
          "//http://commented-host:8080",
          "//end_http_workers"
        ],
        "dcompact_min_level": 2
      }
    }
  }

1.2. 配置参数说明

在 1.1 中,CompactionExecutorFactory 是 C++ 的接口,在 json 中是一个 namespace,在这个 namespace 中,定义了一个 varname 为 dcompact,类名为 DcompactEtcd 的(实现了 CompactionExecutorFactory 接口)的对象,该对象使用 params 进行构造。params 解释说明如下:

属性名 类型 默认值 解释说明
allow_fallback_to_local bool false 如果分布式 Compact 失败,是否允许回退到本地 Compact,如果不允许,则会调用 abort 主动 coredump
copy_sst_files bool false 不可通过 http 在线修改,此时 hoster_root 不能为 db 数据目录的前缀
hoster_root string 该 db 的根目录,一般设置为与 DB::Open 中的 path 变量相同。
instance_name string 该 db 实例名,在多租户场景下,CompactWorker 结点使用 instance_name 区分不同的 db 实例
job_url_root string 查看分布式 Compact Job 详细信息的 http url, 一般可以与 http_workers 中的 web_url 相同
nfs_type string NFS 类型,空表示 nfs, 也可以是 glusterfs, smbfs 等等
nfs_mnt_src string NFS 挂载源
nfs_mnt_opt string NFS 挂载选项
http_max_retry int 3 最大重试次数
retry_sleep_time int 1 单位秒,如果重试原因是服务器繁忙,则睡眠这么长时间再进行重试,避免重试太过频繁
overall_timeout int 5 单位秒,单个分布式 Compact 任务的单次执行尝试(attempt)从头至尾耗时的超时时间
http_timeout int 3 单位秒,http 连接的超时时间,一般情况下,超时即意味着出错
timeout_multiplier int 10 dcompact 执行时间超过预估时间的这么多倍时,会认为超时失败并重试
estimate_speed size 10M 预估的单个 compact 吞吐率,该值会随着时间自动调整,用来计算预估的 compact 执行时间及超时时间
load_balance enum kRoundRobin 可选值有 {kRoundRobin, kWeight},表示多个 http_workers 的选择方式
max_book_dbcf int 20 如果进程运行中对临时 DB 进行 dcompact,max_book_dbcf 表示最多保留多少个最近活动的 DB 记录(WebView 中 stat 字段)
http_workers string

object
多个(至少一个)http url, 以 // 开头的会被跳过,相当于是被注释掉了
末尾的 //end_http_workers 是为了 start_workers.sh 脚本服务的,不能删除
注意: 必须至少定义一个 worker, 否则 DB 启动时会主动 abort
dcompact_min_level int 2 只有在 Compact Output Level 大于等于该值时,才使用分布式 compact,小于该值时使用本地 compact
alert_email string 重试次数到达 http_max_retry 但分布式 Compact 仍然失败时,发送 email 报警
alert_http string 重试次数到达 http_max_retry 但分布式 Compact 仍然失败时,向此 http 发送 POST 报警
alert_interval int 60 如果频繁失败,且每次都报警,报警信息会洪水泛滥,所以每隔这么长时间(单位:),才报警一次
web_domain string 在浏览器中,多个 compact_worker 的状态以 iframe 方式内嵌在页面中,web_domain 用来实现自动调整 iframe 高度(JavaScript 需要跨域权限)
web_show_secret bool false 在浏览器中,是否显示 dcompact_http_headers 等机密内容(不可在线修改)
dcompact_http_headers json 发送 dcompact http 请求时需要填入的 header,用作认证等用途

以上 int, bool, enum, size 类型的参数可以通过 http 在线修改。

1.3. http_workers

在内网环境下,每个 worker 可以简单地配置为一个字符串,表示 worker 的 http url。

在公网(例如云计算)环境下,worker 隐藏在反向代理/负载均衡后面,为此增加了几个配置字段(均无默认值):

字段名 类型 说明
url string 提交 compact job
base_url string probe 查询 compact job 或 shutdown 指定 compact job
web_url string 在浏览器中通过 stat 查看状态,以及查看 log 文件。如果未定义,使用 base_url
weight int http_workers 包含多个服务器时,配置每个服务器的权重,派发 compact 时按权重等比例选择,权重仅在 http_workers 包含多个服务器时有用,表示不同服务器之间的相对值。例如权重 100 比权重 50 多一倍的入选机会,从而承担的计算量也多一倍

最佳实践

应该只定义 url = http://some.host,不定义 base_url,此时:

  • 生效的 base_url = http://some.host
  • 生效的 url = http://some.host/dcompact

在公网环境中,web_url 可定义为不同于生效的 base_url,用于服务浏览器,而生效的 base_url 用于服务 dcompact 命令。

历史原因导致的复杂性

用户可以不用关心该复杂性,仅遵循最佳实践即可

  1. url 与 base_url 必须至少定义其中之一
    • 生效的 url 一定形如 http://some.host/dcompact
    • 生效的 base_url 一定形如 http://some.host
  2. 如果定义 base_url,则必须形如 http://some.host (或 https)
  3. 如果定义 url,则必须形如 http://some.host/dcompacthttp://some.host (或 https)
  4. 如果已定义 base_url,但未定义 url,则生效的 url = "${base_url}/dcompact"
  5. 如果未定义 base_url,但已定义 url
    • 如果 url 形如 http://some.host/dcompact 则 url 保持不变
    • 如果 url 形如 http://some.host 则生效的 url 为 http://some.host/dcompact
    • 生效的 base_url 从生效的 url 推导为 http://some.host

1.4. copy_sst_files 选项

copy_sst_files 为 true 时,compact 中 input sst file 会被拷贝到 ${hoster_root}/dbname/cfname 中,同时将 cf_paths 设为该目录。此时 hoster_root 不能为原 cf_paths 的前缀,实际上,copy_sst_files 选项并非必要,因为如果 hoster_root 是前缀,则无需拷贝文件,如果不是前缀,则必须拷贝文件,compact_worker 才能访问到文件,然后才能执行 compact,但这样的隐性规则过于微妙,所以通过 copy_sst_files 来显式地配置。

这个功能是为了实现公有云跨账号数据交换,因为公有云跨账号的 vpc peering 有配额限制(AWS 是 125,阿里云是 20),其它跨账号通讯也都不合适,所以我们通过对象存储(AWS 的 S3,阿里云的 OSS)来实现数据交换。

对象存储一般都可以通过 fuse mount 到文件系统,所以只需要将数据拷贝到对象存储的文件系统中即可。

1.5. 注意事项

CFOptions 的 level_compaction_dynamic_level_bytes 务必显示指定为 false,为 true 时,很可能会跳过 L1,直接 compact 到 Ln,产生很大的单个 compact ,导致长时间的卡顿。

2. dcompact worker

2.1. dcompact 作为服务

export MAX_PARALLEL_COMPACTIONS=16
export NFS_DYNAMIC_MOUNT=0
export NFS_MOUNT_ROOT=/nvme-shared
export WORKER_DB_ROOT=/tmp
rm -rf $WORKER_DB_ROOT/db-instance-name-1

# Only for ToplingZipTable
export ZIP_SERVER_OPTIONS="listening_ports=8090:num_threads=32"

# ToplingZipTable_XXX can be override here by env, which will
# override the values defined in db Hoster side's json config.
# Hoster side's json config will pass to compact worker through
# rpc, then it may be override by env defined here!
export ToplingZipTable_nltBuildThreads=5
export ToplingZipTable_localTempDir=/dev/shm
export ToplingZipTable_warmupLevel=kValue
export DictZipBlobStore_zipThreads=16
rm -f /tmp/Terark-* # clean garbage files in previous run

ulimit -n 100000
./dcompact_worker.exe -D listening_ports=8080

以该脚本为例,该脚本在当前节点上启动 dcompact_worker,其中几个环境变量说明如下:

环境变量名 解释说明
TERMINATION_CHECK_URL 如果机器是竞价实例(Spot Instance),云厂商会提供 HTTP 接口来检查机器是否将要释放,正常状态下该 HTTP 会返回 404,在机器将要释放时,返回其它值(一般是 200)
WORKER_DB_ROOT worker 为每个 hoster 发过来的每个 compact job 的每个 attempt 都会创建一个目录,
该目录中会保存 db 的 pseudo metadata 及运行日志,compact 成功之后该目录中的数据就没有用处了
DEL_WORKER_TEMP_DB 参考 WORKER_DB_ROOT,当相应的 compact 执行完后,是否删除相应的目录,
因为 compact 执行完之后,相应目录中的数据就没有用处了,可以删除,但是为了事后追踪,仍可保留
NFS_DYNAMIC_MOUNT 0 表示系统中已 mount nfs(如果使用 autofs,设为 0 即可)
1 表示系统中未 mount nfs,由 dcompact_worker 进程动态 mount http 请求中指定的 nfs
NFS_MOUNT_ROOT 此目录下包含多个 Hoster 的 sst 目录,目录名为每个 Hoster 的 instance_name
hoster 发给 worker 的目录都是在 json 中指定的,worker 会将 hoster 发过来的目录前缀中同于
DcompactEtcd json 定义中的 hoster_root 的部分替换为 ${NFS_MOUNT_ROOT}/instance_name
MAX_PARALLEL_COMPACTIONS 该 dcompact_worker 进程可以同时执行多少个 compact 任务,必须大于 0,但不宜设得太大
ADVERTISE_ADDR 该参数会通过 dcompact 请求的 response 返回给 Hoster, 从而在 Hoster 的 dcompact worker web view 中展示在链接 url 中,这是为了适配反向代理,使得我们可以在公网环境下查看内网的 dcompact_worker 的 web view
WEB_DOMAIN 用于 dcompact worker web view iframe 的自适应高度
MULTI_PROCESS 如果使用 ToplingDB 的程序及其 CompactionFilter/EventHandler 等插件使用了全局变量,就无法在同一个进程中执行来自多个 DB 实例的 Compact 任务,此时,将 MULTI_PROCESS 设为 true 可以通过多进程的方式运行 Compact
ZIP_SERVER_OPTIONS ToplingZipTable 环境变量,当 MULTI_PROCESS 为 true 时,设置 ZipServer 的 http 参数,例如:
export ZIP_SERVER_OPTIONS=listening_ports=8090:num_threads=32
FEE_URL 发送计费信息的 url
LABOUR_ID 计费信息中的 labourId,一般是 dcompact_worker 所在的主机名(hostname)
CLOUD_PROVIDER 计费信息中的 provider
ENABLE_HTTP_STOP 是否启用 http stop 接口,禁用该功能可避免通过 http 误操作或被攻击停止 dcompact_worker 服务。默认 false。

注意:对于同一个 hoster 实例,该 hoster 上的 db 数据的路径和 worker 上访问该 hoster 的 db 数据的路径一般是不同的。因为两者的 mount path 很难达成一致,所以,worker 上的环境变量 NFS_MOUNT_ROOT 和 hoster 上的 json 变量 hoster_rootinstance_name 共同协作,完成这个路径的映射关系。

3. Serverless 分布式 Compact

分布式 Compact 可以部署在一个弹性伸缩组(可弹性伸缩的集群)中,挂在一个反向代理后面,该反向代理对外暴露 HTTP 服务,从而该 HTTP 服务本质上就是一个 Serverless 服务。

在公有云上,MyToplingTodis 的分布式 Compact 就是通过这样的 Serverless 服务实现的。

在这种配置中,需要使用 dcompact_worker 的自动 mount 能力,DB 的 instance_name, nfs_mnt_src, nfs_mnt_opt 就是为了实现这个需求,DB 通过 HTTP 请求将包含这些信息的 compact 请求发送给反向代理,反向代理再根据权重等代理策略选择一个后端 dcompact_worker 结点,将请求转发过去,dcompact_worker 根据需要 mount 相应的 NFS,然后执行 compact 任务:从 NFS 上读取输入,将输出写回 NFS。

以这样的方式,如果 DB 的结点或流量有增减,后端 dcompact_worker 的机器负载就会相应增减,进而弹性伸缩组就自动增减结点,将机器负载保持在一个合理范围内,既提供足够的算力,又不浪费资源。

在公有云上,不同账号之间的内网是互相隔离的,要通过内网访问 NFS,就需要将不同账号的内网打通,各个公有云对这个需求都有相应的支持。