如何为多租户平台的自定义Entity场景设计合适的数据架构?
多租户动态Entity平台架构优化方案
针对当前Elasticsearch单租户单索引设计带来的映射膨胀、集群同步压力大、映射修改成本高的问题,以下是几种适配的架构方案,涵盖数据库选型和Schema建模:
一、优化现有Elasticsearch架构(最小侵入改造)
1. 租户内按Entity拆分独立索引
放弃单个租户一个大索引的设计,改为每个租户的每个Entity对应一个独立索引,比如tenant_123_customer、tenant_123_order。
每个索引的映射仅包含对应Entity的属性,示例如下:
{ "properties": { "name": { "type": "text" }, "age": { "type": "integer" }, "address": { "type": "nested", "properties": { "street": { "type": "text" }, "city": { "type": "keyword" } } } } }
- 核心优势:映射仅对应单个Entity,不会无限膨胀;更新某Entity的映射只会影响该索引,集群同步压力大幅降低;修改字段类型时仅需重索引该Entity的索引,无需全租户数据重索引。
2. 动态模板+严格字段管控
若坚持单租户单索引,可通过动态模板统一字段类型规则,同时开启dynamic: strict避免无规则字段新增:
{ "mappings": { "dynamic": "strict", "dynamic_templates": [ { "full_text_fields": { "match": "*_text", "match_mapping_type": "string", "mapping": { "type": "text", "analyzer": "standard" } } }, { "keyword_fields": { "match": "*", "match_mapping_type": "string", "mapping": { "type": "keyword" } } } ] } }
- 核心优势:规范字段类型,避免映射无限制膨胀;仅允许符合规则的字段写入,减少不必要的映射更新操作。
二、换用多租户友好的数据库方案
1. MongoDB(灵活Schema+通用查询场景)
MongoDB原生支持动态Schema,且具备丰富的查询能力(范围、模糊、全文检索、聚合等),多租户隔离方案成熟:
- 隔离方式:
- 集合级隔离:每个租户的每个Entity对应一个集合(如
tenant_123_customers),逻辑清晰,查询性能稳定; - 文档级隔离:单个集合存储所有租户的所有Entity,通过
tenant_id和entity_type字段区分,示例文档:
- 集合级隔离:每个租户的每个Entity对应一个集合(如
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "tenant_id": "123", "entity_type": "Customer", "data": { "name": "john", "age": 30, "address": { "street": "Main St", "city": "NY" } } }
- 查询示例(查找租户123中name为john的Customer并分页):
db.entities.find({ tenant_id: "123", entity_type: "Customer", "data.name": "john" }).sort({"data.age": 1}).skip(0).limit(20)
- 核心优势:Schema修改无需提前定义,实时生效;通过
tenant_id+entity_type的复合索引保证查询性能,避免映射膨胀问题。
2. ClickHouse(OLAP优先场景)
若平台以统计分析、聚合查询为主,ClickHouse是更优选择——专为OLAP设计,支持高并发复杂聚合,多租户隔离清晰:
- 建模方式:
- 租户级分库:每个租户对应一个数据库,库内按Entity分表(如
tenant_123.customer); - 共享表+JSON字段:创建通用表,用
tenant_id、entity_type区分租户和Entity类型,data字段用JSON存储属性:
- 租户级分库:每个租户对应一个数据库,库内按Entity分表(如
CREATE TABLE entities ( tenant_id String, entity_type String, data JSON, created_at DateTime ) ENGINE = MergeTree() PARTITION BY toYYYYMM(created_at) ORDER BY (tenant_id, entity_type, created_at);
- 查询示例(统计租户123中Customer的年龄分布):
SELECT data.age, count(*) FROM entities WHERE tenant_id = '123' AND entity_type = 'Customer' GROUP BY data.age ORDER BY count(*) DESC;
- 核心优势:OLAP性能远超Elasticsearch;JSON字段支持动态属性,无需修改表结构;集群压力小,无映射更新同步问题。
三、混合架构(兼顾检索与存储灵活性)
若需保留Elasticsearch的全文检索能力,可采用存储层+检索层分离的架构:
- 存储层用PostgreSQL(JSONB字段存储Entity属性),支持灵活Schema修改,且ACID特性保证数据一致性;
- 检索层用Elasticsearch,按租户+Entity拆分索引,通过CDC工具实时同步数据;
- 利用Elasticsearch的索引生命周期管理(ILM)自动归档旧数据,降低集群压力。
内容的提问来源于stack exchange,提问作者hitesh kaushik
相关产品推荐
相关产品推荐

