本文介绍如何在宝塔环境下配置分布式数据库,实现 MySQL 主从同步与 TP6 框架的读写分离功能。
前提条件
- MySQL 版本一致。
- MySQL 中的数据一致。
主从服务器信息
- 主服务器IP:
192.168.16.135
- 从服务器IP:
192.168.16.137
在两台虚拟机中安装宝塔并关闭防火墙,确保两台服务器可以互相通信。
systemctl stop firewalld.service
1. 配置主服务器 MySQL
在主服务器上进行如下配置:
编辑 MySQL 配置文件
/etc/my.cnf
,在[mysqld]
属性组下添加以下内容:[mysqld] # [必须] 启用二进制日志 log-bin=mysql-bin # [必须] 服务器唯一ID,一般取IP最后一段 server-id=135
重启 MySQL 服务,并进入 MySQL 命令行:
sudo systemctl restart mysqld mysql -u root -p
创建用于主从同步的用户:
-- 创建帐户 'slave',允许从任何IP访问 GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123456'; -- 或者仅允许从特定IP访问 -- GRANT REPLICATION SLAVE ON *.* TO 'slave'@'192.168.16.137' IDENTIFIED BY '123456';
查询主服务器状态以获取
File
和Position
信息:SHOW MASTER STATUS;
2. 配置从服务器 MySQL
在从服务器上进行如下配置:
编辑 MySQL 配置文件
/etc/my.cnf
,在[mysqld]
属性组下添加以下内容:[mysqld] # [可选] 启用二进制日志 log-bin=mysql-bin # [必须] 服务器唯一ID,一般取IP最后一段 server-id=137
重启 MySQL 服务,并进入 MySQL 命令行:
sudo systemctl restart mysqld mysql -u root -p
配置从服务器同步主服务器的数据:
CHANGE MASTER TO MASTER_HOST='192.168.16.135', MASTER_USER='slave', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000019', MASTER_LOG_POS=3887;
其中
MASTER_LOG_FILE
和MASTER_LOG_POS
是从主服务器的SHOW MASTER STATUS
命令中获取的值。启动从服务器复制功能并检查状态:
START SLAVE; SHOW SLAVE STATUS\G;
确认
Slave_IO_Running
和Slave_SQL_Running
均为Yes
。
3. TP6 配置分布式数据库
在 database.php
中配置主从数据库:
// 省略其他配置
'connections' => [
'mysql' => [
'type' => 'mysql',
// 主库配置
'hostname' => '192.168.16.135',
'database' => 'your_database',
'username' => 'your_username',
'password' => 'your_password',
'hostport' => '3306',
// 读写分离配置
'slave' => [
[
'hostname' => '192.168.16.137',
'database' => 'your_database',
'username' => 'your_username',
'password' => 'your_password',
'hostport' => '3306',
],
],
'read_master' => true, // 开启自动主库读取
],
],
测试读写分离
使用以下代码测试 TP6 的读写分离功能:
public function add() {
$data = [];
for ($i = 0; $i < 5; $i++) {
array_push($data, ['name' => 'name_' . ($i + 1)]);
}
$res = Db::name("student")->insertAll($data); // 主库
dump('插入成功条数: ' . $res);
}
public function list() {
$res = Db::table('student')->where('id', '=', 1)->find(); // 从库
dump($res);
$row = Db::table('student')->where('id', '=', $res['id'])->update(['name' => 'name_4']); // 主库
echo $row;
$res2 = Db::table('student')->where('id', '=', 1)->master(true)->find(); // 强制读取主库
dump($res2);
}
通过配置和代码示例,可以看到读写操作分别使用了不同的服务器,实现了数据库的读写分离和主从同步。