[Praktisches Projekt] Einzelne Datenquelle und mehrere Datenbanken, um Mandantenfähigkeit zu erreichen

Vorwort

Multi-Tenancy ist ein Entwurfsmuster für Softwarearchitekturen, das darauf abzielt, einer einzelnen Anwendung die gleichzeitige Bereitstellung von Diensten für mehrere Mandanten (z. B. verschiedene Organisationen, Benutzer oder Kunden) zu ermöglichen. Jeder Mandant verfügt über unabhängige Daten und Konfigurationen und ist von diesen isoliert gegenseitig. Die Implementierung einer mandantenfähigen Architektur kann Unternehmen dabei helfen, Kosten zu senken, die Verwaltung zu vereinfachen und die Effizienz zu steigern.

Bevor wir ein mandantenfähiges System entwerfen, müssen wir die Geschäftsanforderungen und erwarteten Ziele klären. Möchten Sie eine vollständige Isolierung zwischen den Mandanten oder möchten Sie einige gemeinsame Ressourcen zulassen? Wir müssen folgende Aspekte berücksichtigen:

Datenisolierung: Die Daten jedes Mandanten sollten voneinander isoliert sein, und verschiedene Mandanten können nicht direkt auf Daten zugreifen oder diese teilen. Die Datenisolierung kann durch die Verwendung separater Datenbanken oder die Verwendung von Mandanten-IDs in Datentabellen zur Unterscheidung erreicht werden.

Identitätsauthentifizierung und -autorisierung: Ein mandantenfähiges System muss die Identitätsauthentifizierung und -autorisierung jedes Mandanten unterstützen, um sicherzustellen, dass nur legitime Benutzer auf ihre eigenen Mandantenressourcen zugreifen können.

Horizontale Erweiterung: Multi-Tenant-Systeme stehen möglicherweise vor der Herausforderung einer großen Anzahl von Benutzern und eines Datenwachstums. Daher müssen sie horizontal erweitert werden können, um eine hohe Leistung und Zuverlässigkeit des Systems aufrechtzuerhalten.

Konfigurationsverwaltung: Jeder Mandant kann unterschiedliche Konfigurationsanforderungen haben, z. B. Parametereinstellungen für die Integration mit E-Mail, Zahlung, Speicherung usw. Daher sollte ein flexibel konfigurierbarer Mechanismus bereitgestellt werden, der es den Mietern ermöglicht, ihn an ihre Bedürfnisse anzupassen.

Sicherheit und Isolierung: Mandantenfähige Systeme erfordern eine sichere Isolierung zwischen Mandanten, um potenzielle Datenlecks und Zugriffskonflikte zu verhindern. Bei der Gestaltung des Systems sollten der Schutz sensibler Daten und die Verhinderung verschiedener Angriffe berücksichtigt werden.

Ressourcennutzung: Um die Ressourcennutzung zu verbessern, können Sie die gemeinsame Nutzung bestimmter gemeinsamer Ressourcen wie Rechenressourcen, Speicherplatz und Netzwerkbandbreite in Betracht ziehen. Das senkt die Kosten und sorgt für mehr Effizienz.

Vier Implementierungsmöglichkeiten für Mandantenfähigkeit

Gängige Designlösungen werden grob in 4 Typen unterteilt:

1. Alle Mandanten verwenden dieselbe Datenquelle und dieselbe Datentabelle in derselben Datenbank (einzelne Datenquelle, einzelne Datenbank, einzelne Datentabelle). 2. Alle Mandanten verwenden dieselbe
Datenquelle und unterschiedliche Datentabellen in derselben Datenbank (einzelne Daten). Quelle, einzelne Datenbank, mehrere Datentabellen)
3. Alle Mandanten verwenden unterschiedliche Datentabellen in verschiedenen Datenbanken unter derselben Datenquelle (einzelne Datenquelle, mehrere Datenbanken, mehrere Datentabellen)
4. Alle Mandanten verwenden unterschiedliche Datentabellen in verschiedenen Datenbanken unter unterschiedlichen Datenquellen (mehrere Datenquellen, mehrere Datenbanken, mehrere Datentabellen)
Fügen Sie hier eine Bildbeschreibung ein

Der erste und der zweite Typ sind relativ einfach. Unser Artikel erklärt hauptsächlich den dritten Typ

Einzelne Datenquelle, mehrere Datenbanken

Das ultimative Ziel der Mehrmandantenfähigkeit besteht darin, Datenisolation zu erreichen. In mehreren Datenbanken mit mehreren Datenquellen, dh wenn ein neuer Mandant registriert wird, müssen eine Datenbank und entsprechende Datenbanktabellen erstellt werden.
Nun stellt sich die Frage: Wie erstellt man dynamisch eine Datenbank?

Umsetzungsideen

1. Erstellen Sie eine Datenbank: Sie können die herkömmliche Methode verwenden, um sie mithilfe von SQL-Anweisungen zu erstellen.
2. Erstellen Sie eine Datenbanktabelle: Nachdem Sie die Datenbank erstellt haben, verwenden Sie SQL-Anweisungen, um die Tabelle zu erstellen.

