我目前正在开发一个多租户系统,该系统的核心功能是允许用户定义自定义类型。例如,他们会定义一个事件、帐户、订单、发货,无论他们选择什么。系统中的每个用户对于他们想要管理的字段都有不同的定义。因此,对于一个用户,订单可能有订单号、状态和到期日期,而对于另一个用户,订单可能有10个字段。
与我合作的开发人员希望使用EAV来存储这些数据。我反对这个想法。我在这个网站上以及整个互联网上读了很多文章,列出了这种反设计模式的缺点,但是没有提到我正在考虑采取的方法。我正在尝试构建这个应用程序,以便它从一开始就具有可伸缩性。
当我计算时,如果我有1000个租户,平均每个租户有5个类型(5000个类型)。每种类型都有1000条记录,例如(5000000条记录)。每条记录平均有5个字段,在EAV模型的最低级别上总共有25000000行。
下游流程还将把每个用户的数据绑定到jquery网格,所以首先获取这些数据并转置这些数据对我来说是非常昂贵的。如果你有1万或5万租户。。。我知道MySQL在经过优化后可以处理这类事情,但这看起来像是在自讨苦吃。
我想换一种方式。然而,我对自己的提议有一种不好的直觉,因为它违背了我所知道的一切,所以我希望一些真正有实践知识的专家来验证或批评我的方法。如果你确认了,请告诉我我需要做什么来支持它并让它工作。如果你批评,请告诉我短期和长期我会遇到的陷阱。
我的建议。
使用域划分来划分系统,使得在任何特定碎片中存在一组最大租户。主目录将引用哪个租户属于哪个碎片
对于每个Shard,当用户定义一个类型时,创建一个新表来保存该类型。在shard中保存一个映射表,它将用户链接到他定义的类型(自定义表)。
这基本上意味着我将在一个shard和1000个自定义表中有几个核心表。
现在对我来说,通常数据库中有那么多表通常会告诉我模式有问题或者设计有误,但是对于这个场景,我只是好奇它是否是一种可行的方法。在我前面的例子中,这意味着我在shard中有5000个表,每个表只有1000行。在我看来,这是一种比使用EAV更好的方法。根据用户,找到类型并将数据绑定到网格。
注意事项
多租户体系结构允许用户拥有自己的用户。所以我可能有1000个订户,但有5000个用户。所以需要管理数据库连接。我会遇到管理连接的问题吗?
我会遇到与表缓存相关的问题吗?我洗桌子有问题吗?
我在哪里可以找到这个设计的性能问题?我知道catalouge主数据库可能是一个瓶颈,但是这个数据库的负载不会太重。
开发已经开始,不要让我改成NoSQL数据库!
另一个建议是继续使用EAV,但在shard中使用。你觉得这个主意怎么样?
请不要打!我需要听到全部。
提前谢谢。
最佳答案
我认为在扩展数据方面,您会发现管理数千个相对较小的自定义表比使用EAV更好。我为在一个MySQL实例上拥有超过100000个表的客户提供了咨询。
当一个实例上有上万个表时,您将遇到不同的可伸缩性问题,但是如果您已经有了支持分片的体系结构,那么就可以进一步细分用户,这样就不会在任何一个实例上有太多的表。
目录表非常适合放入缓存(例如memcached),因为用户到shard实例的映射很少更改。这将减少目录的负载。
我还将研究MySQL对目录的分区,以及将用户映射到其自定义表的表。以及任何其他常用(非自定义)表。您可以根据userid对其中任何一个表进行分区,并依赖分区修剪来使多租户表像更小的表一样工作。