初创期应用架构实践 (3):结构化数据存储

叁叁肆2018-11-14 09:16

欢迎访问网易云社区,了解更多网易技术产品运营经验。


3.1.2 结构化数据存储


数据是互联网业务最核心的价值,管理数据是互联网应用最重要的功能。在电商业务 场景中,一次会员购买商品的行为,首先涉及商品数据、会员数据的查询,会员点击购买 后,生成订单数据,会员支付成功后,又会涉及订单数据的更新。要实现高效的数据管理, 数据存储是关键,因为数据的存储方案决定了数据的访问方式及访问效率。


电商业务涉及非常多的数据,按照数据结构,我们可以分为结构化数据和非结构化数 据。在电商业务场景中,每一个商品都拥有编号、名称、品牌、货源地、分类等固定的属 性,每个属性都有明确的数据类型和长度约束,例如商品名称是字符类型的,有最长字符 限制,商品编号是数字类型的,有固定的取值范围,我们将这类有固定结构的数据称为结 构化数据。与结构化数据相对应的是非结构化数据,例如商品图片、广告视频,这类数据 没有固定的结构。不同的数据类型,数据的存储方案也不相同,我们接下来聊聊结构化数 据的存储解决方案。


1. 关系型数据库 

关系型数据库是目前使用最为广泛的一种结构化数据存储解决方案,在关系型数据 库中,数据被组织成由行和列组成的二维表结构逻辑实现。关系型数据库最早可以追溯 到 1970 年,由英国科学家埃德加·弗兰克·科德提出,经过近半个世纪的发展,这个领域 涌现出非常多优秀的产品。下面根据图 3-2 所示的 DB-Engines 发布的数据库排名,介绍 在互联网业务中应用最为广泛的几个数据库产品。

图 3-2 DB-Engines 发布的数据库排名


Oracle 

Oracle 是由甲骨文公司研发的一款关系型数据库管理系统,堪称史上最成功的商业数 据库,在服务高可用、数据高可靠、查询语法支持、性能、运维工具等方面均有成熟完善 的解决方案,同时提供了丰富的监控诊断信息,方便数据库管理员或者开发者进行性能调 优。但是价格不菲的配套硬件及许可证授权费用,让很多中小型企业望而却步,目前,Oracle 数据库主要应用于大型企业,在金融、银行业务领域应用较为广泛。但是随着以 MySQL 为代表的开源数据库快速兴起,越来越多的互联网公司开始将业务迁移到开源数据库中, 并兴起去“IOE” (O 特指 Oracle)的浪潮。


MySQL 

MySQL 是业界最为流行的开源数据库,由芬兰人 Ulf Michael Widenius(Monty)编写, 依靠强大的社区支持及开源浪潮,迅速席卷了各大互联网公司。它具有部署简单、开源免 费、使用门槛低、日趋完善的功能特性,以及基于复制可以快速实现一套高可用架构等诸 多优势,因此成为中小型企业和创业公司的首选。 


SQL Server 

SQL Serve 是微软公司推出的商业数据库,是.Net 框架下的结构化数据存储的标配解决 方案。基于 Windows 系统部署的业务架构,一般后端数据库会选择 SQL Server,鉴于 Windows 的普及程度,SQL Server 占有不可忽视的市场份额,尤其是在大中型企业中。


PostgreSQL 

PostgreSQL 号称“最先进的开源数据库”,诞生于著名的加州大学伯克利分校的 Ingres 项目。由于其支持语法与 Oracle 最为接近,所以又被称为最像 Oracle 的开源数据 库。在国内,PostgreSQL 由于市场起步比 MySQL 晚,所以普及程度还无法与 MySQL 相提并论。


面对如此多的数据库产品,开发者在设计结构化数据存储方案时首先面临的就是数据 库产品选择的问题。开源数据库的优势在于低成本,但是同时也意味着存在一定的风险及 缺少相应的技术服务支持。商用数据库的优势在于完善的功能和技术服务支持,但也同样 价格不菲。随着开源数据库功能的日趋完善和强大的社区支持,越来越多的人才投入到开 源数据库提供技术服务支持,开源数据库成为开发者的首选数据库。


2. 云环境下的关系型数据库 

目前几乎所有的公有云服务都提供了 MySQL 数据库的云服务,网易云基础服务也不 例外,不仅提供了数据库的快捷部署及高可用架构,还提供了技术和服务支持,让开发者 即使使用开源数据库,也能获得高质量的服务保障。 


需求建模 

选定数据库产品后,进入数据库设计阶段,需求建模是数据库设计的第一步,它包括 需求分析和概念设计两个步骤。需求分析就是要明确系统的数据存储需求,主要包括以下 几个方面。 


存储内容需求:要明确哪些数据是需要存储的,在前面介绍的电商业务案例中, 商品信息、订单信息及会员信息都是我们系统需要存储的数据。


数据限制与约束:要明确存储的数据类型、长度限制及数据的约束,包括是否允 许为空值,是否必须全局唯一等。 


