目录
一、目标实现
- 了解mycat提供的读写分离功能
- 了解mysql数据库的主从架构
- 构建以mycat为中间件的读写分离数据库群集
二、项目准备
- 软件:
VMware Workstation 15.5 Pro
MobaXterm_Personal_22.0
- 软件包:
Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
- 物理配置:
CentOS7/2vCPU/4G内存/50G硬盘
- 节点规划:
IP |
主机名 |
节点 |
172.16.51.6 |
mycat |
Mycat中间件服务节点 |
172.16.51.18 |
db1 |
MariaDB数据库集群主节点 |
172.16.51.30 |
db2 |
MariaDB数据库集群从节点 |
三、项目实施
1.配置基础环境
1.1修改主机名
mycat:
[root@localhost ~]# hostnamectl set-hostname mycat #修改主机名为mycat
[root@localhost ~]# bash #刷新
[root@mycat ~]#
db1:
[root@localhost ~]# hostnamectl set-hostname db1 #修改主机名为db1
[root@localhost ~]# bash #刷新
[root@db1 ~]#
db2:
[root@localhost ~]# hostnamectl set-hostname db2 #修改主机名为db2
[root@localhost ~]# bash #刷新
[root@db2 ~]#
1.2配置3台群集虚拟机的/etc/hosts文件
mycat、db1、db2:
[root@mycat/@db1/@db2 ~]# vi /etc/hosts
{
#ip地址 主机名/域名(主机别名)
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.51.6 mycat
172.16.51.18 db1
172.16.51.30 db2
}
补充知识:hosts文件是linux系统中负责ip地址与域名快速解析的文件,它包含了ip地址和主机名之间的映射,以ASCII格式保存在/etc目录下。在没有域名服务器的情况下,它可以充当dns服务器角色(dns缓存>hosts>dns服务)
1.3.配置网卡
单独配置:
mycat:
[root@mycat ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33
{
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=eabcfae9-7b72-41db-8f65-d6e51132239e
DEVICE=ens33
ONBOOT=yes
IPADDR=172.16.51.6 #IP地址
PREFIX=24 #子网掩码
GATEWAY=172.16.51.254 #网关
DNS1=8.8.8.8 #首选DNS
}
db1:
[root@db1 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33
{
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=2268a449-8cb3-450e-a990-4562256fbec9
DEVICE=ens33
ONBOOT=yes
IPADDR=172.16.51.18
PREFIX=24
GATEWAY=172.16.51.254
DNS1=8.8.8.8
}
db2:
[root@db2 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33
{
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=23a65a6d-6a6f-4399-b68a-b0807913f4df
DEVICE=ens33
ONBOOT=yes
IPADDR=172.16.51.30
PREFIX=24
GATEWAY=172.16.51.254
DNS1=8.8.8.8
}
综合配置
1.4.配置本地yum源
[root@mycat/@db1/@db2 ~]# mv /etc/yum.repos.d/* /media/ #移动yun源原配置至文件/media/下
[root@mycat/@db1/@db2 ~]# mkdir /opt/gpmall-repo #创建挂载点
[root@mycat/@db1/@db2 ~]# mount /dev/cdrom /opt/gpmall-repo #挂载
(mount: no medium found on /dev/sr0 #错误提示:没有找到光驱介质,将光盘映像重新连接即可)
[root@mycat/@db1/@db2 ~]# mount /dev/cdrom /opt/gpmall-repo #解决问题后重新挂载
(mount: /dev/sr0 is write-protected, mounting read-only #挂载成功)
[root@mycat/@db1/@db2 ~]# vi /etc/yum.repos.d/local.repo #vi新建并编辑一个repo源文件
{
[mariadb] #yum源名称
name=mariadb #yum源描述
baseurl=file:///opt/gpmall-repo #yum镜像路径地址
gpgcheck=0 #不启用校验(检查包来源)
enabled=1 #启用yum源
}
补充知识:1.目录/media:设备连接后自动挂载的目录。
2. baseurl也可以是=ftp:// 和 http:// 。
2.部署Mycat中间件服务
2.1安装KDJ环境
为什么要安装KDJ环境?
MyCat是java工程师开发的,需要配置java虚拟机环境,所以必须要安装KDJ环境,且部署环境要求JDK必须是1.7及以上版本。
[root@mycat ~]# yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel #安装KDJ(1.8版本)
(Complete! #安装成功)
[root@mycat ~]# java -version #检查JDK版本
(
openjdk version "1.8.0_161"
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)
#有这三条数据即安装成功
)
3.部署MariaDB主从数据库集群服务
3.1安装MariaDB服务
[root@db1/@db2 ~]# yum install -y mariadb mariadb-server #安装数据库MariaDB服务
(Complete! #安装成功)
[root@db1/@db2 ~]# systemctl start mariadb #启动mariadb服务
[root@db1/@db2 ~]# systemctl enable mariadb #将mariadb服务设置为开机自自启
(Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service. #此数据意为在创建从/etc/……到/usr/……的符号链接)
3.2初始化MariaDB数据库
[root@db1/@db2 ~]# mysql_secure_installation #安全配置向导
(
Enter current password for root (enter for none): #根密码,初次运行直接回车
OK, successfully used password, moving on...
…………
Set root password? [Y/n] y #确认重置root密码
New password: #密码不可视
Re-enter new password: #确认密码
Password updated successfully!
Reloading privilege tables..
... Success!
…………
Remove anonymous users? [Y/n] y #确认删除匿名用户
... Success!
…………
Disallow root login remotely? [Y/n] n #不允许root远程登陆
... skipping.
…………
Remove test database and access to it? [Y/n] y #确认刷新数据库
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
…………
Reload privilege tables now? [Y/n] y #确认刷新权限
... Success!
3.3配置数据库集群主节点
[root@db1 ~]# vi /etc/my.cnf #编辑MySQL主配置文件
{
[mysqld] #服务端配置
log_bin=mysql-bin #记录操作日志
binlog_ignore_db=mysql #不同步MySQL系统数据库
server_id=18 #服务id,在集群中,每个节点id须是自己ip尾数
datadir=/var/lib/mysql #数据目录
socket=/var/lib/mysql/mysql.sock #socket通讯设置
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0 #禁用skip-symbolic-links(启用可能会有安全风险)
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
[mysqld_safe] #服务端工具,用于启动mysqld,且是mysqld的守护进程
log-error=/var/log/mariadb/mariadb.log #错误日志存储路径
pid-file=/var/run/mariadb/mariadb.pid #进程id存储路径
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d #参数文件位置路径
}
[root@db1 ~]# systemctlrestart mariadb #重启mariadb服务
3.4开放主节点的数据库权限
[root@db1 ~]# mysql -uroot -p123456 #mysql命令以root用户登录mariadb数据库
{
MariaDB [(none)]> grant all privileges on *.* to root@'%' identified by "123456"; #授权在任何客户端上可以以root用户登录数据库。
(Query OK, 0 rows affected (0.00 sec) #配置成功)
MariaDB [(none)]> grant replication slave on *.* to 'user'@'db2' identified by '123456'; #在主节点db1数据库上创建一个user用户让从节点db2连接,并赋予从节点同步主节点数据库的权限
(Query OK, 0 rows affected (0.00 sec) #配置成功)
MariaDB [(none)]> exit #退出数据库
(Bye #成功退出)
}
3.5从节点同步主节点
[root@db2 ~]# mysql -uroot -p123456 #以root用户登录数据库
{
MariaDB [(none)]> change master to master_host='db1',master_user='user',master_password='123456'; #配置从节点连接主节点的连接信息
(Query OK, 0 rows affected (0.00 sec) #配置成功)
MariaDB [(none)]> start slave; #同时启用I/O线程与SQL线程
(ERROR 1200 (HY000): The server is not configured as slave; fix in config file or with CHANGE MASTER TO #错误提示:没有配置从点服务,发现是没有设置从点的server_id)
MariaDB [(none)]> exit #退出数据库
(Bye #成功退出)
}
[root@db2 ~]# vi /etc/my.cnf
{
[mysqld]
server_id=30 #添加配置db2的server_id
}
[root@db2 ~]# systemctl restart mariadb #重启mariadb服务
[root@db2 ~]# mysql -uroot -p123456 #以root登录数据库
{
MariaDB [(none)]> start slave; #重新启用线程
(Query OK, 0 rows affected (0.00 sec) #启用成功)
MariaDB [(none)]> show slave status\G; #查看从节点服务状态,重点查看Slave_IO_Running和Slave_SQL_Running的状态
(
…………
Slave_IO_Running: No #未开启
Slave_SQL_Running: Yes #成功开启
…………
)
#查出结果,发现主节点的server_id丢失,重新设置server_id并重启服务
…………
MariaDB [(none)]> show slave status\G; 重新查看db2的服务状态
(
Slave_IO_Running: Yes #成功开启
Slave_SQL_Running: Yes #成功开启
)
}
3.6验证主从数据库同步功能
步骤1:在主节点db1创建库test,在库test中创建表company,并插入表数据。
MariaDB [(none)]> create database test; #创建数据库test
(Query OK, 1 row affected (0.00 sec) #创建成功)
MariaDB [(none)]> use test #选择并进入数据库test
(Database changed) #成功进入库
MariaDB [test]> create table company(id int not null primary key,name varchar(50),addr varchar(255)); #创建名为"company"的表,
(Query OK, 0 rows affected (0.01 sec) #成功创建表
MariaDB [test]> insert into company values(1,"facebook","usa"); #为表"company"插入表数据,数据为(1,"facebook","usa")
(Query OK, 1 row affected (0.00 sec) #成功插入数据
MariaDB [test]> select * from company; #查询表数据
(
+----+----------+------+
| id | name | addr |
+----+----------+------+
| 1 | facebook | usa |
+----+----------+------+
1 row in set (0.00 sec)
)
步骤2:在从节点db2验证从主节点db1同步过来的数据
MariaDB [(none)]> show databases; #显示所有数据库,发现已有数据库"test"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.00 sec)
MariaDB [(none)]> select * from test.company; #查询表数据,发现已有facebook,usa
+----+----------+------+
| id | name | addr |
+----+----------+------+
| 1 | facebook | usa |
+----+----------+------+
1 row in set (0.00 sec)
4部署Mycat读写分离中间件服务
4.1安装Mycat服务
步骤1:使用ssh工具——(MobaXterm_Personal_22.0)将Mycat服务的二进制软件包Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz上传到Mycat虚拟机的/root目录下。并将软件包解压到/use/local目录中,赋予解压后的Mycat目录权限。
[root@mycat ~]# tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/ #压缩软件包
[root@mycat ~]# chown -R 777 /usr/local/mycat/ #赋予全部权限
步骤2:添加系统变量,并生效变量
[root@mycat ~]# echo export MYCAT_HOME=/usr/local/mycat/ >> /etc/profile #将系统变量mycat目录/usr/local/mycat/追加输出到环境变量/etc/profile
[root@mycat ~]# source /etc/profile #生效环境变量
补充知识:echo是shell命令,用于输出内容;
export用于设置/显示环境变量;
>>是重定向符,将'>>'前面的文件内容/命令追加输出到后面的文件;
MYCAT_HOME=/usr/local/mycat/中,MYCAT_HOME是MYCAT的目录,/usr/local/mycat/即其存储路径;
/etc/profile是环境变量,系统变量是环境变量的一种,常说的环境变量就是系统环境变量,对所有用户起作用,而相应的用户环境变量只对当前用户起作用。
4.2编辑Mycat逻辑库配置文件
[root@mycat ~]# vi /usr/local/mycat/conf/schema.xml #编辑逻辑库配置文件
{
<?xmlversion="1.0"?> #xml结构
<!DOCTYPEmycat:schema SYSTEM "schema.dtd"> #xml结构
<mycat:schemaxmlns:mycat="http://io.mycat/"> #xml结构
<schemaname="USERDB" checkSQLschema="true" sqlMaxLimit="100"dataNode="dn1"></schema> #schema标签用于定义MyCat的逻辑库,即操作节点
#schemaname定义了mycat前端显示的逻辑数据库的名字
#checkSQLschema用于检查是否通过 dbName.tableName 的方式来访问数据库中的表,默认false,即用户自己检测。
#sqlMaxLimit限制了默认查询数量
#dataNode指定了逻辑数据库对应的物理数据库节点逻辑名称
<dataNodename="dn1" dataHost="localhost1" database="test"/> #不使用mycat托管mysql主从服务器操作一
#dataNodename定义了数据节点的操作节点
#dataHost定义了数据节点的逻辑名称
#database定义了数据节点要使用的数据库名称
<dataHostname="localhost1" maxCon="1000" minCon="10"balance="3" dbType="mysql" dbDriver="native"writeType="0" switchType="1" slaveThreshold="100"> #不使用mycat托管mysql主从服务器操作二
#dataHostname是唯一标识,供上层标签使用
#maxCon指定每个读写实例连接池的最大连接数
#minCon指定每个读写实例连接池的最小连接数
#balance="3"将所有读请求随机地分发到wiriterHost对应的readhost执行,writerHost不负担读压力(注意balance=3只在1.4及以上版本有)
<heartbeat>selectuser()</heartbeat> #配置真实mysql与mycat的心跳
<writeHost host="hostM1"url="172.16.51.18:3306" user="root" password(🦀)="123456"> #指定写实例的主机,ip地址与端口,登录用户及其密码
<readHost host="hostS1"url="172.16.51.30:3306" user="root" password(🦀)="123456"/> #指定读实例的主机,ip地址与端口,登录用户及其密码
</writeHost> #xml结构,结束标签
</dataHost> #xml结构,结束标签
</mycat:schema> #xml结构,结束标签
}
[root@mycat ~]# chown root:root /usr/local/mycat/conf/schema.xml #修改schema.xml的用户权限
密码被迫和谐,请不要在意
4.3编辑mycat的访问用户
[root@mycat ~]# vi /usr/local/mycat/conf/server.xml
{
#修改最后部分
…………
<username="root">
<propertyname="password">123456</property> #root用户的访问密码
<propertyname="schemas">USERDB</property> #root用户访问的逻辑库
…………
#删除以下部分(关于用户user的配置)
<user name="user">
<propertyname="password">user</property>
<propertyname="schemas">TESTDB</property>
<propertyname="readOnly">true</property>
</user>
}
[root@mycat ~]# /bin/bash /usr/local/mycat/bin/mycat start #开启mysql数据库中间件服务
(Starting Mycat-server... #启动成功)
[root@mycat ~]# netstat -ntpl #查看虚拟机TCP类型端口开放情况(n即数字形式显示ip地址与端口号,t即tcp协议的端口,p即proto指定的协议连接,l即正监听的端口)
(-bash: netstat: command not found #没有找到指令,需先安装对于服务)
[root@mycat ~]# yum -y install net-tools #安装"net-tools"包
(Complete! #安装成功)
[root@mycat ~]# netstat -ntpl #再次查看端口情况,有我们需要的8066和9066端口
(
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN 21572/java
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1000/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1314/master
tcp6 0 0 :::1984 :::* LISTEN 21572/java
tcp6 0 0 :::8066 :::* LISTEN 21572/java
tcp6 0 0 :::9066 :::* LISTEN 21572/java
tcp6 0 0 :::22 :::* LISTEN 1000/sshd
tcp6 0 0 :::46809 :::* LISTEN 21572/java
tcp6 0 0 ::1:25 :::* LISTEN 1314/master
tcp6 0 0 :::36859 :::* LISTEN 21572/java
)
补充知识:8066端口是mycat服务默认的数据端口,9066端口是mycat管理端口,用于管理mycat的整个集群状态。
5验证集群服务读写分离
5.1Mycat服务查询数据库信息
[root@mycat ~]# yum -y install mariadb* #安装mariadb数据库服务
[root@mycat ~]# mysql -h127.0.0.1 -P8066 -uroot -p123456 #指定ip地址、端口、用户登录mysql
{
…………
MySQL [(none)]> show databases; #显示所有数据库
+----------+
| DATABASE |
+----------+
| USERDB |
+----------+
1 row in set (0.00 sec)
MySQL [(none)]> use USERDB #连接数据库USERDB
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [USERDB]> show tables; #显示所有表格
+----------------+
| Tables_in_test |
+----------------+
| company |
+----------------+
1 row in set (0.00 sec)
MySQL [USERDB]> select * from company; #查询表数据
+----+----------+------+
| id | name | addr |
+----+----------+------+
| 1 | facebook | usa |
+----+----------+------+
1 row in set (0.04 sec)
}
5.2Mycat添加表数据
MySQL [USERDB]> insert into company values(2,"bastetball","usa"); #插入表数据
Query OK, 1 row affected (0.00 sec)
MySQL [USERDB]> select * from company; #查询表数据
+----+----------+------+
| id | name | addr |
+----+----------+------+
| 1 | facebook | usa |
+----+----------+------+
1 row in set (0.01 sec)
5.3验证Mycat服务对数据库读写操作分离
[root@mycat ~]# mysql -h127.0.0.1 -P9066 -uroot -p123456 -e 'show @@datasource;' #指定ip、port、用户显示数据库读写分离信息
+----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
| DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
+----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
| dn1 | hostM1 | mysql | 172.16.51.18 | 3306 | W | 0 | 10 | 1000 | 370 | 0 | 1 |
| dn1 | hostS1 | mysql | 172.16.51.30 | 3306 | R | 0 | 8 | 1000 | 371 | 4 | 0 |
+----------+--------+-------+--------------+------+------+--------+------+------+---------+-----------+------------+
四、知识集锦
1.读写分离
1.1什么是读写分离?
读写分离就是将数据库分为了主从库,主库用于写入数据,从库用于读出数据(P.S.主库只能有一个,从库可以有多个)。
图片来源于网络,侵删
1.2为什么要用到读写分离?
读写分离用来解决数据库的读性能瓶颈。
举个栗子:当我要进入某个考试系统内报名,由于此时是高峰期,平时不会过多维护系统网站,就会造成卡顿/延迟等问题。就是性能不够,写入的数据不变,但突然间奔涌的读取数据会使网站崩溃。
P.S.读写分离要区分数据库连接池,且要能够实现故障自动转移,最后要考虑主从的一致性。
图片来源于网络,侵删
1.3读写分离有哪些应用场景?
程序使用数据库较多、更新较少、查询较多的情况下会考虑使用,相反,会考虑使用读写分离。
1.4如何实现读写分离?
使用中间件服务节点与数据库MariaDB集群主从节点。
2.MySQL基础
1.连接与退出mysql
mysql -h主机地址 -u用户名 -p用户密码
exit
2.数据库(database)
create database db_name; #创建数据库
show databases; #显示所有的数据库
drop database db_name; #删除数据库
use db_name; #选择数据库
3.表(table)
create table tb_name (字段名 varchar(20), 字段名 char(1)); #创建数据表模板
show tables; 显示数据表
desc tb_name; 显示表结构
drop table tb_name; 删除表
4.插入表数据(insert into)
mysql> insert into tb_name (field1,field2.field3,……) values (value1,value2,value3,...); #插入表数据
5.查询数据(select)
select <目标列表达式列表> #查询数据的类型
[into 新表名]
from 表名或视图名 #查询数据的地方
[where <条件>] #查询数据的条件
[group by <分组表达式>]
[having <条件>]
[order by <排序表达式>[ASC|DESC]]select * from tb_name; #查询表的所有列
五、参考来源
什么是数据库读写分离? - Luiken - 博客园 (cnblogs.com)
实战案例——构建读写分离的数据库集群(超详细)_清瞳清的博客-CSDN博客_构建读写分离的数据库集群
浅谈web网站架构演变过程 - 小M的博客 - 博客园 (cnblogs.com)