一、主从数据库概述

从字面意思上来了解,主从复制的意思其实就是用来建立一个和主数据库完全统一的数据库环境,这种数据库被称之为从数据库,主数据库一般是为准实时的业务数据库。

二、主从复制的优点

1、做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
2、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
3、读写分离,使数据库能支撑更大的并发。在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度。

三、主从数据库的工作流程

支撑主从数据库工作的三个线程:
1.binlog输出线程:每当有从库连接到主库的时候,主库都会创建一个线程然后发送binlog内容到从库。
在从库里,当复制开始的时候,从库就会创建两个线程进行处理:
2.从库I/O线程:当START SLAVE语句在从库开始执行之后,从库创建一个I/O线程,该线程连接到主库并请求主库发送binlog里面的更新记录到从库上。从库I/O线程读取主库的binlog输出线程发送的更新并拷贝这些更新到本地文件,其中包括relay log文件。
3.从库的SQL线程:从库创建一个SQL线程,这个线程读取从库I/O线程写到relay log的更新事件并执行。
image.png
具体流程:
①主库db的更新事件(update、insert、delete)被写到binlog
②:从库发起连接,连接到主库
③:此时主库创建一个binlog dump thread线程,把binlog的内容发送到从库
④:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log.
⑤:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db.
主从同步复制有以下几种方式:
(1)同步复制,master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回。
(2)异步复制,master只需要完成自己的数据库操作即可,至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
(3)半同步复制,master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MYSQL引入的。

四、读写分离

什么是读写分离
让主数据库(master)处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库(slave)处理SELECT查询操作。在数据库中,数据库的“写”操作(写10000条数据到数据库可能要3分钟)操作是比较耗时的。但是数据库的“读”(从数据库读10000条数据可能只要5秒钟)。所以读写分离,解决的是数据库的写入,影响了查询的效率。

什么是MyCat?
MyCAT 是一款开源软件,也是目前最流行的基于Java语言编写的数据库中间件,实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为多个小表,存储在后端MySQL服务器里或者其他数据库里。
配和主从数据库使用可实现读写分离功能。

五、主从数据库部署

1.修改三台节点主机名

  1. [root@localhost ~]# hostnamectl set-hostname mycat
  2. [root@localhost ~]# hostnamectl set-hostname db1
  3. [root@localhost ~]# hostnamectl set-hostname db2

2.配置三台节点主机名映射文件

  1. [root@mycat ~]# vi /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  4. 192.168.200.40 mycat
  5. 192.168.200.50 db1
  6. 192.168.200.60 db2
  7. //将第一台节点的hosts文件发送到第二台节点
  8. [root@mycat ~]# scp /etc/hosts db1:/etc/hosts
  9. The authenticity of host 'db2 (192.168.200.60)' can't be established.
  10. ECDSA key fingerprint is SHA256:Lmr7gTzopJeRGxI8QEh1dATe5NNvhoZYJJlEFK2oiqI.
  11. ECDSA key fingerprint is MD5:58:6b:96:dc:db:45:d7:aa:7f:8a:af:78:df:5a:b4:21.
  12. Are you sure you want to continue connecting (yes/no)? yes
  13. Warning: Permanently added 'db1,192.168.200.60' (ECDSA) to the list of known hosts.
  14. root@db2's password:
  15. hosts 100% 217 237.8KB/s 00:00

3.配置yum源

  1. //在第一台节点上安装ftp服务
  2. [root@mycat ~]# yum -y install vsftpd
  3. //编辑ftp配置文件
  4. [root@mycat ~]# vi /etc/vsftpd/vsftpd.conf
  5. anon_root=/opt //在文件顶部添加
  6. //重启ftp服务
  7. [root@mycat ~]# systemctl restart vsftpd
  8. //设置服务开机自启
  9. [root@mycat ~]# systemctl enable vsftpd
  10. Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to /usr/lib/systemd/system/vsftpd.service.
  11. //在第二台节点移除网络源
  12. [root@db1 ~]# mv /etc/yum.repos.d/* /media/
  13. //编辑本地local.repo文件
  14. [root@db1 ~]# vi /etc/yum.repos.d/local.repo
  15. [centos]
  16. name=centos7
  17. baseurl=ftp://mycat/centos
  18. gpgcheck=0
  19. enable=1
  20. //在第三台节点移除网络源
  21. [root@db2 ~]# mv /etc/yum.repos.d/* /media/
  22. //编辑本地local.repo文件
  23. [root@db2 ~]# vi /etc/yum.repos.d/local.repo
  24. [centos]
  25. name=centos7
  26. baseurl=ftp://mycat/centos
  27. gpgcheck=0
  28. enable=1