数据操作:要明确系统对这些数据需要完成哪些操作,例如会员购买某个商品, 首先要查看商品的信息,就需要完成一次商品信息的读取操作,操作的输入与输 出也必须明确,例如要读取商品的哪些信息,根据什么条件来筛选商品信息。


明确需求的最佳途径就是产品需求文档,如果有一份完整的产品需求文档,我们就可 以根据产品需求文档中描述的功能需求,来整理我们需要的数据存储需求。但是对于一些 创业团队,可能没有产品策划或者产品经理,或者是由开发者来承担的,那我们就需要通 过还原用户的使用场景,来明确功能需求,然后再理清数据存储的需求。


有了数据存储需求,接下来我们就要完成概念设计,即数据建模。我们经常使用的一 个工具即 E-R 图(Entity Relationship Diagram)。 E-R 图使用实体、属性和联系来描述现实 世界的数据。在上面描述的电商商品、会员和订单的案例中,我们可以将其使用 E-R 图来 描述。 

图 3-3 电商系统 E-R 图


图 3-3 中,会员、商品和订单是 3 个实体,我们使用虚线框来表示,3 个实体分别有 一些属性来描述这些实体的特征,我们使用矩形框来描述。3 个实体之间是有联系的,我 们将实体之间的关系使用实心正方形框来描述,会员和商品之间存在“购买”联系,一个会员可以购买多个商品,一个商品也可以被多个会员购买。会员和订单之间存在“订 货”联系,会员下订单以后,会生成订单数据,一个会员可以产生多笔订单,但是一个 订单,只能属于一个会员。订单和商品之间存在“包含”联系,一个订单包含多个商品, 同时,一个商品也可以被多个订单包含。在菱形框的两侧我们用连接线来连接有联系的 两个实体,并且在连接线上用 1∶1、1∶N、N∶M 来分别表示实体之间 1 对 1、1 对多 和多对多的对应关系。目前,很多画图软件都集成了 E-R 图模板,比如 Visio,开发者 可以根据场景选择使用。


表结构设计 

完成 E-R 图后,我们就可以开始将 E-R 图转换成关系型数据库中的表结构。一般来说, 我们将 E-R 图中的实体单独成为关系型数据库中的一张表,将实体的属性定义为每张表的 列,如果属性中有能够唯一标识的键,就将其定义为表主键,如果存在多个健属性,就选 择其中一个作为主键,其他的设置为唯一键约束。如果不存在唯一键,就单独增加一列, 设置自增属性,将其作为主键。对于 MySQL 数据库,我们强烈建议开发者在设计表时, 必须指定主键,因为没有主键,不仅会影响数据库的插入性能,还会导致 MySQL 复制的 性能问题。另外,我们也建议开发者尽量使用与业务无关的自增列作为主键,这样可以提 高插入和按插入顺序检索的效率。对于实体之间的联系,我们可以在表结构设计时做如下 转换。 


1:1:在一个实体对应的表中增加另外一个实体的主键作为一列,在电商业务场 景中,尤其使用 MySQL 数据库时,我们不建议开发者在两个表之间设置外键约 束,因为这样在扩展数据库时会受到限制。 

1:N:在多个实体对应的表中增加一列,将一个实体对应表的主键作为该列的值。 这样,我们可以通过该列进行关联查询。

 N:M:单独一张表来维护两个实体之间的关系,将两个实体对应的表的主键分 别作为该表的两个属性,通过这两个属性之间的连接,完成 3 张表之间的关联 查询。


经过转换,电商案例中的 3 张表,设计如图 3-4 所示。

图 3-4 电商系统表结构设计


在设计 product、member 和 order 3 张表时,我们都在 E-R 图所标识的属性外增加了一 列与业务无关的自增列作为主键。由于 member 表与 order 表是 1:N 的关系,即一个会员 可以拥有多个订单,但是一个订单只属于一个会员,根据之前约定的规则,我们在 order 表中增加了一列 memberId,用来标识该订单属于哪个用户,将 order 和 member 表关联。 product 表与 order 表是 N:M 的关系,所以我们额外增加了一张表,order_product,将 order 表的 orderId 和 product 表的 productId 作为其两个属性列,这样通过 order_product 表就将 order 表和 product 表进行了关联。product 和 member 之间也是 N:M 的关系,由于 order 表中已经拥有 memberId,并且 order 表已经和 product 表建立了映射,所以我们通过 order_product 和 order 表的 memberId,就可以建立 member 表和 product 表的映射关系。


定义了表整体结构后,接下来我们就要针对每一个列明确具体的数据类型、长度限制、 约束及索引相关内容。MySQL 数据库提供了丰富的数据类型,常用的包括 int、long、float、 double、varchar、datetime 等,根据字段表达的内容确定某一列的数据类型并不困难,但是 值得注意的是每一种类型的长度限制,例如 int 类型的取值范围是 0~65535,如果超出该 值,数据库就无法正确存储该值,如果字段可能大于 65535,就应该使用 long 类型。但并不是字段长度越长就越好,字段越长,就代表字段占用的空间越大,对于数据库来说,会 耗费很多存储空间,降低数据库的存储效率。varchar 类型用户可以指定字段长度为 0~ 65535,开发者根据业务的实际需要,限制字段长度的大小。


