第二章day02:数据库设计与前端框架

1. 多租户Saas平台

1.1 多租户定义:

多租户技术(Multi-TenancyTechnology)

又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务。

  • 从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离。
  • 那么重点就很浅显易懂了,多租户的重点就是同一套程序下实现多用户数据的隔离

1.2 需求分析:

传统软件模式
指将软件产品进行买卖,是一种单纯的买卖关系,客户通过买断的方式获取软件的使用权,软件的源码属于客户所有,因此传统软件是部署到企业内部,不同的企业各自部署一套自己的软件系统。

Saas模式
指服务提供商提供的一种软件服务,应用统一部署到服务提供商的服务器上,客户可以根据自己的实际需求按需付费。用户购买基于WEB的软件,而不是将软件安装在自己的电脑上,用户也无需对软件进行定期的维护与管理

多租户saas架构 数据库设计方案 saas多租户平台开发实战_数据库

1.3 数据库方案

目前基于多租户的数据库设计方案通常有如下三种:

  • 独立数据库
  • 共享数据库、独立 Schema
  • 共享数据库、共享数据表

1.独立数据库

每个租户一个数据库。

  • 优点:为不同的租户提供独立的数据库,有助于简化数据模型的扩展设计,满足不同租户的独特需求;如果出现故障,恢复数据比较简单。
  • 缺点: 增多了数据库的安装数量,随之带来维护成本和购置成本的增加

多租户saas架构 数据库设计方案 saas多租户平台开发实战_java_02

2.共享数据库、独立 Schema

即多个或所有的租户使用同一个数据库服务(如常见的ORACLE或MYSQL数据库),
但是每个租户一个Schema。

  • 优点: 为安全性要求较高的租户提供了一定程度的逻辑数据隔离,并不是完全隔离;每个数据库可支持更多的租户数量。
  • 缺点: 如果出现故障,数据恢复比较困难,因为恢复数据库将牵涉到其他租户的数据; 如果需要跨租户统计数据,存在一定困难。

多租户saas架构 数据库设计方案 saas多租户平台开发实战_vue_03

3.共享数据库,共享数据表

即租户共享同一个Database,同一套数据库表(所有租户的数据都存放在一个数据库
的同一套表中)。在表中增加租户ID等租户标志字段,表明该记录是属于哪个租户的。

  • 优点:所有租户使用同一套数据库,所以成本低廉。
  • 缺点:隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量,数据备份和恢复最困难。

多租户saas架构 数据库设计方案 saas多租户平台开发实战_java_04

三种方式对比:

多租户saas架构 数据库设计方案 saas多租户平台开发实战_数据库_05

2. 数据库设计三范式

2.1 三范式介绍

数据库设计三大范式

数据库逻辑设计之三大范式通俗理解

  • 三范式:
  1. 第一范式(1NF):确保每一列的原子性(做到每列不可拆分)
  2. 第二范式(2NF):在第一范式的基础上,非主字段必须依赖于主字段(一个表只做一件事)
  3. 第三范式(3NF):在第二范式的基础上,消除传递依赖
  • 反三范式:
    反三范式是基于第三范式所调整的,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。

举例说明

  1. 第一范式:

此时的用户表是不满足第一范式的,因为对于address字段是可以继续拆分的:国家+城市

多租户saas架构 数据库设计方案 saas多租户平台开发实战_多租户saas架构 数据库设计方案_06

  1. 第二范式:
    第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。
    也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

用户表就应该只存储用户表的信息,后续两种信息应该存在成绩表/图书表中。

  1. 第三范式:
    对于学生表:

因为存在依赖传递: (学号) → (学生)→(所在学院) → (学院电话) 。

可能会存在问题:

  • 数据冗余:有重复值;
  • 更新异常:有重复的冗余信息,修改时需要同时修改多条记录,否则会出现数据不一致的情况

正确做法:

多租户saas架构 数据库设计方案 saas多租户平台开发实战_python_07

  1. 反三范式的出现
    降低范式就是增加字段,允许冗余,达到以空间换时间的目的
    【例】:如订单表,“金额”这个字段的存在,表明该表的设计不满足第三范式,因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。
    Rose 2002中,规定列有两种类型:数据列计算列
    “金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。

2.2 三范式总结:

  • 范式化
  • 优点:
  1. 可以尽量的减少数据冗余,数据表更新快体积小
  2. 范式化的更新操作比反范式化更快
  3. 范式化的表通常比反范式化更小
  • 缺点:
  1. 对于查询需要对多个表进行关联 导致性能降低
  2. 更难进行索引优化
  • 反范式化
  • 优点:
  1. 可以減少表的关联
  2. 可以更好的进行索引优化
  • 缺点:
  1. 存在数据冗余及数据维护异常
  2. 对数据的修改需要更多的成本

3.前端框架:

了解前端技术栈(看得懂,会改就行):

  • 技术栈
    vue 2.5++,elementUI 2.2.2,vuex,axios,vue-router,vue-i18n,
  • 前端环境
    node 8.++,npm 5.++

3.1安装与启动:

  1. 在vsCode中使用终端(命令安装文件):

通过淘宝镜像下载安装所有的依赖,几分钟后下载完成
如果没有安装淘宝镜像,请使用npm instal

