3

构建可扩展模型的几种方案

 1 year ago
source link: https://juejin.cn/post/7166880726221062152
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

构建可扩展模型的几种方案

2022年11月17日 07:17 ·  阅读 1316

我们来自字节跳动飞书商业应用研发部(Lark Business Applications),目前我们在北京、深圳、上海、武汉、杭州、成都、广州、三亚都设立了办公区域。我们关注的产品领域主要在企业经验管理软件上,包括飞书 OKR、飞书绩效、飞书招聘、飞书人事等 HCM 领域系统,也包括飞书审批、OA、法务、财务、采购、差旅与报销等系统。欢迎各位加入我们。

本文作者:飞书商业应用研发部 许家强

欢迎大家关注飞书技术,每周定期更新飞书技术团队技术干货内容,想看什么内容,欢迎大家评论区留言~

在 SaaS 平台建设过程中存在一个问题:由于 B 类业务的复杂多变,不同企业的业务流程和管理机制存在很大差异,而市面上的标准化 SaaS 产品,较难满足企业的差异化、定制化需求。

因此需要有一套基于高度可扩展的技术框架,用于支撑 B 类业务中灵活变化、可定制化性强的场景。APaaS 就是用于解决平台扩展性的杀手锏,APaaS 平台不仅提供了 SaaS 产品标准化的产品能力,同时,允许使用方通过零代码、轻量的配置化方式,或是以较低成本在 APaaS 平台进行二次开发,丰富和扩展产品的功能。 本文介绍当前业界用于构建可扩展性模型采用的几种方法。

APaaS 平台需要有高度可扩展的模型设计。然而,传统的企业应用的建模方法,通常是基于关系型数据库、面向对象进行建模,该方式预先定义好了模型的结构,如果需要扩展必须通过修改模型( DDL 变更),代价较大;更为致命的是,一个平台上所有租户共享一份数据结构和模型,这套方案显然不适用于 APaaS 平台。

基于元数据驱动的模型

  • 对象:模型的实例。定义了一个特定的信息论域。如一个具体的订单。
  • 模型:一个模型是一个元模型的实例。模型层的主要责任是定义描述信息论域的语言。在建模层上的对象的例子如:订单模型。
  • 元模型:一个元模型是一个元元模型的实例。元模型层的主要责任是定义描述模型的语言。一般来说,元模型比定义它的元元模型更加精细,尤其是当它们定义动态语义时。
  • 元元模型:构成了元建模( metamodeling )体系结构的基础结构。这一层的主要责任是定义描述元模型的语言。一个元元模型定义了这样一个模型,它比元模型具有更高的抽象级别,而且比它定义的元模型更加简洁。一个元元模型能够定义多个元模型,而每个元模型也可以与多个元元模型相关联。通常所说的相关联的元模型和元元模型共享同一个设计原理和构造,也不是绝对的准则。每一层都需要维持自己设计的完整性。在元元模型层上的元元对象的例子有:元类、元属性元操作。 salesforce 的 APaaS 平台,就是基于元模型设计的。其主要的模型如下:
image.png

多租户隔离

  • OrgId:表示租户id,用于多租户隔离。
  • Guid:区分该记录的唯一标识。
  • Object:描述模型的基本信息。如PO、商品、需求单、付款单都是一个Object。
  • Field:描述模型的元结构信息,其中FieldNum维护了该字段在Object的顺序编码。
  • Data:存储模型对象的数据,定义Value0、Value1...、Value500 共500个固定字段,用于存储在Field定义的字段,value的下标,正好与Field中的FieldNum对应。
  • Indexs: 定义了模型的索引字段的信息,用于快速检索。salesforce在写入数据时,将同时写Data和Index表。
  • UniqueIndexs:定义了模型的唯一索引字段信息,利用数据库自身的唯一约束能力保证模型的完整性。salesforce在写入数据时,将同时写Data、UniqueIndexs表。