针对不同的数据类型,往往有一些特殊的属性,例如对于 varchar 类型,会有 default、 binary、字符集及校验规则的属性,default 就是该列的默认值,binary 实际与该列的字符校 验规则有关,字符校验规则会影响字符的比较和排序,如果对 varchar 设置了 binary 属性, 字符集是 utf8,校验规则就会是 utf8_bin,而不是 utf8_general_ci,因为 utf_bin 是区分大小 写的,utf_general_ci 是不区分大小写的。MySQL 允许对某一列设置字符集,在开发应用 时,为了确保中文输入正确,建议开发者把字符集都设置为 utf8,随着很多存储的数据会 包含一些表情符号,比如开发基于 iOS 的应用,所以开发者最好将字符集设置为支持表情 符号的 utf8mb4。除了不同类型的特殊属性,还有一些每个字段都可以设置的约束限制,有 是否允许为空、唯一限制。如果字段不允许为空,在插入时没有指定该列的值,数据库就 会抛错误。如果限制了唯一约束,开发者插入了在该字段相同的两行记录,后插入的也会 抛错。


最后,我们需要完成索引的设计,这也是表结构设计中难度最大,又最为关键的一部 分内容,它对后续数据库访问性能有非常大的影响。我们需要了解 3 个问题。


 为什么要创建索引? 

 创建索引会对数据库产生什么影响? 

 如何选择索引字段? 


第一个问题,在 MySQL 数据库中,存在两类索引,分别是主键索引和二级索引。在 默认的 InnoDB 存储引擎中,数据记录是按照主键字段构建的 B+树的组织存储的,如果 开发者在创建表时,没有指定主键,InnoDB 也会默认为该表自动生成一个主键,但是我 们非常不建议开发者这么使用,因为这会造成一系列性能问题。所以主键是数据存储结 构构建的依据,每张表都要有。第二种就是二级索引,它的存在主要是基于性能的考虑, 如果在某个字段或者某几个字段创建一个二级索引,则基于这些字段的查询会相对更快, 代价更低。


第二个问题,既然二级索引能够加速数据库的访问,是不是创建得越多越好呢,这与 索引在数据库的内部实现相关。实际上数据库创建索引是有开销的,创建一个二级索引,数据库系统就会新构建一棵 B+树,与主键索引不同的是,二级索引的叶子节点不是数据库 记录,而是主键的值。一旦该表涉及索引字段的更新,记录的插入或者删除,就会导致二级 索引 B+树的节点合并和分裂,造成数据库很大的开销。所以索引确实可以加速数据库访问, 但是也会造成一定的系统开销,必须要合理创建索引,才能发挥最大的功效。


最后一个问题就是如何合理选择索引字段,以达到高效的访问。索引字段的选择与应 用访问数据库的 SQL 息息相关。最常用的规则如下。


查询、更新、删除语句涉及的条件字段对应的属性列应该创建索引。 

如果存在多张表的关联查询,连接字段应该创建索引。 

频繁更新的字段不宜创建索引。 

如果存在多个索引交叉,可以创建多个字段的联合索引,但是需要注意的是,索 引的字段顺序必须要与查询条件中的字段顺序一致。 


开发者遵循上述基本的原则,可以创建出较为高效的索引。


设计工具 

目前业界已经有很多优秀的表结构设计工具,帮助开发者完成表结构的设计,并可以 直接转化成对应的 SQL 语句在指定的数据库上实施,降低了开发者编写 SQL 语句和执行 的烦琐过程。


MySQL workbench是一款专门针对MySQL打造的数据库设计和建模工具,集成了SQL 开发、数据库管理、数据库设计、创建及维护于一体的客户端工具。其操作界面如图 3-5 所示。


Navicat 也是国内开发者使用较多的一款图形化数据库管理客户端软件,它不仅提供了 面向 MySQL,还包括 Oracle、SQL Server 等多种数据库,它是一款收费的软件。其操作界 面如图 3-6 所示。


phpMyAdmin 是一款免费开源的基于 Web 浏览器的可视化 MySQL 和 MariaDB 管理系 统,它使用 PHP 语言开发。相比于客户端工具,phpMyAdmin 具有免安装的优势,可以随 时随地完成对数据库的设计和管理。其操作界面如图 3-7 所示。 

图 3-5 MySQL workbench 操作界面 

图 3-6 Navicat 操作界面

 
图 3-7 phpMyAdmin 操作界面


公有云数据库服务也面向开发者提供了数据库设计和管理的可视化工具,例如在网易 云上的 WebSQL 功能,在网易云数据库的控制台上就可以轻松完成数据库的设计工作。其 操作界面如图 3-8 所示。


文章节选自《云原生应用架构实践》 网易云基础服务架构团队 著


网易云计算基础服务深度整合了 IaaSPaaS 及容器技术,提供弹性计算、DevOps 工具链及微服务基础设施等服务,帮助企业解决 IT、架构及运维等问题,使企业更聚焦于业务,是新一代的云计算平台。点击可免费试用