数据库读写分离是一种常见的数据库架构设计,通过将读操作和写操作分离到不同的数据库实例上,以提高系统的性能和可扩展性。读写分离通常通过主从复制(Master-Slave Replication)实现,其中主数据库(Master)负责处理写操作,从数据库(Slave)负责处理读操作。
以下内容将详细介绍如何进行数据库读写分离,并结合代码示例。
1. 数据库读写分离的基本概念
在读写分离架构中:
- 主数据库(Master):负责处理所有的写操作(INSERT、UPDATE、DELETE)。
- 从数据库(Slave):负责处理读操作(SELECT),从主数据库复制数据。
2. 实现读写分离的步骤
- 配置主从复制:设置主数据库和从数据库的复制关系。
- 修改应用程序代码:将写操作路由到主数据库,将读操作路由到从数据库。
- 使用中间件:使用如 ProxySQL、MySQL Router 或其他中间件来简化读写分离的实现。
3. 主从复制配置
以下是配置 MySQL 主从复制的步骤。
3.1 主数据库配置
- 修改主数据库配置文件 (
my.cnf
或my.ini
):
ini
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-do-db = your_database_name # 将 'your_database_name' 替换为实际的数据库名
- 重启主数据库:
bash
sudo systemctl restart mysql
- 在主数据库上创建复制用户:
sql
CREATE USER 'replica_user'@'%' IDENTIFIED BY 'replica_password';
GRANT REPLICATION SLAVE ON *.* TO 'replica_user'@'%';
FLUSH PRIVILEGES;
- 获取二进制日志信息:
sql
SHOW MASTER STATUS;
记下 File
和 Position
的值,将在配置从数据库时使用。
3.2 从数据库配置
- 修改从数据库配置文件 (
my.cnf
或my.ini
):
ini
[mysqld]
server-id = 2
relay-log = mysql-relay-bin
- 重启从数据库:
bash
sudo systemctl restart mysql
- 在从数据库上设置复制:
sql
CHANGE MASTER TO
MASTER_HOST='master_host_ip',
MASTER_USER='replica_user',
MASTER_PASSWORD='replica_password',
MASTER_LOG_FILE='mysql-bin.000001', # 替换为获取的 File 值
MASTER_LOG_POS=123; # 替换为获取的 Position 值
START SLAVE;
- 检查复制状态:
sql
SHOW SLAVE STATUS\G;
确保 Slave_IO_Running
和 Slave_SQL_Running
均为 Yes
。
4. 修改应用程序代码
示例代码以 Python 和 SQLAlchemy 为例,展示如何在应用程序中实现读写分离。
4.1 安装依赖
bash
pip install sqlalchemy pymysql
4.2 配置数据库引擎
python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 主数据库(写操作)
master_engine = create_engine('mysql+pymysql://username:password@master_host/your_database_name')
# 从数据库(读操作)
slave_engine = create_engine('mysql+pymysql://username:password@slave_host/your_database_name')
# 创建 Session
MasterSession = sessionmaker(bind=master_engine)
SlaveSession = sessionmaker(bind=slave_engine)
# 获取 Session
master_session = MasterSession()
slave_session = SlaveSession()
4.3 使用读写分离
python
# 写操作
def create_user(username, email):
new_user = User(username=username, email=email)
master_session.add(new_user)
master_session.commit()
# 读操作
def get_user(user_id):
user = slave_session.query(User).filter(User.id == user_id).first()
return user
5. 使用中间件
使用中间件如 ProxySQL 可以简化读写分离的实现。
5.1 安装 ProxySQL
bash
sudo apt-get install proxysql
5.2 配置 ProxySQL
- 登录 ProxySQL 管理控制台:
bash
mysql -u admin -padmin -h 127.0.0.1 -P 6032
- 添加主从数据库:
sql
-- 添加主数据库
INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight) VALUES (10, 'master_host_ip', 3306, 1);
-- 添加从数据库
INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight) VALUES (20, 'slave_host_ip', 3306, 1);
- 配置读写分离规则:
sql
-- 写操作发送至主数据库
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup) VALUES (1, 1, '^INSERT|^UPDATE|^DELETE', 10);
-- 读操作发送至从数据库
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup) VALUES (2, 1, '^SELECT', 20);
- 加载配置:
sql
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
小结
通过主从复制配置和应用程序代码的修改,可以实现数据库读写分离,从而提高系统的性能和扩展性。在实际生产环境中,使用中间件如 ProxySQL 可以简化读写分离的实现,进一步提升系统的可维护性和可靠性。