我们是一个多租户平台。
- 该平台有一个称为
Entity
的结构。 - 用户可以创建实体来模拟任何现实生活中的对象,例如:
Customers, Orders, Payment, Inventory, Cart
,几乎任何东西。 - 每个实体都有其属性集,例如,Customer实体可以具有:
name, email, phone, address (can be another nested entity)
等。 - 要求提供对这些实体的查询/OLAP功能。例如,
find all customers where name = 'john'
。 - 要求包括所有类型的查询,如
DATE RANGE, CONTAINS, LIKE, NUMERIC RANGE, FULL-TEXT Queries
等。我们还需要Sorting, Aggregation, Pagination
功能。
当前设计
- 我们使用ElasticSearch来存储实体数据。
- 为每个租户分配一个单独的索引。
- 在租户中创建实体时,会在关联的索引内创建对应的Map。这些Map大致具有以下形式:
{
"properties": {
"Customer": {
"properties": {
"name": {
"values": {
"type": "text"
}
},
"age": {
"values": {
"type": "integer"
}
}
}
},
"Order": {
"properties": {
"id": {
"values": {
"type": "text"
}
},
"eta": {
"values": {
"type": "integer"
}
}
}
}
//... other entities of this tenant
}
}
此设计存在的主要问题
- 不断增长的Map。
- 频繁更新Map,因此节点忙于传递集群更新信息,导致搜索/索引延迟和偶尔超时。
- 如果需要,不能更改现有的Map。我们必须完成整个重建程序。
目前的设计能够为我们服务几年,直到最近问题开始出现。
什么样的设计才能很好地模拟上述多租户要求?哪种数据库解决方案和模式建模将是合适的?
1条答案
按热度按时间n53p2ov01#
如果您决定继续使用ES,则需要为租户提供多个索引,即每个租户/实体一个索引,而不是每个租户一个索引。这正是您提到的原因,即不断增长的Map和更新现有Map的困难。
您最终肯定会得到更多的索引(N个租户x M个实体),挑战将是根据每个实体需要多少主分片来适当调整这些索引的大小。但我认为现在更难了,因为所有实体都存储在每个租户的单个索引中,所以将租户索引分成几个将变得更容易。
另一种选择是提供一个非常通用的Map,它只包含
int_field_1
、int_field_2
、text_field_1
、text_field_2
等类型化字段,并在通用字段名和租户特定字段名之间保留每个租户的Map:这样,您需要管理的Map更少,在可以容纳的数据类型方面更加灵活,但这是以保持上述字段Map最新为代价的。
在任何情况下,您都需要为租户提供更多索引,以便更容易地管理他们的Map并控制他们的大小。它还将允许您更好地扩展,因为在数据节点上分布几个较小的索引比非常大的索引更容易,特别是考虑到Elastic提出的新的大小调整建议。