4.关闭三台节点防火墙以及selinux

  1. //关闭三台节点防火墙与selinux
  2. [root@mycat ~]# systemctl stop firewalld && systemctl disable firewalld
  3. [root@mycat ~]# setenforce 0

5.第二台和第三台节点安装数据库服务

  1. [root@db1 ~]# yum -y install mariadb mariadb-server

6.初始化第二台和第三台节点数据库,数据库密码全部设置为123456(同步配置)

  1. [root@db1 ~]# systemctl restart mariadb
  2. [root@db1 ~]# mysql_secure_installation
  3. NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
  4. SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
  5. In order to log into MariaDB to secure it, we'll need the current
  6. password for the root user. If you've just installed MariaDB, and
  7. you haven't set the root password yet, the password will be blank,
  8. so you should just press enter here.
  9. Enter current password for root (enter for none):
  10. OK, successfully used password, moving on...
  11. Setting the root password ensures that nobody can log into the MariaDB
  12. root user without the proper authorisation.
  13. Set root password? [Y/n] y
  14. New password:
  15. Re-enter new password:
  16. Password updated successfully!
  17. Reloading privilege tables..
  18. ... Success!
  19. By default, a MariaDB installation has an anonymous user, allowing anyone
  20. to log into MariaDB without having to have a user account created for
  21. them. This is intended only for testing, and to make the installation
  22. go a bit smoother. You should remove them before moving into a
  23. production environment.
  24. Remove anonymous users? [Y/n] y
  25. ... Success!
  26. Normally, root should only be allowed to connect from 'localhost'. This
  27. ensures that someone cannot guess at the root password from the network.
  28. Disallow root login remotely? [Y/n] n
  29. ... skipping.
  30. By default, MariaDB comes with a database named 'test' that anyone can
  31. access. This is also intended only for testing, and should be removed
  32. before moving into a production environment.
  33. Remove test database and access to it? [Y/n] y
  34. - Dropping test database...
  35. ... Success!
  36. - Removing privileges on test database...
  37. ... Success!
  38. Reloading the privilege tables will ensure that all changes made so far
  39. will take effect immediately.
  40. Reload privilege tables now? [Y/n] y
  41. ... Success!
  42. Cleaning up...
  43. All done! If you've completed all of the above steps, your MariaDB
  44. installation should now be secure.
  45. Thanks for using MariaDB!

7.配置第二台和第三台

  1. [root@db1 ~]# vi /etc/my.cnf //编辑数据库配置文件
  2. [mysqld]
  3. log_bin = mysql-bin
  4. binlog_ignore_db = mysql
  5. server_id = 50
  6. [root@db1 ~]# systemctl restart mariadb //重启数据库
  7. [root@db2 ~]# vi /etc/my.cnf //编辑第三台
  8. [mysqld]
  9. log_bin = mysql-bin
  10. binlog_ignore_db = mysql
  11. server_id = 60
  12. [root@db2 ~]# systemctl restart mariadb

8.登录第一台数据库配置权限

  1. //登录
  2. [root@db1 ~]# mysql -uroot -p123456
  3. Welcome to the MariaDB monitor. Commands end with ; or \g.
  4. Your MariaDB connection id is 2
  5. Server version: 5.5.56-MariaDB MariaDB Server
  6. Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
  7. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  8. MariaDB [(none)]> grant all privileges on *.* to root@'%' identified by "123456";
  9. Query OK, 0 rows affected (0.00 sec)
  10. MariaDB [(none)]> grant replication slave on *.* to 'user'@'db2' identified by '123456';
  11. Query OK, 0 rows affected (0.00 sec)
  12. MariaDB [(none)]>

