在企业网站中,后端MySQL数据库只有一台时,会有以下问题
改造方法
更好的解决方案
基于语句的复制(默认,一般都是用这种类型)
基于行的复制
混合类型的复制
主机 | ip |
---|---|
主MySQL服务器 | 192.168.188.65 |
从MySQL服务器1 | 192.168.188.66 |
从MySQL服务器2 | 192.168.188.67 |
我们通过二进制包安装
tar xf mysql-5.7.25-el7-x86_64.tar.gz -C /usr/local/
mv mysql-5.7.25-el7-x86_64 mysql
groupadd mysql
useradd -M -s /sbin/nologin mysql -g mysql
chown -R mysql.mysql /usr/local/mysql
vim /etc/my.cnf
[mysqld]
user=mysql
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
server_id=1
port=3306
socket=/tmp/mysql.sock
[mysql]
socket=/tmp/mysql.sock
prompt=mysql [\\d]>
添加环境变量
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> /etc/profile
source /etc/profile
初始化
mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
如果报错可以
yum install -y libaio
使用systemd管理mysql
vim /etc/systemd/system/mysqld.service
[Unit]
Description=MySQL Server
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf
LimitNOFILE = 5000
systemctl daemon-reload
systemctl start mysqld
netstat -lnt
设置密码
mysqladmin -uroot password '123'
登陆验证
mysql -uroot -p123
保证三台服务器都完整安装MySQL
在主节点上搭建时间同步服务器
安装NTP(关闭防火墙/selinux)
yum -y install ntp
配置NTP
vim /etc/ntp.conf
# local clock
server 127.127.1.0 # 本地时间供给源
fudge 127.127.1.0 stratum 8 # 设置时区为+08区
重启服务并设置为开机启动
systemctl enable ntpd --now
在从节点上进行时间同步
yum -y install ntpdate
ntpdate 192.168.188.65
修改主节点配置
vim /etc/my.cnf
server_id = 1 # 服务器编号
log_bin = master-bin # 开启二进制日志
log-slave-updates = true # 开启从机复制
重启mysqld
systemctl restart mysqld
进入mysql查看二进制日志是否开启
show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.00 sec)
给服务器授权
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'192.168.188.%' IDENTIFIED BY '123';
刷新权限
FLUSH PRIVILEGES;
获取日志名及偏移量
show master status;
修改从节点配置
vim /etc/my.cnf
server_id = 2 # 每个服务器编号不一样
relay-log=relay-log-bin # 开启中继日志
relay-log-index=slave-relay-bin.index # 开启索引记录
重启mysqld
systemctl restart mysqld
在从服务器上配置同步
change master to master_host='192.168.188.65',master_user='slave',master_password='123',master_log_file='maste
r-bin.000001',master_log_pos=604; --这个数字就是在主服务器上 show master status; 查出来的
开启同步(stop slave是停止)
start slave;
备注; 解决UUID重复的问题:
mv /usr/local/mysql/data/auto.cnf /usr/local/mysql/data/auto.cnf.bak
进入主MySQL
show slave hosts;
新建一个测试库school
CREATE DATABASE IF NOT EXISTS `school`;
-- 创建一个school数据库
USE `school`;-- 创建学生表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`(
`studentno` INT(4) NOT NULL COMMENT '学号',
`loginpwd` VARCHAR(20) DEFAULT NULL,
`studentname` VARCHAR(20) DEFAULT NULL COMMENT '学生姓名',
`gender` varchar(2) NOT NULL DEFAULT '女' COMMENT '性别',
`gradeid` INT(11) DEFAULT NULL COMMENT '年级编号',
`phone` VARCHAR(50) NOT NULL COMMENT '联系电话,允许为空',
`address` VARCHAR(255) NOT NULL COMMENT '地址,允许为空',
`borndate` DATETIME DEFAULT NULL COMMENT '出生时间',
`email` VARCHAR (50) NOT NULL COMMENT '邮箱账号允许为空',
`identitycard` VARCHAR(18) DEFAULT NULL COMMENT '身份证号',
PRIMARY KEY (`studentno`),
UNIQUE KEY `identitycard`(`identitycard`),
KEY `email` (`email`)
)ENGINE=MYISAM DEFAULT CHARSET=utf8;
INSERT INTO `student` (`studentno`,`loginpwd`,`studentname`,`gender`,`gradeid`,`phone`,`address`,`borndate`,`email`,`identitycard`)
VALUES
(1000,'123456','唐嘉','女',2,'13800001234','北京朝阳','1980-5-2','[email protected]','123456198001011298'),
(1001,'123456','刘美玲','女',1,'13800002222','广东深圳','1991-6-4','[email protected]','123456199001011191'),
(1002,'123456','潘辰','男',1,'13800002111','四川成都','1992-7-6','[email protected]','123456199001011333'),
(1003,'123456','小田','男',2,'13800002333','四川成都','1993-8-8','[email protected]','123456199001011555'),
(1004,'123456','胡杨','男',3,'13800002555','浙江杭州','1994-9-10','[email protected]','123456199001011777'),
(1005,'123456','猫猫','女',2,'13800002666','日本东京','1995-1-12','[email protected]','123456199001011888'),
(1006,'123456','飞飞','男',2,'13800002666','上海浦东','1997-7-12','[email protected]','123456199001011666');
只在主服务器上写,只在从服务器上读
基本原理是让主数据库处理事务性查询,而从数据库处理select查询
Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。
主要功能:
读写分离
从库负载均衡
IP过滤
自动分表
DBA可平滑上下线DB
自动摘除宕机的DB
Atlas相对于官方MySQL-Proxy的优势
将主流程中所有Lua代码用C重写,Lua仅用于管理接口
重写网络模型、线程模型
实现了真正意义上的连接池
优化了锁机制,性能提高数十倍
主机 | ip |
---|---|
主MySQL服务器 | 192.168.188.65 |
从MySQL服务器1 | 192.168.188.66 |
从MySQL服务器2 | 192.168.188.67 |
从MySQL服务器3 | 192.168.188.69 |
Atlas 中间代理服务器 | 192.168.188.68 |
rpm -ivh https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
补充:
安装后,它会默认在”/usr/local/mysql-proxy”下生成4个文件夹,以及需要配置的文件
bin
目录下放的都是可执行文件
conf
目录下放的是配置文件
lib
目录下放的是一些包,以及Atlas的依赖
log
目录下放的是日志,如报错等错误信息的记录
配置master,slave1,slave2,slave3中开放权限给atlas:
grant all on *.* to mao@'192.168.188.%' identified by '123';
flush privileges;
加密用户名密码
进入bin目录,使用encrypt来对数据库的密码进行加密,我的MySQL数据的用户名是mao,密码是123,我需要对密码进行加密
cd /usr/local/mysql-proxy/bin
./encrypt 123
3yb5jEku5h4= # 加密的字符就是写在配置文件里的
编辑test.cnf配置文件
vim /usr/local/mysql-proxy/conf/test.cnf
[mysql-proxy]
#带#号的为非必需的配置项目
admin-username = atlas # 自定义
#管理接口的密码
admin-password = 123
#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses = 192.168.188.65:3306
#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
#proxy-read-only-backend-addresses = 127.0.0.1:3305@1
proxy-read-only-backend-addresses = 192.168.188.66:3306@1,192.168.188.67:3306@1,192.168.188.69:3306@1
#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密
pwds = mao:3yb5jEku5h4=
# 守护进程
daemon = true
keepalive = true
#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置
event-threads = 4
#日志级别,分为message、warning、critical、error、debug五个级别
log-level = message
#日志存放的路径
log-path = /usr/local/mysql-proxy/log
#sql-log = OFF
#慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该参数则输出全部日志。
#sql-log-slow = 10
#实例名称,用于同一台机器上多个Atlas实例间的区分
#instance = test
#Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:1234
#Atlas监听的管理接口IP和端口
admin-address = 0.0.0.0:2345
#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3
#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
#charset = utf8
#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1
#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1
配置无误后,启动Atlas软件
/usr/local/mysql-proxy/bin/mysql-proxyd test start
在Atlas 代理服务器上
yum -y install mysql
mysql -h127.0.0.1 -P2345 -uatlas -p123 # 这里用户和密码就是配置文件里面写的
select * from help; # 可以查看帮助
select * from backends; # 查看目前的主从复制
通过代理访问Mysql
mysql -h192.168.188.68 -P1234 -umao -p123 # 这里用户名和密码就是之前授权的账号
进入数据库后可以查询到主MySQL的所有库和表
select * from school.student;
在MASTER/测试机上创建一个库和表
CREATE DATABASE IF NOT EXISTS `test`;
create table student (
-> id int(4) not null auto_increment comment '学号',
-> name varchar(30) default null comment '姓名',
-> gender varchar(2) not null default '女' comment '性别',
-> primary key (id)
-> )
-> engine=innodb default charset=utf8;
分别在两台从服务器上停止复制。
stop slave;
在主服务器上,插入数据
insert into student (id,name,gender)
-> values
-> (1,'猫猫','女');
在从服务器1上,手动插入一条内容
insert into student (id,name,gender)
values (2,'猪猪','男');
在从服务器2上,手动插入一条内容
insert into student (id,name,gender)
values (3,'牛牛','男');
在从服务器3上,手动插入一条内容
insert into student (id,name,gender)
-> values (4,'小宋','女');
测试读操作
在测试机上第一次查询结果 `
在测试机上第二次查询结果
在测试机上第三次查询结果
在Atlas主机上插入一条语句:
insert into student (id,name,gender)
values (5,'小田','男');
在Atlas上查询不到,最终只有在MASTER上才能看到这条语句内容,说明写操作只能在Master上。
由此验证:已经实现了MYSQL读写分离,目前所有的写操作都在MASTER主服务器上,用来避免数据的不同步,所有的读操作都分摊给了slave从服务器,用来分担数据库压力。