Der folgende Code verwendet SQL, um die zu erstellende XML-Datei zu lesen

Code

Erstellen Sie eine XML-Datei unter Ressourcen:
Fügen Sie hier eine Bildbeschreibung ein

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <statement>
        <name>create-tenant</name>
        <script>
            DROP DATABASE IF EXISTS `sys_user${
    
    tenant_id}`;
            CREATE DATABASE ${
    
    database};
            USE ${
    
    database};

            CREATE TABLE `sys_user` (
            `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
            `dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
            `user_name` varchar(30) NOT NULL COMMENT '用户账号',
            `nick_name` varchar(30) NOT NULL COMMENT '用户昵称',
            `user_type` varchar(2) DEFAULT '00' COMMENT '用户类型(00系统用户)',
            `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
            `phonenumber` varchar(11) DEFAULT '' COMMENT '手机号码',
            `sex` char(1) DEFAULT '0' COMMENT '用户性别(012未知)',
            `avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
            `password` varchar(100) DEFAULT '' COMMENT '密码',
            `status` char(1) DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
            `del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
            `login_ip` varchar(128) DEFAULT '' COMMENT '最后登录IP',
            `login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
            `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
            `create_time` datetime DEFAULT NULL COMMENT '创建时间',
            `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
            `update_time` datetime DEFAULT NULL COMMENT '更新时间',
            `remark` varchar(500) DEFAULT NULL COMMENT '备注',
            `auth_id` varchar(30) DEFAULT NULL COMMENT '其他项目用户id(积分)',
            `ding_id` varchar(50) DEFAULT NULL COMMENT '用户dingid',
            `tenant_id` varchar(100) DEFAULT NULL COMMENT '公司id',
            `open_id` varchar(50) DEFAULT NULL COMMENT '微信用户唯一标识',
            PRIMARY KEY (`user_id`) USING BTREE
            ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户信息表';
                 </script>
    </statement>
</document>

Dies ist die entsprechende Anweisung zum Erstellen einer Datenbank.

Informationen aus der XML-Datei abrufen:

@Component
public class ExecSqlConfig {
    
    
    private final Map<String, String> sqlContainer = new HashMap<>();

    public ExecSqlConfig() throws Exception {
    
    
        // 1.创建Reader对象
        SAXReader reader = new SAXReader();
        // 2.加载xml
        InputStream inputStream = new ClassPathResource("create-library.xml").getInputStream();
        Document document = reader.read(inputStream);
        // 3.获取根节点
        Element root = document.getRootElement();

        // 4.遍历每个statement
        List<Element> statements = root.elements("statement");
        for (Element statement : statements) {
    
    
            String name = null;
            String sql = null;
            List<Element> elements = statement.elements();
            // 5.拿到name和script加载到内存中管理
            for (Element element : elements) {
    
    
                if ("name".equals(element.getName())) {
    
    
                    name = element.getText();
                } else if ("script".equals(element.getName())) {
    
    
                    sql = element.getText();
                }
            }
            sqlContainer.put(name, sql);
        }
    }

    public String get(String name) {
    
    
        return sqlContainer.get(name);
    }

}

SQL-Ausführungsskript:
Lesen Sie die Informationen in der ExecSqlConfig-Datei im Skript

@Component
public class ExecSqlUtil {
    
    
    @Autowired
    private   ExecSqlConfig execSqlConfig ;

    @Autowired
    private  DataSource dataSource ;
/**
 * @description: 把模板中的数据库名称替换为新租户的名称
 * @author: 
 * @date: 2023/9/27 15:05
 * @param: [name , replaceMap]
 * @return: void
 **/
    @SneakyThrows
    public  void execSql(String name, Map<String, String> replaceMap) {
    
    
        try {
    
    
            // 获取SQL脚本模板
            String sql = execSqlConfig.get(name);

            // 替换模板变量
            for (Map.Entry<String, String> entity : replaceMap.entrySet()) {
    
    
                sql = sql.replace(entity.getKey(), entity.getValue());
            }
            ScriptRunner scriptRunner = new ScriptRunner(dataSource.getConnection());

            // 执行SQL
           scriptRunner.runScript(new StringReader(sql));
        }catch (Exception e){
    
    
            e.printStackTrace();
        }

    }

}

Geschäftslogik

public void addTenantLibrary(TanentModel tanentModel) {
    
    
        try {
    
    
            if (!(tanentModel.getDescription().isEmpty()||tanentModel.getTenantContact().isEmpty()||tanentModel.getTel().isEmpty()||tanentModel.getTenantName().isEmpty())){
    
    
                //判断数据源中是否已经存在该数据库
               int flag= tantentMapper.insertTantentAdmin(tanentModel.getTenantName());
               if (flag>0){
    
    
                   throw new Exception("已存在该数据库");
               }else {
    
    
                   Map<String,String> map=new HashMap<>();
                   map.put("${database}",tanentModel.getTenantName());
                   map.put("${project_name}",tanentModel.getTenantName());
                   map.put("${leader}",tanentModel.getTenantContact());
                   map.put("${phone}",tanentModel.getTel());
                   map.put("${description}",tanentModel.getDescription());
                   execSqlUtil.execSql("create-tenant",map);

               }
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
            throw new RuntimeException(e.getMessage()); // 将异常信息作为响应的一部分返回给前端
        }
    }

Im Geschäftslogikcode ist „map.put(“${database}“,tanentModel.getTenantName()); die Variable in der ersetzten XML-Datei

Zusammenfassen

In einer Multi-Tenant-Architektur ist eine einzelne Datenquelle mit mehreren Datenbanken eine gängige Implementierungslösung. Durch die Verwendung verschiedener Datenbankinstanzen oder Datenbankschemata können wir eine unabhängige Datenspeicherung für jeden Mandanten erreichen und die Isolation voneinander aufrechterhalten. In diesem Artikel diskutieren wir Implementierungsoptionen und einige wichtige Überlegungen für mehrere Datenbanken mit einer einzigen Datenquelle.

Zusammenfassend bietet die Lösung mit einer einzigen Datenquelle und mehreren Datenbanken die folgenden Vorteile für Systeme mit mehreren Mandanten:

Datenisolation: Jeder Mandant verfügt über eine unabhängige Datenbank, und die Daten beeinträchtigen sich nicht gegenseitig, wodurch die Isolation und Sicherheit der Mandantendaten gewährleistet wird.

Leistungsoptimierung: Durch die Verteilung der Mandantendaten auf mehrere Datenbanken kann der Lastdruck auf eine einzelne Datenbank verringert und die Systemleistung und der Durchsatz verbessert werden.

Skalierbarkeit: Wenn die Anzahl der Mandanten steigt, kann das System horizontal erweitert werden, indem neue Datenbankinstanzen oder Datenbankserver hinzugefügt werden, um wachsenden Geschäftsanforderungen gerecht zu werden.

Fehlertoleranz: Die Lösung mit einer einzigen Datenquelle und mehreren Datenbanken reduziert die Interaktion zwischen Mandanten. Wenn eine Datenbank ausfällt, können andere Datenbanken weiterhin normal ausgeführt werden, wodurch die Fehlertoleranz und Verfügbarkeit des Systems verbessert wird.

Bei der Implementierung einer Multidatenbanklösung mit einer einzigen Datenquelle müssen wir auf die folgenden Schlüsselfaktoren achten:

Datenmigration und -synchronisierung: Bei bestehenden mandantenfähigen Systemen kann die Migration bestehender Daten in eine neue Datenbank einen gewissen Arbeitsaufwand erfordern. Gleichzeitig müssen wir zur Aufrechterhaltung der Datenkonsistenz die Datensynchronisation zwischen mehreren Datenbanken sicherstellen.

Mandantenverwaltungs- und Routing-Strategien: Dynamische Management- und Routing-Strategien für Mandanten müssen implementiert werden, um sicherzustellen, dass jede Anfrage korrekt an die entsprechende Datenbank weitergeleitet werden kann. Dies kann durch die Pflege einer Mandanten-zu-Datenbank-Zuordnung oder die Verwendung von Middleware für die Anforderungsweiterleitung erreicht werden.

Datenbankverbindung und Ressourcenverwaltung: Beim Systemdesign müssen die Verwaltung und Ressourcenzuweisung von Datenbankverbindungen berücksichtigt werden. Durch die ordnungsgemäße Konfiguration des Datenbankverbindungspools und die Optimierung von Datenbankabfragen können die Systemleistung und die Ressourcennutzung verbessert werden.

Sicherheit und Berechtigungskontrolle: Beim Entwurf der Datenbankarchitektur müssen Sie die Anforderungen an Sicherheit und Berechtigungskontrolle berücksichtigen. Stellen Sie sicher, dass der Datenzugriff und -betrieb zwischen verschiedenen Mandanten eingeschränkt ist und die gesetzlichen Anforderungen an Datenschutz und Datenschutz eingehalten werden.

Zusammenfassend lässt sich sagen, dass eine einzelne Datenquelle und mehrere Datenbanken eine effektive Lösung zur Implementierung eines mandantenfähigen Systems sind, das eine gute Datenisolierung, Leistungsoptimierung und Skalierbarkeit bietet. Allerdings müssen Faktoren wie Datenmigration, Mandantenverwaltung, Ressourcenmanagement und Sicherheit während des Implementierungsprozesses umfassend berücksichtigt werden, um die Stabilität und Zuverlässigkeit des Systems sicherzustellen. Bei richtiger Konzeption und Implementierung kann die Multidatenbanklösung mit einer einzigen Datenquelle eine effiziente, sichere und skalierbare Datenspeicherlösung für Systeme mit mehreren Mandanten bieten.

Acho que você gosta

Origin blog.csdn.net/weixin_45309155/article/details/133409083
Recomendado
Clasificación