cnpm install

多租户saas架构 数据库设计方案 saas多租户平台开发实战_java_08

1.1 关闭语法检查

打开 config/index.js 将useEslint的值改为false。
此配置作用: 是否开启语法检查,语法检查是通过ESLint 来实现的。

科普一下,什么是ESLint : ESLint是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。

如果我们开启了Eslint , 也就意味着要接受它非常苛刻的语法检查,包括空格不能少些或多些,必须单引不能双引,语句后不可以写分号等等,这些规则其实是可以设置的。我们作为前端的初学者,最好先关闭这种校验,否则会浪费很多精力在语法的规范性上。如果以后做真正的企业级开发,建议开启

  1. 加载完成之后使用命令(编译并启动前端脚手架):
npm run dev

安装成功后可以点击链接进行访问:

多租户saas架构 数据库设计方案 saas多租户平台开发实战_java_09

3.2脚手架大纲:

├── assets             | 资源
├── build              | webpack编译配置
├── config             | 全局变量
├── src               | 源码
├── dist              | 编译发布目录
├── index.html           | 页面模板
├── package.json          | npn包配置
├── static
└── test              | 测试
 ├── e2e
 └── unit

多租户saas架构 数据库设计方案 saas多租户平台开发实战_多租户saas架构 数据库设计方案_10

3.3前端执行步骤:

3.3.1 路由和菜单:

多租户saas架构 数据库设计方案 saas多租户平台开发实战_多租户saas架构 数据库设计方案_11

路由和菜单是组织起一个后台应用的关键骨架。本项目侧边栏和路由是绑定在一起的,所以你只有在
@/router/index.js 下面配置对应的路由,侧边栏就能动态的生成了。大大减轻了手动编辑侧边栏的工作量。当然这样就需要在配置路由的时候遵循很多的约定:

  • 这里的路由分为两种, constantRouterMap 和 asyncRouterMap 。
  • constantRouterMap 代通用页面。
  • asyncRouterMap 代表那些业务中通过 addRouters 动态添加的页面。

多租户saas架构 数据库设计方案 saas多租户平台开发实战_多租户saas架构 数据库设计方案_12

3.3.2 前端数据交互

一个完整的前端 UI 交互到服务端处理流程是这样的:

  1. UI 组件交互操作;
  2. 调用统一管理的 api service 请求函数;
  3. 使用封装的 request.js 发送请求;
  4. 获取服务端返回;
  5. 更新 data

从上面的流程可以看出,为了方便管理维护,统一的请求处理都放在 src/api 文件夹中,并且一般按照 model
纬度进行拆分文件:

api/
    frame.js
    menus.js
    users.js
    permissions.js
    ..

其中, src/utils/request.js 是基于 axios 的封装,便于统一处理 POST,GET 等请求参数,请求头,以及错
误提示信息等。具体可以参看 request.js。 它封装了全局 request拦截器 、 respone拦截器 、 统一的错误处
理 、 统一做了超时,baseURL设置等

多租户saas架构 数据库设计方案 saas多租户平台开发实战_python_13

3.4 Mock.js

官方文档:http://mockjs.com/0.1/

Mock.js 是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试。提供了以下模拟功能:

  • 根据数据模板生成模拟数据
  • 模拟 Ajax 请求,生成并返回模拟数据
  • 基于 HTML 模板生成模拟数据

实战例子:在vue中结合mock.js调试框架

多租户saas架构 数据库设计方案 saas多租户平台开发实战_数据库_14

//index.js
import Mock from 'mockjs'
import TableAPI from './table'
import ProfileAPI from './profile'
import LoginAPI from './login'

//如果发送请求的api路径匹配,拦截
//第一个参数匹配的请求api路径,第二个参数匹配请求的方式,第三个参数相应数据如何替换
Mock.mock(/\/table\/list\.*/, 'get', TableAPI.list)
//获取用户信息
Mock.mock(/\/frame\/profile/, 'post', ProfileAPI.profile)
Mock.mock(/\/frame\/login/, 'post', LoginAPI.login)
//以ProfileAPI.profile 为例:
//拦截到对应api后调用相应数据显示
//profile.js
export default {
    profile:{
        "code" : "10000",
        "success" : true,
        "message" : "登录成功",
        "data" : {
            mobile:"138000138000",
            username:"张三ok",
            company:"传智播客教育科技股份有限公司12345678",
            email:"bipeng@itcast.cn",
        }
    }
}

扩展:

  1. mock.js的使用方法

Mock.Random 提供的完整方法(占位符)如下:

TypeMethodBasicboolean, natural, integer, float, character, string, range, date, time, datetime, nowImageimage, dataImageColorcolorTextparagraph, sentence, word, title, cparagraph, csentence, cword, ctitleNamefirst, last, name, cfirst, clast, cnameWeburl, domain, email, ip, tldAddressarea, regionHelpercapitalize, upper, lower, pick, shuffleMiscellaneousguid, id

  1. 正确开启Mockjs的三种姿势:入门参考(一)
  • Mock.mock(url, type, data)

参数名

参数需求

参数描述

例子

url

可选: URL 字符串或 URL 正则

拦截请求的地址

/mock

type

可选

拦截Ajax类型

GET、POST