## 多租户考虑

Apache Druid经常被用于支持面向用户的数据应用程序，其中多租户是一个重要的需求。本文概述了Druid的多租户存储和查询功能。

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-8828078415045620"
     data-ad-slot="7586680510"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>

### 共享数据源还是每个租户一个数据源

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。
