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的结构,优化读,包括全文索引能力。设计调度算法解决倾斜问题
具体结构

Controller
用Zookeeper保证高可用。元信息管理,管理Shard,路由,database schema,检查其他组件是否存活。
Query层
SLB 负载均衡到 Broker,broker解析SQL,转换成DAG,分发到Shard上(Worker),收集数据后合并
Execution层
Worker负责管理一批Shard,读写请求都会落在Worker上。写请求有两个阶段:
- 本地写。写WAL,复制到其他Replica去。LogStore生产环境有三个Replica。
- 远程归档,异步转换成LogBlocks,写入到OSS。
云存储层
问题: OSS的读写性能到底如何?按照对外售卖的性能保证,读性能不一定够用。。
OSS 优势:便宜
问题:读延迟高,Append文件效率差(对比HDFS,专门支持了Append,所以是FileSystem)。 解决:两阶段写,第二阶段生成的LogBlock不会再发生修改了。
问题:遍历小文件的效率很低。 解决:把LogBlock所需要的信息都打包在了一起,存一个tar包。
多租户
策略1: 为每一个租户分配单独的物理资源。缺点:大量小租户浪费资源 策略2: 全放一起。缺点:load会互相影响,会有不必要的读取。
LogBlock
压缩+列存索引+自恰
特点是全文索引+可Skip,维护(min, max)信息, 如果查询不在范围内,就Skip
LoadBalance
自动化的减少热点数据,如果一个租户的load太高,就把load平均分配在各个节点上。没仔细看
想法
论文着墨比较多的是Traffic Control的算法解决热点,然而俺没怎么仔细看,暂时还用不上
- 读写分别设计数据结构优化。但是没想清楚异步写怎么保证实时可见性,有点矛盾。
- 用OSS存储Immutable数据,避免了Shard Nothing架构FailOver数据会来回倒腾。OSS的读性能感觉会是个瓶颈,论文里也写了好几个解决放方法,比如元数据和日志数据打包在一起避免遍历大量小文件,并发读取解决读延迟。
- 多租户的TradeOff:写数据结构放在一起,减少空间浪费。读数据结构隔离起来,避免浪费读吞吐。