https://zhuanlan.zhihu.com/p/382477856

论文: https://dl.acm.org/doi/pdf/10.1145/3448016.3457565

问题

  • 写吞吐 (千万级 QPS)
  • 租户(1000+),业务上
  • 读写(PB+)
  • 低延迟写入+实时的数据可见性

在这个基础上尽可能的降低成本

对比开源方案

HBase、MongoDB:可以大量级的事务写,但是牺牲查询 ElasticSearch: 由于需要实时索引,写入性能达不到要求,只适合单租户

另外上面的结构都是Shared Nothing,failover什么的维护起来不方便

  • Druid: 支持查询丰富,但是只能异步读写
  • Amazon S3(这个不是对象存储么):按照租户分割,不够经济

结构体系

云分布式数据库:

  • Shared Nothing,利用本地存储,写扩展性好,但是存储和计算资源耦合,不经济。例如:ES
  • Shared Storage,解耦计算和存储资源,由下层存储来做数据复制、物化,但是写吞吐有限。例如:PolarDB
  • Shared Data,同样解耦计算和存储资源,但是使用对象存储。优点是存储便宜,缺点是对象存储Append性能差,写延迟高。例如:SnowFlake

问题 :shared data和shared storage有哪些区别?shared data好像是snowflake提出来的名词,但是像Druid这样用HDFS当DeepStorage的算不算Shared data,还是说只有用对象存储的才算?好像纠结这个名词也不重要

LogStore是Shared nothing和Shared data结合,保证写吞吐和存储便宜。读写能力都可以扩展。设计LogBlock的结构,优化读,包括全文索引能力。设计调度算法解决倾斜问题

具体结构

./2021-10-09-15-41-38.jpg

Controller

用Zookeeper保证高可用。元信息管理,管理Shard,路由,database schema,检查其他组件是否存活。

Query层

SLB 负载均衡到 Broker,broker解析SQL,转换成DAG,分发到Shard上(Worker),收集数据后合并

Execution层

Worker负责管理一批Shard,读写请求都会落在Worker上。写请求有两个阶段:

  1. 本地写。写WAL,复制到其他Replica去。LogStore生产环境有三个Replica。
  2. 远程归档,异步转换成LogBlocks,写入到OSS。

云存储层

问题: OSS的读写性能到底如何?按照对外售卖的性能保证,读性能不一定够用。。

OSS 优势:便宜

问题:读延迟高,Append文件效率差(对比HDFS,专门支持了Append,所以是FileSystem)。 解决:两阶段写,第二阶段生成的LogBlock不会再发生修改了。

问题:遍历小文件的效率很低。 解决:把LogBlock所需要的信息都打包在了一起,存一个tar包。

多租户

策略1: 为每一个租户分配单独的物理资源。缺点:大量小租户浪费资源 策略2: 全放一起。缺点:load会互相影响,会有不必要的读取。

LogBlock

压缩+列存索引+自恰

特点是全文索引+可Skip,维护(min, max)信息, 如果查询不在范围内,就Skip

LoadBalance

自动化的减少热点数据,如果一个租户的load太高,就把load平均分配在各个节点上。没仔细看

想法

论文着墨比较多的是Traffic Control的算法解决热点,然而俺没怎么仔细看,暂时还用不上

  1. 读写分别设计数据结构优化。但是没想清楚异步写怎么保证实时可见性,有点矛盾。
  2. 用OSS存储Immutable数据,避免了Shard Nothing架构FailOver数据会来回倒腾。OSS的读性能感觉会是个瓶颈,论文里也写了好几个解决放方法,比如元数据和日志数据打包在一起避免遍历大量小文件,并发读取解决读延迟。
  3. 多租户的TradeOff:写数据结构放在一起,减少空间浪费。读数据结构隔离起来,避免浪费读吞吐。