• 利用多租户模式演化成分库分表和读写分离


    前言

    最近两周我都发了随笔写关于利用EF core实现多租户,并且给出了一些关于EF 自动迁移的内容。

    这个系列的随笔是想要把这部分的代码优化和做成类库的。

    我已经整理和抽象好了,本来想介绍一下整理的思路的。但后来发现这里的代码量太少了,好像没什么可以说的。

    所以这篇随笔会讲解利用这个类库可以实现的功能。

    多租户介绍

    按照系列的随笔介绍,现在主要支持3种模式。分别是: 按表、按Schema和按数据库分离数据。

    支持的数据库有MySql和SqlServer,并且在我重构的时候,把Postgre也集成进去了。

    通过这次的代码重构,代码的结构已经不像前面的文章一样,停留在Demo层面。

    代码修改后,我的目标是同时支持最基本的多租户,多租户演变成读写分离。

    典型的模式

    1. 按数据库分离的模式,可以看到一个DbContext会同时连接3个不同的数据库,每个库里面都有一个Product表.

     2. 按表分离的模式,这里可以看到一个DbContext只会同时连接一个数据库,数据库里面有3个结构相同的Product表,但是它们的名称是根据前缀区分的。

     3. 按Schema分离的模式,这里是一个DbContext只会同时连接一个数据库,数据库里面有3个Schema,3个Schema同时具有Product表

    在多租户的场景下的变型

    通过通过数据库的结构,我们能知道,数据库、Schema和表是有层级关系的。一个数据库有n个Schema,一个Schema有n个表。

    通过这个层级特性,我们是可以把他变型成4种模式:数据库和表混合模式、数据库和Schema混合模式、Schema和表混合模式、数据库和Schema和表混合模式

    但一般来说,后面2中模式把更加多的压力都同时在一个数据库,并没有从硬件/数据库实例方面进行分离,数据量继续增长的情况下,最终还是需要通过多个数据库分离数据。

    1. 数据库和表混合模式,可以看到DbContext里面有3个连接分别连接到3个Store Container的数据库,里面各自存在3个结构相同的数据表。

    通过3个Store container,共有9个租户

    2. 数据库和Schema混合模式,一个DbContext里面有3个连接连接到3个Store Container的数据库,里面各自有3个Schema,每个Schema下都有一个结构相同的数据表

    通过3个Store Container, 共有9个租户

    转变为读写分离

    在目前的系统中,读写分离是的应用更加广泛。通过下面的图看出,同一个DbContext下有3个连接分别链接到不同的数据库。数据库里见面有完全相同的表

    其中一个是主库,2个是从库。

    如果对比我们典型的多租户模式,其实是非常类型的,显而易见他们之间是可以互相演变的。事实上我项目中其实就是通过多租户模式下演变成读写分离的。

    读写分离&多租户图解

    我们这里先看看下图中的结构。其实这里的图就是我整个系列的主要流程。其中有几个关键步骤

    A. Http Request通过asp.net core的中间件或者拦截器。通过AOP的模式,通过http header和url等, 调用Tenant Generator。

    B. Tenant Generator根据调用的接口参数,获取这是哪一个租户和API的操作类型(读或写),并且讲租户信息和操作类型返回

    C. Connection Resolver接收租户和操作信息的组合,通过配置文件或配置中心获取具体的连接字符串,并且把连接字符串作为参数传入到DbContext的构造函数。

    D. Db Context利用接收到连接字符串,通过EF core的封装,自动连接到不同的数据库。

    注:租户和操作信息的组合,拿store1 & read的组合举个例子,他的配置的连接字符串的键值是 store_read。同理 store2 & write 的键值就是store2_write

     通过上图的结构,其实读写分离在我们的封装下,也是能轻而易举的实现的。估计读者来到这里会发现有3个关键组件是需要用户自定义才能完成。

    分别是中间件或拦截器、Tenant Generator和Connection Resolver。他们3者需要同时维护和使用一个TenantInfo。

    总结

    好了,来到这里已经是本文的结束。是的,本文并没有贴出任何代码,仅仅是一个介绍的随笔。

    本文的目的是,让阅读者对多租户和读写分离模式有抽象的概念,利用图和抽象对象尽量描述出这个模式实现下的关键是什么。

    从系列的第一篇开始,是对多租户的入门,之后的随笔是对该模式的深入理解和加深实施办法。

    经过了前面几篇文章的基础,通过本文的抽象概念和之前的实施代码进行融合,从而希望读者能够系统地了解到分库分表。

    关于代码

    由于之前的代码都只停留在Demo阶段,所以后来我重构了,并且使用了新的Github Repository.

    并且我把如何使用的示例代码都放在了同一个Repository下。

    请到这个github地址下获取重构的代码:

    https://github.com/woailibain/kiwiho.EFcore.MultiTenant

    对于这份代码,由于我也是在最近2天写的,只做了基础功能测试,并且事例代码量有限,我会随着系列文章的进行中,不断补充事例代码也同时修复bug。

    其中事例代码,我会包含今天讲到的所有内容。并且我在编写example的同时,也会发文写关于怎么使用,为什么这样使用的详细。

    往期文章

    如果读者是首次阅读本系列,建议阅读系列的其他文章。因为本文是对前文的总结

    Asp.net core下利用EF core实现从数据实现多租户(1)

    Asp.net core下利用EF core实现从数据实现多租户(2) : 按表分离

    EF core (code first) 通过自定义 Migration History 实现多租户使用同一数据库时更新数据库结构

    EF core (code first) 通过自动迁移实现多租户数据分离 :按Schema分离数据

  • 相关阅读:
    Mysql 从库的备份中恢复一张表
    my.cnf 配置文件参数解释
    利用mvn deploy命令上传包(转)
    IntelliJ IDEA 项目文件旁边都有0%classes,0% lines covered
    idea启动java Maven项目,出现" java: 程序包xxxx不存在"
    org/apache/poi/POIXMLTypeLoader或者java.lang.NoSuchFieldError: RETURN_NULL_AND_BLANK
    elasticsearch,kibana,logstash.下载
    idea显示 RunDashboard ,多个启动项时列表显示
    写for循环快捷生成方式
    Could not transfer artifact xxx from/to xxx解决方案
  • 原文地址:https://www.cnblogs.com/woailibian/p/12391163.html
Copyright © 2020-2023  润新知