9.配置第二台数据库权限

  1. [root@db2 ~]# mysql -uroot -p123456
  2. Welcome to the MariaDB monitor. Commands end with ; or \g.
  3. Your MariaDB connection id is 2
  4. Server version: 5.5.56-MariaDB MariaDB Server
  5. Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
  6. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  7. MariaDB [(none)]> change master to master_host='db1',master_user='user',master_password='123456';
  8. Query OK, 0 rows affected (0.00 sec)
  9. MariaDB [(none)]> start slave;
  10. Query OK, 0 rows affected (0.00 sec)
  11. MariaDB [(none)]> show slave status\G
  12. *************************** 1. row ***************************
  13. Slave_IO_State: Waiting for master to send event
  14. Master_Host: db1
  15. Master_User: user
  16. Master_Port: 3306
  17. Connect_Retry: 60
  18. Master_Log_File: mysql-bin.000001
  19. Read_Master_Log_Pos: 527
  20. Relay_Log_File: mariadb-relay-bin.000002
  21. Relay_Log_Pos: 811
  22. Relay_Master_Log_File: mysql-bin.000001
  23. Slave_IO_Running: Yes
  24. Slave_SQL_Running: Yes
  25. Replicate_Do_DB:
  26. Replicate_Ignore_DB:
  27. Replicate_Do_Table:
  28. Replicate_Ignore_Table:
  29. Replicate_Wild_Do_Table:
  30. Replicate_Wild_Ignore_Table:
  31. Last_Errno: 0
  32. Last_Error:
  33. Skip_Counter: 0
  34. Exec_Master_Log_Pos: 527
  35. Relay_Log_Space: 1107
  36. Until_Condition: None
  37. Until_Log_File:
  38. Until_Log_Pos: 0
  39. Master_SSL_Allowed: No
  40. Master_SSL_CA_File:
  41. Master_SSL_CA_Path:
  42. Master_SSL_Cert:
  43. Master_SSL_Cipher:
  44. Master_SSL_Key:
  45. Seconds_Behind_Master: 0
  46. Master_SSL_Verify_Server_Cert: No
  47. Last_IO_Errno: 0
  48. Last_IO_Error:
  49. Last_SQL_Errno: 0
  50. Last_SQL_Error:
  51. Replicate_Ignore_Server_Ids:
  52. Master_Server_Id: 50
  53. 1 row in set (0.00 sec)
  54. MariaDB [(none)]>

10.验证数据库同步

  1. MariaDB [(none)]> create database test; //在db1节点创建test库
  2. Query OK, 1 row affected (0.00 sec)
  3. MariaDB [(none)]> use test; //进入到test库中
  4. Database changed
  5. MariaDB [test]> create table company(id int not null primary key,name varchar(50),addr varchar(255)); //创建数据表
  6. Query OK, 0 rows affected (0.00 sec)
  7. MariaDB [test]> insert into company values(1,"facebook","usa"); //插入数据
  8. Query OK, 1 row affected (0.00 sec)
  9. MariaDB [test]> select * from company; //查看数据
  10. +----+----------+------+
  11. | id | name | addr |
  12. +----+----------+------+
  13. | 1 | facebook | usa |
  14. +----+----------+------+
  15. 1 row in set (0.00 sec)
  16. MariaDB [(none)]> show databases; //在db2节点查询数据库
  17. +--------------------+
  18. | Database |
  19. +--------------------+
  20. | information_schema |
  21. | mysql |
  22. | performance_schema |
  23. | test |
  24. +--------------------+
  25. 4 rows in set (0.00 sec)
  26. MariaDB [(none)]> use test; //进入数据库
  27. Reading table information for completion of table and column names
  28. You can turn off this feature to get a quicker startup with -A
  29. Database changed
  30. MariaDB [test]> select * from company; //查询数据表中的内容
  31. +----+----------+------+
  32. | id | name | addr |
  33. +----+----------+------+
  34. | 1 | facebook | usa |
  35. +----+----------+------+
  36. 1 row in set (0.00 sec)