基于上述元模型驱动的架构,达到了几个目标:

  • 多租户,每个租户的数据完全隔离
  • 模型结构是高度可定制化的,其结构不是在系统部署前预先定义好的,是在程序运行时基于用户配置的元模型,动态加载、拼装而成的,在内存中看到的是组装后的真正对象视图

查询的实现:

  1. 前端在查询数据时,平台需要从Object、Field获取元模型的结构定义,确定了对象类型和对象的结构
  2. 根据对象的索引,到Index、UniqueIndexs表查询数据的主键,即定位Data的Guid
  3. 查询Data获取数据
  4. 根据对象的结构Field,将扁平化的Data,对应value0、value1...value500,组装成对象视图

写入的实现:

  1. 前端在写入数据时,平台需要从Object、Field获取元模型的结构定义,确定了对象类型和对象的结构
  2. 根据对象的结构Field,将对象视图的数据,组装到扁平化的Data中,对应value0、value1...value500
  3. 根据对象的索引设置,按需写入Index、UniqueIndexs表,用于维护索引数据。
  • 实现的成本较高,框架逻辑复杂
  • 分库分表比较难做,会遇到性能瓶颈

基于key-value的纵表设计

所有的数据都基于纵表进行存储。

  • Object:按租户id进行隔离。一个Object表示一种业务实体类型,如PO、商品、采购申请单。
  • Filed:维护每个对象的结构和数据。每个租户的结构是不同的。例如,一个商品有名称、属性、价格、库存,分成多行记录存储在Filed。
  • 数据很容易膨胀,对于B类业务,一个业务实体可能有几十、上百种属性,水平扩展能力差
  • 一次写事务要操作上百条数据,大事务的处理会影响系统的吞吐量
  • 查询时要涉及表关联查询,且会查大量数据,频繁IO导致系统性能不佳。
  • 检索查询支撑能力较差

基于NOSQL的存储设计

为了解决上述方案中数据量大、频繁IO查询导致的性能问题,可以采用NOSQL方案以支持水平扩展。

当前NOSQL产品有如下可选:

产品优点缺点存储示例
MOGODB高性能,支持部分筛选查询功能,海量存储不支持事务操作,数据结构json需要额外转换处理PR模型: 以json的key-value格式,维护PR的字段信息,如 { "id":"3444", "prNumber":"3030333", "applyTime":"2020-01-01 00:00:00", "applyUser":"小王", "description":"买一个15英寸苹果电脑", "money":"20000" }
HBASE高性能,支持海量存储,列动态扩展,支持行级事务查询功能有限,仅支持基于get和scan,rowkey的设计有很多限制PR模型,查询主要需求为根据pr单号或创建用户查询单据。 rowkey为 :tenantId+PR单号+申请用户id+创建时间戳 col为:创建时间、采购类型、状态、金额、需求说明、立项名称等。

动态DDL方案

每个租户的数据模型在物理上是隔离的,当遇到个性化需求时,需要动态创建DDL,该方式较重,实现成本较大。 采用此方案的,有微软的power platform、一些轻量的表单类应用产品。

本文分别介绍了几种提升可扩展性的几种设计方法:大宽表(元数据驱动)、纵表、NOSQL、动态建表,这些方案各有利弊,其复杂度、扩展能力、面向的场景都不一样。

方案优点缺点使用场景
元数据模型模型通用度高,灵活性强实现成本较高、性能一般金蝶、salesforce
纵表灵活性高数据量膨胀,条件检索需求较难支持数据量不大、对检索需求不强的业务场景
NOSQL可以支持较大的数据量,性能较好条件检索需求较难支持大数据量、对性能有较高需求的场景
动态DDL具备一定的扩展性因为安全因素,不一定具备落地条件微软云平台

在实际业务建设过程中,要根据实际情况(团队技术现状、建设&维护成本、业务对扩展性灵活度的要求、性能)进行权衡,综合判断,选择适合的方案。

加入我们

扫码发现职位&投递简历

468b1fff43e54de196cda3c5e9aaafe4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

官网投递:job.toutiao.com/s/FyL7DRg


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK