内容简介:本文主要介绍MariaDB多租户架构的实现方法与实践,包括多租户架构的基本概念、多租户架构的模式、多租户架构的优缺点等内容。通过实际案例讲解多租户架构的实现过程,帮助读者掌握多租户架构的设计和实现技能。风哥教程参考MariaDB官方文档和相关最佳实践。
Part01-基础概念与理论知识
1.1 多租户架构的基本概念
多租户架构(Multi-tenant Architecture)是一种软件架构模式,允许多个租户(Tenant)共享同一个应用实例和数据库,同时保持数据隔离。每个租户只能访问自己的数据,不能访问其他租户的数据。
多租户架构的主要特点:
- 资源共享:多个租户共享同一个应用实例和数据库
- 数据隔离:每个租户的数据相互隔离,不能相互访问
- 可扩展性:可以轻松添加新租户
- 成本效益:通过资源共享降低成本
1.2 多租户架构的模式
多租户架构主要有三种模式:
- 共享数据库模式:所有租户共享同一个数据库,通过租户ID区分不同租户的数据
- 分离数据库模式:每个租户有自己的数据库,完全隔离
- 混合模式:结合共享数据库和分离数据库的优点,根据数据的重要性和访问频率选择不同的存储方式
1.3 多租户架构的优缺点
多租户架构的优点:
- 降低成本:通过资源共享降低硬件和维护成本
- 简化管理:集中管理所有租户的应用和数据
- 快速部署:可以快速为新租户部署应用
- 易于升级:集中升级应用,所有租户同时受益
多租户架构的缺点:
- 性能影响:多个租户共享资源,可能影响性能
- 数据安全:需要确保租户数据的隔离和安全
- 复杂性增加:设计和实现多租户架构需要更多的考虑
- 扩展性挑战:随着租户数量的增加,需要考虑扩展性
更多视频教程www.fgedu.net.cn
Part02-生产环境规划与建议
2.1 多租户架构规划
多租户架构规划建议:
- 租户识别机制:设计合理的租户识别机制,如租户ID、域名等
- 数据模型设计:根据租户数量和数据量设计合适的数据模型
- 资源分配:合理分配资源,确保每个租户的性能
- 监控与告警:建立租户级别的监控和告警机制
2.2 数据隔离策略
数据隔离策略建议:
- 共享数据库模式:通过租户ID字段区分不同租户的数据,使用视图和存储过程控制访问
- 分离数据库模式:为每个租户创建独立的数据库,使用连接池管理连接
- 混合模式:核心数据使用分离数据库,非核心数据使用共享数据库
2.3 性能优化建议
性能优化建议:
- 索引优化:为租户ID字段创建索引,提高查询性能
- 缓存策略:使用缓存减少数据库访问
- 查询优化:优化SQL语句,避免全表扫描
- 资源隔离:使用数据库资源管理(Resource Management)隔离不同租户的资源
- 定期维护:定期优化数据库,清理无用数据
学习交流加群风哥微信: itpux-com
Part03-生产环境项目实施方案
3.1 多租户架构实现
更多学习教程公众号风哥教程itpux_com
# 多租户架构实现
MariaDB [(none)]> # 1. 共享数据库模式
# 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 创建用户表,包含租户ID
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 创建索引
CREATE INDEX idx_tenant_id ON fgedu_users(tenant_id);
# 2. 分离数据库模式
# 为每个租户创建数据库
CREATE DATABASE fgedu_tenant_1;
CREATE DATABASE fgedu_tenant_2;
# 在每个数据库中创建相同的表结构
USE fgedu_tenant_1;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
MariaDB [(none)]> # 1. 共享数据库模式
# 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 创建用户表,包含租户ID
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 创建索引
CREATE INDEX idx_tenant_id ON fgedu_users(tenant_id);
# 2. 分离数据库模式
# 为每个租户创建数据库
CREATE DATABASE fgedu_tenant_1;
CREATE DATABASE fgedu_tenant_2;
# 在每个数据库中创建相同的表结构
USE fgedu_tenant_1;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 数据隔离实现
# 数据隔离实现
MariaDB [(none)]> # 1. 共享数据库模式的数据隔离
# 创建视图,只显示当前租户的数据
CREATE VIEW v_fgedu_users AS
SELECT * FROM fgedu_users WHERE tenant_id = CURRENT_TENANT_ID();
# 创建存储过程,设置当前租户ID
DELIMITER //
CREATE PROCEDURE set_tenant_id(IN tenant_id INT)
BEGIN
SET @current_tenant_id = tenant_id;
END //
DELIMITER;
# 创建函数,获取当前租户ID
DELIMITER //
CREATE FUNCTION CURRENT_TENANT_ID() RETURNS INT
BEGIN
RETURN @current_tenant_id;
END //
DELIMITER;
# 2. 分离数据库模式的数据隔离
# 创建租户连接池,根据租户ID选择对应的数据库
# 示例代码(应用层实现)
# def get_tenant_connection(tenant_id):
# db_name = f”fgedu_tenant_{tenant_id}”
# return create_connection(db_name, user, password)
MariaDB [(none)]> # 1. 共享数据库模式的数据隔离
# 创建视图,只显示当前租户的数据
CREATE VIEW v_fgedu_users AS
SELECT * FROM fgedu_users WHERE tenant_id = CURRENT_TENANT_ID();
# 创建存储过程,设置当前租户ID
DELIMITER //
CREATE PROCEDURE set_tenant_id(IN tenant_id INT)
BEGIN
SET @current_tenant_id = tenant_id;
END //
DELIMITER;
# 创建函数,获取当前租户ID
DELIMITER //
CREATE FUNCTION CURRENT_TENANT_ID() RETURNS INT
BEGIN
RETURN @current_tenant_id;
END //
DELIMITER;
# 2. 分离数据库模式的数据隔离
# 创建租户连接池,根据租户ID选择对应的数据库
# 示例代码(应用层实现)
# def get_tenant_connection(tenant_id):
# db_name = f”fgedu_tenant_{tenant_id}”
# return create_connection(db_name, user, password)
3.3 租户管理
# 租户管理
MariaDB [(none)]> # 1. 添加租户
INSERT INTO fgedu_tenants(name, domain) VALUES(‘Tenant 1’, ‘tenant1.fgedu.net.cn’);
# 2. 删除租户
DELETE FROM fgedu_tenants WHERE id = 1;
# 3. 租户数据管理
# 备份租户数据
mysqldump -u root -p fgedu_db fgedu_users –where=”tenant_id = 1″ > tenant1_backup.sql;
# 恢复租户数据
mysql -u root -p fgedu_db < tenant1_backup.sql;
# 清理租户数据
DELETE FROM fgedu_users WHERE tenant_id = 1;
MariaDB [(none)]> # 1. 添加租户
INSERT INTO fgedu_tenants(name, domain) VALUES(‘Tenant 1’, ‘tenant1.fgedu.net.cn’);
# 2. 删除租户
DELETE FROM fgedu_tenants WHERE id = 1;
# 3. 租户数据管理
# 备份租户数据
mysqldump -u root -p fgedu_db fgedu_users –where=”tenant_id = 1″ > tenant1_backup.sql;
# 恢复租户数据
mysql -u root -p fgedu_db < tenant1_backup.sql;
# 清理租户数据
DELETE FROM fgedu_users WHERE tenant_id = 1;
学习交流加群风哥QQ113257174
Part04-生产案例与实战讲解
4.1 共享数据库模式实现
场景描述:实现一个基于共享数据库模式的多租户应用。
# 共享数据库模式实现
MariaDB [(none)]> # 1. 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 2. 创建用户表
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 创建产品表
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 4. 创建索引
CREATE INDEX idx_tenant_id ON fgedu_users(tenant_id);
CREATE INDEX idx_tenant_id ON fgedu_products(tenant_id);
# 5. 插入租户数据
INSERT INTO fgedu_tenants(name, domain) VALUES(‘Tenant 1’, ‘tenant1.fgedu.net.cn’), (‘Tenant 2’, ‘tenant2.fgedu.net.cn’);
# 6. 插入用户数据
INSERT INTO fgedu_users(tenant_id, username, email, password) VALUES
(1, ‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’),
(1, ‘user2’, ‘user2@tenant1.fgedu.net.cn’, ‘password123’),
(2, ‘user3’, ‘user3@tenant2.fgedu.net.cn’, ‘password123’);
# 7. 插入产品数据
INSERT INTO fgedu_products(tenant_id, name, price) VALUES
(1, ‘Product 1’, 100.00),
(1, ‘Product 2’, 200.00),
(2, ‘Product 3’, 150.00);
# 8. 查询租户1的用户
SELECT * FROM fgedu_users WHERE tenant_id = 1;
# 9. 查询租户2的产品
SELECT * FROM fgedu_products WHERE tenant_id = 2;
MariaDB [(none)]> # 1. 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 2. 创建用户表
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 创建产品表
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 4. 创建索引
CREATE INDEX idx_tenant_id ON fgedu_users(tenant_id);
CREATE INDEX idx_tenant_id ON fgedu_products(tenant_id);
# 5. 插入租户数据
INSERT INTO fgedu_tenants(name, domain) VALUES(‘Tenant 1’, ‘tenant1.fgedu.net.cn’), (‘Tenant 2’, ‘tenant2.fgedu.net.cn’);
# 6. 插入用户数据
INSERT INTO fgedu_users(tenant_id, username, email, password) VALUES
(1, ‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’),
(1, ‘user2’, ‘user2@tenant1.fgedu.net.cn’, ‘password123’),
(2, ‘user3’, ‘user3@tenant2.fgedu.net.cn’, ‘password123’);
# 7. 插入产品数据
INSERT INTO fgedu_products(tenant_id, name, price) VALUES
(1, ‘Product 1’, 100.00),
(1, ‘Product 2’, 200.00),
(2, ‘Product 3’, 150.00);
# 8. 查询租户1的用户
SELECT * FROM fgedu_users WHERE tenant_id = 1;
# 9. 查询租户2的产品
SELECT * FROM fgedu_products WHERE tenant_id = 2;
执行结果:
# 查询租户1的用户
+—-+———–+———-+————————+————-+———————+
| id | tenant_id | username | email | password | created_at |
+—-+———–+———-+————————+————-+———————+
| 1 | 1 | user1 | user1@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
| 2 | 1 | user2 | user2@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
+—-+———–+———-+————————+————-+———————+
# 查询租户2的产品
+—-+———–+———-+——-+———————+
| id | tenant_id | name | price | created_at |
+—-+———–+———-+——-+———————+
| 3 | 2 | Product 3 | 150.0 | 2023-01-01 10:00:00 |
+—-+———–+———-+——-+———————+
+—-+———–+———-+————————+————-+———————+
| id | tenant_id | username | email | password | created_at |
+—-+———–+———-+————————+————-+———————+
| 1 | 1 | user1 | user1@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
| 2 | 1 | user2 | user2@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
+—-+———–+———-+————————+————-+———————+
# 查询租户2的产品
+—-+———–+———-+——-+———————+
| id | tenant_id | name | price | created_at |
+—-+———–+———-+——-+———————+
| 3 | 2 | Product 3 | 150.0 | 2023-01-01 10:00:00 |
+—-+———–+———-+——-+———————+
4.2 分离数据库模式实现
场景描述:实现一个基于分离数据库模式的多租户应用。
# 分离数据库模式实现
MariaDB [(none)]> # 1. 创建租户管理数据库
CREATE DATABASE fgedu_tenant_management;
USE fgedu_tenant_management;
# 2. 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
db_name VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 为每个租户创建数据库
CREATE DATABASE fgedu_tenant_1;
CREATE DATABASE fgedu_tenant_2;
# 4. 在每个租户数据库中创建表结构
USE fgedu_tenant_1;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 5. 重复步骤4为其他租户创建表结构
USE fgedu_tenant_2;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 6. 插入租户数据
USE fgedu_tenant_management;
INSERT INTO fgedu_tenants(name, domain, db_name) VALUES
(‘Tenant 1’, ‘tenant1.fgedu.net.cn’, ‘fgedu_tenant_1’),
(‘Tenant 2’, ‘tenant2.fgedu.net.cn’, ‘fgedu_tenant_2’);
# 7. 插入租户1的数据
USE fgedu_tenant_1;
INSERT INTO fgedu_users(username, email, password) VALUES
(‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’),
(‘user2’, ‘user2@tenant1.fgedu.net.cn’, ‘password123’);
INSERT INTO fgedu_products(name, price) VALUES
(‘Product 1’, 100.00),
(‘Product 2’, 200.00);
# 8. 插入租户2的数据
USE fgedu_tenant_2;
INSERT INTO fgedu_users(username, email, password) VALUES
(‘user3’, ‘user3@tenant2.fgedu.net.cn’, ‘password123’);
INSERT INTO fgedu_products(name, price) VALUES
(‘Product 3’, 150.00);
MariaDB [(none)]> # 1. 创建租户管理数据库
CREATE DATABASE fgedu_tenant_management;
USE fgedu_tenant_management;
# 2. 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
db_name VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 为每个租户创建数据库
CREATE DATABASE fgedu_tenant_1;
CREATE DATABASE fgedu_tenant_2;
# 4. 在每个租户数据库中创建表结构
USE fgedu_tenant_1;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 5. 重复步骤4为其他租户创建表结构
USE fgedu_tenant_2;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 6. 插入租户数据
USE fgedu_tenant_management;
INSERT INTO fgedu_tenants(name, domain, db_name) VALUES
(‘Tenant 1’, ‘tenant1.fgedu.net.cn’, ‘fgedu_tenant_1’),
(‘Tenant 2’, ‘tenant2.fgedu.net.cn’, ‘fgedu_tenant_2’);
# 7. 插入租户1的数据
USE fgedu_tenant_1;
INSERT INTO fgedu_users(username, email, password) VALUES
(‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’),
(‘user2’, ‘user2@tenant1.fgedu.net.cn’, ‘password123’);
INSERT INTO fgedu_products(name, price) VALUES
(‘Product 1’, 100.00),
(‘Product 2’, 200.00);
# 8. 插入租户2的数据
USE fgedu_tenant_2;
INSERT INTO fgedu_users(username, email, password) VALUES
(‘user3’, ‘user3@tenant2.fgedu.net.cn’, ‘password123’);
INSERT INTO fgedu_products(name, price) VALUES
(‘Product 3’, 150.00);
执行结果:
# 查询租户1的用户
USE fgedu_tenant_1;
SELECT * FROM fgedu_users;
+—-+———-+————————+————-+———————+
| id | username | email | password | created_at |
+—-+———-+————————+————-+———————+
| 1 | user1 | user1@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
| 2 | user2 | user2@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
+—-+———-+————————+————-+———————+
# 查询租户2的产品
USE fgedu_tenant_2;
SELECT * FROM fgedu_products;
+—-+———-+——-+———————+
| id | name | price | created_at |
+—-+———-+——-+———————+
| 1 | Product 3 | 150.0 | 2023-01-01 10:00:00 |
+—-+———-+——-+———————+
USE fgedu_tenant_1;
SELECT * FROM fgedu_users;
+—-+———-+————————+————-+———————+
| id | username | email | password | created_at |
+—-+———-+————————+————-+———————+
| 1 | user1 | user1@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
| 2 | user2 | user2@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
+—-+———-+————————+————-+———————+
# 查询租户2的产品
USE fgedu_tenant_2;
SELECT * FROM fgedu_products;
+—-+———-+——-+———————+
| id | name | price | created_at |
+—-+———-+——-+———————+
| 1 | Product 3 | 150.0 | 2023-01-01 10:00:00 |
+—-+———-+——-+———————+
4.3 混合模式实现
场景描述:实现一个基于混合模式的多租户应用,核心数据使用分离数据库,非核心数据使用共享数据库。
# 混合模式实现
MariaDB [(none)]> # 1. 创建租户管理数据库
CREATE DATABASE fgedu_tenant_management;
USE fgedu_tenant_management;
# 2. 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
db_name VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 创建共享数据库,存储非核心数据
CREATE DATABASE fgedu_shared;
USE fgedu_shared;
# 4. 创建共享表,包含租户ID
CREATE TABLE fgedu_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
level VARCHAR(20) NOT NULL,
message TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 5. 为每个租户创建数据库,存储核心数据
CREATE DATABASE fgedu_tenant_1;
CREATE DATABASE fgedu_tenant_2;
# 6. 在每个租户数据库中创建核心表
USE fgedu_tenant_1;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 7. 插入租户数据
USE fgedu_tenant_management;
INSERT INTO fgedu_tenants(name, domain, db_name) VALUES
(‘Tenant 1’, ‘tenant1.fgedu.net.cn’, ‘fgedu_tenant_1’),
(‘Tenant 2’, ‘tenant2.fgedu.net.cn’, ‘fgedu_tenant_2’);
# 8. 插入核心数据
USE fgedu_tenant_1;
INSERT INTO fgedu_users(username, email, password) VALUES
(‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’);
# 9. 插入共享数据
USE fgedu_shared;
INSERT INTO fgedu_logs(tenant_id, level, message) VALUES
(1, ‘INFO’, ‘User login’),
(2, ‘ERROR’, ‘Database connection failed’);
MariaDB [(none)]> # 1. 创建租户管理数据库
CREATE DATABASE fgedu_tenant_management;
USE fgedu_tenant_management;
# 2. 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
db_name VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 创建共享数据库,存储非核心数据
CREATE DATABASE fgedu_shared;
USE fgedu_shared;
# 4. 创建共享表,包含租户ID
CREATE TABLE fgedu_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
level VARCHAR(20) NOT NULL,
message TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 5. 为每个租户创建数据库,存储核心数据
CREATE DATABASE fgedu_tenant_1;
CREATE DATABASE fgedu_tenant_2;
# 6. 在每个租户数据库中创建核心表
USE fgedu_tenant_1;
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 7. 插入租户数据
USE fgedu_tenant_management;
INSERT INTO fgedu_tenants(name, domain, db_name) VALUES
(‘Tenant 1’, ‘tenant1.fgedu.net.cn’, ‘fgedu_tenant_1’),
(‘Tenant 2’, ‘tenant2.fgedu.net.cn’, ‘fgedu_tenant_2’);
# 8. 插入核心数据
USE fgedu_tenant_1;
INSERT INTO fgedu_users(username, email, password) VALUES
(‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’);
# 9. 插入共享数据
USE fgedu_shared;
INSERT INTO fgedu_logs(tenant_id, level, message) VALUES
(1, ‘INFO’, ‘User login’),
(2, ‘ERROR’, ‘Database connection failed’);
执行结果:
# 查询租户1的核心数据
USE fgedu_tenant_1;
SELECT * FROM fgedu_users;
+—-+———-+————————+————-+———————+
| id | username | email | password | created_at |
+—-+———-+————————+————-+———————+
| 1 | user1 | user1@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
+—-+———-+————————+————-+———————+
# 查询共享数据
USE fgedu_shared;
SELECT * FROM fgedu_logs WHERE tenant_id = 1;
+—-+———–+——-+————-+———————+
| id | tenant_id | level | message | created_at |
+—-+———–+——-+————-+———————+
| 1 | 1 | INFO | User login | 2023-01-01 10:00:00 |
+—-+———–+——-+————-+———————+
USE fgedu_tenant_1;
SELECT * FROM fgedu_users;
+—-+———-+————————+————-+———————+
| id | username | email | password | created_at |
+—-+———-+————————+————-+———————+
| 1 | user1 | user1@tenant1.fgedu.net.cn | password123 | 2023-01-01 10:00:00 |
+—-+———-+————————+————-+———————+
# 查询共享数据
USE fgedu_shared;
SELECT * FROM fgedu_logs WHERE tenant_id = 1;
+—-+———–+——-+————-+———————+
| id | tenant_id | level | message | created_at |
+—-+———–+——-+————-+———————+
| 1 | 1 | INFO | User login | 2023-01-01 10:00:00 |
+—-+———–+——-+————-+———————+
风哥提示:安全开发是防止SQL注入的第一道防线
Part05-风哥经验总结与分享
5.1 多租户架构最佳实践
风哥提示:在设计和实现多租户架构时,应遵循最佳实践,确保系统的可扩展性、安全性和性能。
- 选择合适的多租户模式:根据租户数量、数据量和性能要求选择合适的多租户模式
- 合理设计数据模型:为共享数据库模式设计合理的数据模型,确保数据隔离
- 实现租户识别机制:设计可靠的租户识别机制,确保请求正确路由到对应的租户
- 加强安全措施:确保租户数据的隔离和安全,防止越权访问
- 建立监控和告警机制:监控租户的资源使用情况,及时发现和解决问题
5.2 性能优化技巧
- 索引优化:为租户ID字段创建索引,提高查询性能
- 缓存策略:使用缓存减少数据库访问,提高响应速度
- 查询优化:优化SQL语句,避免全表扫描
- 资源隔离:使用数据库资源管理(Resource Management)隔离不同租户的资源
- 数据库分片:对于大型多租户应用,考虑使用数据库分片技术
- 定期维护:定期优化数据库,清理无用数据
5.3 常见问题与解决方案
- 性能问题:随着租户数量的增加,性能可能下降。解决方案:使用缓存、优化查询、资源隔离等
- 数据安全:租户可能访问其他租户的数据。解决方案:加强访问控制,使用视图和存储过程控制访问
- 扩展性挑战:随着租户数量的增加,系统可能难以扩展。解决方案:使用水平扩展、数据库分片等技术
- 备份与恢复:需要为每个租户单独备份和恢复数据。解决方案:实现自动化的备份和恢复机制
- 迁移困难:租户数据迁移可能比较困难。解决方案:设计合理的数据迁移策略,使用工具辅助迁移
# 多租户架构实现示例
— 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
— 创建用户表
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
— 创建索引
CREATE INDEX idx_tenant_id ON fgedu_users(tenant_id);
— 插入租户数据
INSERT INTO fgedu_tenants(name, domain) VALUES(‘Tenant 1’, ‘tenant1.fgedu.net.cn’), (‘Tenant 2’, ‘tenant2.fgedu.net.cn’);
— 插入用户数据
INSERT INTO fgedu_users(tenant_id, username, email, password) VALUES
(1, ‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’),
(2, ‘user2’, ‘user2@tenant2.fgedu.net.cn’, ‘password123’);
— 查询租户1的用户
SELECT * FROM fgedu_users WHERE tenant_id = 1;
— 创建租户表
CREATE TABLE fgedu_tenants (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
domain VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
— 创建用户表
CREATE TABLE fgedu_users (
id INT PRIMARY KEY AUTO_INCREMENT,
tenant_id INT NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES fgedu_tenants(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
— 创建索引
CREATE INDEX idx_tenant_id ON fgedu_users(tenant_id);
— 插入租户数据
INSERT INTO fgedu_tenants(name, domain) VALUES(‘Tenant 1’, ‘tenant1.fgedu.net.cn’), (‘Tenant 2’, ‘tenant2.fgedu.net.cn’);
— 插入用户数据
INSERT INTO fgedu_users(tenant_id, username, email, password) VALUES
(1, ‘user1’, ‘user1@tenant1.fgedu.net.cn’, ‘password123’),
(2, ‘user2’, ‘user2@tenant2.fgedu.net.cn’, ‘password123’);
— 查询租户1的用户
SELECT * FROM fgedu_users WHERE tenant_id = 1;
通过以上措施,可以有效实现MariaDB多租户架构,确保系统的可扩展性、安全性和性能。
from MariaDB视频:www.itpux.com
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