六、读写分离部署

1.第一台节点安装MYCAT服务

image.png

  1. [root@mycat ~]# yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
  2. //解压mycat安装包至/usr/local目录下
  3. [root@mycat ~]# tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/
  4. /将mycat下的包赋予所有权限
  5. [root@mycat ~]# chmod -R 777 /usr/local/mycat/
  6. //在系统环境下添加Mycat变量
  7. [root@mycat ~]# echo export MYCAT_HOME=/usr/local/mycat/ >> /etc/profile
  8. //生效环境变量
  9. [root@mycat ~]# source /etc/profile

2.编辑Mycat 的逻辑库配置文件

  1. [root@mycat ~]# vi /usr/local/mycat/conf/schema.xml
  2. //编辑mycat逻辑库(将原来的文件直接删除然后进行覆盖添加即可) //ip修改为db1和db2的
  3. <?xml version="1.0"?>
  4. <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
  5. <mycat:schema xmlns:mycat="http://io.mycat/">
  6. <schema name="USERDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1"></schema>
  7. <dataNode name="dn1" dataHost="localhost1" database="test" />
  8. <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" dbType="mysql" dbDriver="native" writeType="0" switchType="1" slaveThreshold="100">
  9. <heartbeat>select user()</heartbeat>
  10. <writeHost host="hostM1" url="192.168.200.50:3306" user="root" password="123456">
  11. <readHost host="hostS1" url="192.168.200.60:3306" user="root" password="123456" />
  12. </writeHost>
  13. </dataHost>
  14. </mycat:schema>
  15. //修改逻辑库配置文件权限

3.编辑Mycta访问用户

  1. [root@mycat ~]# vi /usr/local/mycat/conf/server.xml //编辑文件
  2. 在配置文件的最后部分
  3. <user name="root">
  4. <property name="password">123456</property>
  5. <property name="schemas">USERDB</property> //将TESTDB改为USERDB
  6. 然后删除以下几行内容
  7. <user name="user">
  8. <property name="password">user</property>
  9. <property name="schemas">TESTDB</property>
  10. <property name="readOnly">true</property>
  11. </user>

4.启动Mycat服务

  1. [root@mycat ~]# /bin/bash /usr/local/mycat/bin/mycat start
  2. Starting Mycat-server...
  3. //启动之后使用netstat -ntpl命令查询端口号,寻找暴露端口8066、9066端口,如果还想端口暴露则服务正常
  4. [root@mycat ~]# netstat -ntpl
  5. Active Internet connections (only servers)
  6. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
  7. tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN 11380/java
  8. tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 916/sshd
  9. tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1165/master
  10. tcp6 0 0 :::1984 :::* LISTEN 11380/java
  11. tcp6 0 0 :::8066 :::* LISTEN 11380/java
  12. tcp6 0 0 :::9066 :::* LISTEN 11380/java
  13. tcp6 0 0 :::21 :::* LISTEN 11106/vsftpd
  14. tcp6 0 0 :::34422 :::* LISTEN 11380/java
  15. tcp6 0 0 :::22 :::* LISTEN 916/sshd
  16. tcp6 0 0 ::1:25 :::* LISTEN 1165/master
  17. tcp6 0 0 :::40827 :::* LISTEN 11380/java

5.验证mycat读写分离信息

image.png

  1. //上传压缩包
  2. [root@mycat ~]# yum install -y unzip
  3. [root@mycat ~]# unzip gpmall-repo.zip
  4. [root@mycat ~]# ls
  5. anaconda-ks.cfg gpmall-repo gpmall-repo.zip Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
  6. [root@mycat ~]# mv gpmall-repo /opt/
  7. [root@mycat ~]# cd /opt/
  8. [root@mycat opt]# ls
  9. centos gpmall-repo
  10. [root@mycat opt]# vi /etc/yum.repos.d/local.repo
  11. [centos]
  12. name=centos
  13. baseurl=file:///opt/centos
  14. gpgcheck=0
  15. enable=1
  16. [gpmall]
  17. name=gpmall
  18. baseurl=file:///opt/gpmall-repo
  19. gpgcheck=0
  20. enabled=1
  21. [root@mycat opt]# yum clean all
  22. [root@mycat opt]# yum repolist
  23. //现在第一台节点上安装数据库插件
  24. [root@mycat ~]# yum install -y MariaDB-client
  25. [root@mycat ~]# mysql -h127.0.0.1 -P8066 -uroot -p123456
  26. Welcome to the MariaDB monitor. Commands end with ; or \g.
  27. Your MySQL connection id is 2
  28. Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
  29. Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
  30. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  31. MySQL [(none)]> insert into company values(2,"bastetball","usa");
  32. ERROR 3000 (HY000): No MyCAT Database selected
  33. MySQL [(none)]> show databases;
  34. +----------+
  35. | DATABASE |
  36. +----------+
  37. | USERDB |
  38. +----------+
  39. 1 row in set (0.000 sec)
  40. MySQL [(none)]> use USERDB
  41. Reading table information for completion of table and column names
  42. You can turn off this feature to get a quicker startup with -A
  43. Database changed
  44. MySQL [USERDB]> show tables;
  45. +----------------+
  46. | Tables_in_test |
  47. +----------------+
  48. | company |
  49. +----------------+
  50. 1 row in set (0.001 sec)
  51. MySQL [USERDB]> select * from company;
  52. +----+----------+------+
  53. | id | name | addr |
  54. +----+----------+------+
  55. | 1 | facebook | usa |
  56. +----+----------+------+
  57. 1 row in set (0.002 sec)
  58. //使用Mycat服务添加数据表
  59. MySQL [USERDB]> insert into company values(2,"bastetball","usa");
  60. Query OK, 1 row affected (0.002 sec)
  61. MySQL [USERDB]> select * from company;
  62. +----+------------+------+
  63. | id | name | addr |
  64. +----+------------+------+
  65. | 1 | facebook | usa |
  66. | 2 | bastetball | usa |
  67. +----+------------+------+
  68. 2 rows in set (0.001 sec)
  69. MySQL [USERDB]>

7.验证读写分离操作

  1. Mycat 虚拟机节点使用 mysql 命令,通过 9066 端口查询对数据库读写操作的分离信 息。可以看到所有的写入操作 WRITE_LOAD 数都在 db1 主数据库节点上,所有的读取操作 READ_LOAD 数都在 db2 主数据库节点上。
  2. [root@mycat ~]# mysql -h127.0.0.1 -P9066 -uroot -p123456 -e 'show @@datasource;'
  3. +----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
  4. | DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
  5. +----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
  6. | dn1 | hostM1 | mysql | 192.168.200.50 | 3306 | W | 0 | 10 | 1000 | 132 | 0 | 1 |
  7. | dn1 | hostS1 | mysql | 192.168.200.60 | 3306 | R | 0 | 8 | 1000 | 136 | 7 | 0 |
  8. +----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
  9. [root@mycat ~]# netstat -ntpl
  10. Active Internet connections (only servers)
  11. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
  12. tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN 11380/java
  13. tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 916/sshd
  14. tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1165/master
  15. tcp6 0 0 :::1984 :::* LISTEN 11380/java
  16. tcp6 0 0 :::8066 :::* LISTEN 11380/java
  17. tcp6 0 0 :::9066 :::* LISTEN 11380/java
  18. tcp6 0 0 :::21 :::* LISTEN 11106/vsftpd
  19. tcp6 0 0 :::34422 :::* LISTEN 11380/java
  20. tcp6 0 0 :::22 :::* LISTEN 916/sshd
  21. tcp6 0 0 ::1:25 :::* LISTEN 1165/master
  22. tcp6 0 0 :::40827 :::* LISTEN 11380/java