数据库-软件架构设计

导读:本篇文章讲解 数据库-软件架构设计,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

范式与反范式

在大学的数据库原理的教材,都会讲到数据库各个等级的范式。在一般的工程项目中,对于数据库的设计都要求达到第三范式。数据库范式的要求如下:
在这里插入图片描述
但在互联网中,为了性能或便于开发,违背范式的设计比比皆是,如字段冗余、字段存在一个复杂的JSON串、分库分表之后数据多维度冗余存储、宽表等。
虽然范式未必一定要遵守,但还是需要仔细权衡,什么时候应该遵守范式,什么时候可以违背范式。如果系统是重业务的系统,对性能、高并发的要求没那么高,最好保证数据库的设计达到第三范式的要求。不能仅仅为了开发的方便,在数据库中存在JSON、存数组类型的字段。

分库分表

分库分表是分布式系统设计中一个非常普遍的问题,什么时候分?怎么分?分完之后又将引发新的问题,例如不能Join、分布式事物等。

为什么要分

分库的目的是做“业务拆分”,通过业务拆分,把一个大的复杂系统拆分多个业务子系统,之间通过RPC或者消息中间件通信。这样做既便于团队成员的职责分工,也便于对未来某个系统进行扩展。
第二个考虑是应对高并发。但要针对读多写少,还是读少写多的场景分别讨论。如果是读多写少,可以通过加从库、加缓存解决,不一定要分库分表。如果读少写多,或者说写入的QPS已经达到了数据库的瓶颈,这时候就要考虑分库分表了。
另外一个考虑角度是“数据隔离”。如果把核心业务数据和非核心业务数据放在一个库里面,不分轻重,同等对待。一旦因为非核心业务导致数据库宕机,核心业务也会受到牵连。分开之后,区别对待,投入的开发和运维人力也不同。
分库分表之后,会面临几个关键问题,下面一一阐述。

分布式ID生成服务

在分库之前,数据库的自增主键可以唯一标识一条记录,在分库分表之后,需要一个全局的ID生成服务。开源的方案有Twitter的Snowflake,各大公司往往也都有自己的分布式ID生成服务。生成的ID是完全无序,还是趋势递增,或者呈更严格的单调递增,方案也不尽相同,此处不再展开讨论。

拆分维度的选择

有了全局的ID,接下来的问题是按哪个维度进行拆分。比如电商的订单表,至少有三个查询维度:订单ID、用户ID、商户ID。当拆分的时候,根据哪个维度进行拆分呢?
假设按用户ID维度拆分,同一个用户ID的所有订单会落到同一个库的同一张表里。当查询的时候,按用户ID查,可以很容易地定位到某个库的某个表;但如果按订单ID或商户ID维度查询,就很难做。
对于在分库分表之后其他维度的查询,一般有以下几个方法:

建立一个映射表

建立辅助维度和主维度之间的映射关系(商户ID和用户ID之间的映射关系)。查询的时候根据商户ID查询映射表,得到用户ID;再根据用户ID查询订单ID。但这里有个问题:映射表本身也需要分库分表,并且分库分表维度和订单表的分库维度还不同。即使映射表不分库分表,写入一条订单的时候也可能需要同时写两个库,属于分布式事物问题。对于这种问题,通常也只能做一个后台任务定时比对,保证订单表和映射表的数据最终一致。

业务双写

同一份数据,两套分库分表。一套按用户ID切分,一套按商户ID切分。同样,存在写入多个库的分布式事物问题。

异步双写

还是两套表,只是业务单写。然后通过监听Binlog,同步到另外一套表上。

两个维度统一到一个维度

把订单ID和用户ID统一成一个维度,比如把用户ID作为订单ID的某几位,这样订单ID中就包含了用户ID信息,然后按照用户ID分库,当按订单ID查询的时候,截取出用户ID,在按用户ID查询;或者订单ID和用户ID中有某几位是相同的(两个ID都是字符串类型),用这几位作为分库维护。

Join查询问题

分库分表之后,Join查询就不能用了。针对这种情况,一般有下面几种解决方法:

  1. 把Join拆成多个单表查询,不让数据库做Join,而是在代码层面对结果进行拼装。
    这种做法非常的常见,因为数据库全是单表查询,大大降低了数据库发生慢查询的概率。
  2. 做宽表,重写轻读场景
    很多时候会有这样的情况:需要把Join的结果分页,这需要利用MySQL本身的分页功能。对于这种不得不用Join的情况,可以另外做一个Join表,提前把结果Join好。这是“重写轻读”,其实也是“空间换时间”的思路。
  3. 利用搜索引擎
    对于第二种方法中提到的场景,还可以利用类似ES的搜索引擎,把数据库中的数据导入搜索引擎中进行查询,从而解决Join问题。

分布式事物

做了分库之后,纯数据库的事务就做不了了。一般的解决办法是优化业务,避免跨库的事务,保证所有事务都落到单库中。
如果实在无法避免,需要分布式事务的解决方案。分布式事务是一个系统性的问题,后面专门讨论。

B+树

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100167.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!