## 多租户考虑
Apache Druid经常被用于支持面向用户的数据应用程序,其中多租户是一个重要的需求。本文概述了Druid的多租户存储和查询功能。
### 共享数据源还是每个租户一个数据源
Druid中的数据源等价于关系型数据库中的表。 对于多租户场景,可以为每一个租户创建独立的数据源,也可以多个租户之间通过使用一个租户ID的维度来共享一个或者多个数据源。在决定走哪条路时,要考虑每一条路都有利弊。
为租户独立数据源的优势:
* 每个数据源可以有自己的schema、自己的backfills、自己的分区规则以及自己的数据加载和过期规则。
* 查询可以更快,因为对于典型的租户查询,需要检查的段更少。
* 你得到了最大的灵活性。
多租户共享数据源的优势:
* 每个数据源都需要自己的JVM来进行实时索引。
* 对于Hadoop批处理作业,每个数据源都需要自己的YARN资源。
* 每个数据源在磁盘上都需要自己的段文件。
* 由于这些原因,拥有大量的小数据源可能是浪费。
一个折衷方案是使用多个数据源,但数量要比租户少。例如,您可以让一些租户使用分区规则A,而另一些租户使用分区规则B;您可以使用两个数据源并在它们之间拆分租户。
### 对共享数据源进行分区
如果您的多租户集群使用共享数据源,那么您的大多数查询可能会在"tenant_id"维度上过滤。当数据被租户很好地分区时,这类查询的性能最好。有几种方法可以做到这一点。
使用批处理索引,您可以使用 [单维分区](../DataIngestion/hadoopbased.md#单一维度范围分区) 按租户ID对数据进行分区。Druid总是先按时间进行分区,但每个时间段内的辅助分区将位于租户ID上。
通过实时索引,你可以通过调整发送给Druid的数据流来实现这一点。例如,如果您使用的是Kafka,那么您可以让Kafka生产者按照租户ID的哈希对您的Topic进行分区。
### 定制数据的分布
Druid还通过提供可配置的数据分发方式来支持多租户。Druid的Historical进程可以配置成多个[层次(tier)](../Operations/role-configuration.md),并且可以设置 [规则(rule)](../Operations/role-configuration.md) 来决定哪些部分进入哪些层。其中一个场景是最近的数据比旧的数据更容易被访问,分层使较新的数据段能够托管在功能更强大的硬件上,以获得更好的性能。最近的段的第二个副本可以复制到更便宜的硬件上(另一层),旧的段也可以存储在这个层上。
### 支持高查询并发
Druid的基本计算单位是[段](../Design/Segments.md)。进程并行地扫描段,给定进程可以根据`druid.processing.numThreads`的配置并发扫描。为了并行处理更多的数据并提高性能,可以向集群中添加更多的核。Druid段的大小应该使任何给定段上的计算都能在最多500毫秒内完成。
Druid在内部将扫描段的请求存储在优先队列中。如果一个给定的查询需要扫描比集群中可用处理器总数更多的段,并且许多类似昂贵的查询同时运行,我们不希望任何查询都被耗尽。Druid的内部处理逻辑将扫描一个查询中的一组段,扫描完成后立即释放资源,允许继续扫描来自另一个查询的第二组段。通过保持段计算时间非常小,我们确保不断地产生资源,并且与不同查询相关的段都被处理。
Druid查询可以选择在[查询上下文](query-context.md)中设置`priority`标志。已知速度较慢的查询(下载或报告样式的查询)可以取消优先级,交互程度更高的查询可以具有更高的优先级。
Broker进程也可以专用于给定的层。例如,一组Broker进程可以专用于快速交互查询,另一组Broker进程可以专用于较慢的报告查询。Druid还提供了一个[Router](../Design/Router.md)进程,可以根据各种查询参数(datasource、interval等)将查询路由到不同的Broker。