docker mysql主从复制 mycat读写分离 分库分表【水平拆分/垂直拆分】

扩展

linux安装docker,mysql配置

docker中mysql主从复制

环境

192.168.135.20
192.168.135.21

- 主服务器的配置

下面是在没有docker下配置,想要查看docker自定义my.cnf配置,移步到扩展,其中Ctrl+F  搜索 “修改my.cnf文件”,就能够定位到配置内容。
1. 在第一个服务器上,编辑mysql配置文件
    // 编辑mysql配置文件
    vi /etc/my.cnf
      
    // 在[mysqld]下面加上:
    // log-bin代表开启主从复制,server-id代表主从服务器的唯一标识
    log-bin=mysql-bin
    server-id=1
    innodb_flush_log_at_trx_commit=1
    sync_binlog=1

2. 查看主服务器的配置
      // 重启mysql
      service mysqld restart
      
      // 登录mysql
      mysql -u root -p

      // 查看主服务的配置
      show master status;
      需要记住 File 列和 Position 列的数据,将来配置从服务器需要使用
  

  mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.03 sec)

docker的操作

# 启动 Docker

[root@localhost ~]# systemctl start docker

# 查看容器

docker ps -a

# 启动mysql容器

docker start [容器名]

# 进入容器

  docker exec -it 3de8e50705e9 /bin/bash
# 登录mysql服务

   mysql -u root -p

# 第一种方式

// 创建用户
CREATE USER 'hm'@'%' IDENTIFIED BY 'itheima';

// 授权
GRANT ALL ON *.* TO 'hm'@'%';

# 第二种方式 创建主从连接帐号与授权

GRANT REPLICATION SLAVE ON *.* TO '主用户名'@'%' IDENTIFIED BY '密码';
 

# 修改my.cnf文件,修改完后,重启mysql服务。

# 退出

exit

# 重启mysql命令

docker restart c_mysql

# 再次进入mysql服务

# 进入容器

  docker exec -it 3de8e50705e9 /bin/bash
# 登录mysql服务

   mysql -u root -p

// 查看主服务器配置
show master status;

+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.03 sec)
 

- 从服务器的配置
1. 在第二个服务器上,编辑mysql配置文件
      // 编辑mysql配置文件
      vi /etc/my.cnf
      
      // 在[mysqld]下面加上:
      server-id=2

2. 登录mysql
      // 登录mysql
      mysql -u root -p
      
      // 执行
      use mysql;
      drop table slave_master_info;
      drop table slave_relay_log_info;
      drop table slave_worker_info;
      drop table innodb_index_stats;
      drop table innodb_table_stats;
      source /usr/share/mysql/mysql_system_tables.sql;

3. 重启mysql,重新登录,配置从节点
      // 重启mysql
      service mysqld restart
      
      // 重新登录mysql
      mysql -u root -p
      
      // 执行
       change master to master_host='192.168.135.20',master_port=3307,master_user='root',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=120;

      // 开启从节点
      start slave;
      
      // 查询结果
      show slave status\G;
      //Slave_IO_Running和Slave_SQL_Running都为YES才表示同步成功。

如果设置错误,可以删除主从连接,在进行重新配置。

mysql> stop slave;
Query OK, 0 rows affected (0.12 sec)

mysql> reset slave all;
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status\G
Empty set (0.00 sec)


问题: Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

[root@localhost ~]# docker exec -it 3de8e50705e9 /bin/bash
 

变更uuid,复制到临时文件,然后替换容器里的文件,重启mysql服务

 问题:Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

mysql> stop slave;
Query OK, 0 rows affected (0.12 sec)

mysql> reset slave;
Query OK, 0 rows affected (0.41 sec)

mysql> start slave;
Query OK, 0 rows affected (0.04 sec)


问题:Error 'Operation DROP USER failed for 'hikktn'@'%'' on query. Default database: ''. Query: 'DROP USER 'hikktn'@'%''

MariaDB [(none)]> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

MariaDB [(none)]> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)

4. 测试
    在主服务器上创建一个db1数据库,查看从服务器上是否自动同步

mycat

问题:安装成功后,按照各种博客,尝试打开mysql,都以1184 - Invalid Datasource:0失败告终。

这个东西卡了我好几天,什么解决方案都无效。

这时的环境

心得收获:mycat不需要使用docker,反而加大配置难度。在schema.xml不要有任何中文注释,都有造成一下错误,wrapper.log

致使即便连接成功了,也会出现1184 - Invalid Datasource:0,打不开数据库。根本无法进行操作,读写分离也好,分库分表也好,都无法进行。

还有这两个配置最好直接使用 vi/vim命令更改,不要使用任何其他软件编辑,破坏了原本文件的编码格式。

下面是我的安装以及配置,读写分离

 put D:\Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz 

解压:解压mycat.tar.gz并查看

tar -zxvf mycat.tar.gz
cd mycat
ll

授权:设置mycat权限

chmod -R 777 mycat

环境变量:配置环境变量

vi /etc/profile 
// 添加
export MYCAT_HOME=/root/mycat

// 使环境变量生效
source /etc/profile

读写分离配置(主服务配置修改即可)

  • server.xml : 是Mycat服务器参数调整和用户授权的配置文件
  • schema.xml : 是逻辑库定义和表以及分片定义的配置文件
  • rule.xml : 是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件

server.xml 不进行任何修改,直接用<user>标签里schemas:TESTDB,这里的配置对应schema.xml中<schems>的name,可以更改name,那么这时就需要更改server.xml

        <!--
        <property name="processors">1</property>
        <property name="processorExecutor">32</property>
         -->
        <!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
                <property name="processorBufferPoolType">0</property>
                <!--默认是65535 64K 用于sql解析时最大文本长度 -->
                <!--<property name="maxStringLiteralLength">65535</property>-->
                <!--<property name="sequnceHandlerType">0</property>-->
                <!--<property name="backSocketNoDelay">1</property>-->
                <!--<property name="frontSocketNoDelay">1</property>-->
                <!--<property name="processorExecutor">16</property>-->
                <!--
                        <property name="serverPort">8066</property> <property name="managerPort">9066</property>
                        <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property>
                        <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
                <!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志-->
                <property name="handleDistributedTransactions">0</property>

                        <!--
                        off heap for merge/order/group/limit      1开启   0关闭
                -->
                <property name="useOffHeapForMerge">0</property>

                <!--
                        单位为m
                -->
        <property name="memoryPageSize">64k</property>

                <!--
                        单位为k
                -->
                <property name="spillsFileBufferSize">1k</property>

                <property name="useStreamOutput">0</property>

                <!--
                        单位为m
                -->
                <property name="systemReserveMemorySize">384m</property>


                <!--是否采用zookeeper协调切换  -->
                <property name="useZKSwitch">false</property>

                <!-- XA Recovery Log日志路径 -->
                <!--<property name="XARecoveryLogBaseDir">./</property>-->

                <!-- XA Recovery Log日志名称 -->
                <!--<property name="XARecoveryLogBaseName">tmlog</property>-->
                <!--如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接-->
                <property name="strictTxIsolation">false</property>

                <property name="useZKSwitch">true</property>

        </system>

        <!-- 全局SQL防火墙设置 -->
        <!--白名单可以使用通配符%或着*-->
        <!--例如<host host="127.0.0.*" user="root"/>-->
        <!--例如<host host="127.0.*" user="root"/>-->
        <!--例如<host host="127.*" user="root"/>-->
        <!--例如<host host="1*7.*" user="root"/>-->
        <!--这些配置情况下对于127.0.0.1都能以root账户登录-->
        <!--
        <firewall>
           <whitehost>
              <host host="1*7.0.0.*" user="root"/>
           </whitehost>
       <blacklist check="false">
       </blacklist>
        </firewall>
        -->

        <user name="root" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">TESTDB</property>

                <!-- 表级 DML 权限设置 -->
                <!--
                <privileges check="false">
                        <schema name="TESTDB" dml="0110" >
                                <table name="tb01" dml="0000"></table>
                                <table name="tb02" dml="1111"></table>
                        </schema>
                </privileges>
                 -->
        </user>

        <user name="user">
                <property name="password">user</property>
                <property name="schemas">TESTDB</property>
                <property name="readOnly">true</property>
        </user>

</mycat:server>

schema.xml配置,多余的配置可以删除,需要的时候在进行配置。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                /> -->
        <dataNode name="dn1" dataHost="localhost1" database="hikktn_db" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.135.20:3307" user="root"
                                   password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="192.168.135.21:3307" user="root" password="123456" />
                </writeHost>
        </dataHost>
</mycat:schema>

启动mycat

// 进入bin目录
[root@localhost]# cd /root/mycat/bin

// 执行启动命令
[root@localhost bin]# ./mycat start

查看:检测端口监听状况,Mycat的端口号是8066

[root@localhost bin]# netstat -ant|grep 8066

tcp6       0      0 :::8066                 :::*                    LISTEN
 

做完这些配置后,发现mysql的主从复制出现问题,只能删除主从复制。

192.168.135.20 主服务器

[root@localhost mycat]#  docker exec -it 3de8e50705e9 /bin/bash
root@3de8e50705e9:/# mysql -uroot -p123456

进入mysql中删除用户

DROP USER 'hikktn'@'%';

192.168.135.21 从服务器

删除主从连接

mysql>  stop slave;
Query OK, 0 rows affected (0.01 sec)

mysql> reset slave all;
Query OK, 0 rows affected (0.03 sec)

mysql> show slave status\G
Empty set (0.00 sec)

重新建立连接
change master to master_host='192.168.135.20',master_port=3307,master_user='hikktn',master_password='hikktn',master_log_file='mysql-bin.000003',master_log_pos=1635;
此时,

             Slave_IO_Running: No
            Slave_SQL_Running: No
会变成这样,按照下面操作。

mysql> set global server_id=2;
Query OK, 0 rows affected (0.00 sec)

mysql>  show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+
1 row in set (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.04 sec)

mysql> show slave status\G
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

测试

收获:大概就是主从复制,其实就是备份数据库,防止出现宕机,数据无法恢复。而读写分离大概就是设置两台主从服务器,最大限度的使用,单独进行管理,读取的时候直接从服务器中取出,修改新增的情况,就主服务器中写入。这样更好的增加系统维护性,极大的减少了CPU的消耗。

当我们操作mycat中间件时,mycat无法提供数据表的查看,只能进行数据表的增加和修改操作,而读取数据需要去从服务器中查看,当然新增的数据,因为有主从复制,主从服务器都会有同样的数据。

我们在mycat中间件运行下面的命令

-- 创建学生表
CREATE TABLE student(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10)
);
-- 查询学生表
SELECT * FROM student;

-- 添加两条记录
INSERT INTO student VALUES (NULL,'张三'),(NULL,'李四');

主服务器 192.168.135.20

-- 主服务器:查询学生表,可以看到数据
SELECT * FROM student;

从服务器 192.168.135.21

-- 从服务器:查询学生表,可以看到数据(因为有主从复制)
SELECT * FROM student;

分库分表

分库分表的概念

  • 水平拆分:根据表的数据逻辑关系,将同一表中的数据按照某种条件,拆分到多台数据库服务器上,也叫做横向拆分。例如:一张1000万的大表,按照一模一样的结构,拆分成4个250万的小表,分别保存到4个数据库中。
  • 垂直拆分:根据业务的维度,将不同的表切分到不同的数据库之上,也叫做纵向拆分。例如:所有的订单都保存到订单库中,所有的用户都保存到用户库中,同类型的表保存在同一库,不同的表分散在不同的库中。

水平切分

优点:  不存在单库大数据,高并发的性能瓶颈。

            对应用透明,应用端改造较少。      

              按照合理拆分规则拆分,join操作基本避免跨库。

            提高了系统的稳定性跟负载能力。

缺点:  拆分规则难以抽象。

             分片事务一致性难以解决。

             数据多次扩展难度跟维护量极大。

             跨库join性能较差。

垂直拆分

优点:  --拆分后业务清晰,拆分规则明确。

             --系统之间整合或扩展容易。 

             --数据维护简单。

缺点:  --部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。

             --受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。

             --事务处理复杂。

水平拆分配置

  • 在mycat/conf/sequence_conf.properties文件中: GLOBAL.MINDI=10000最小值 GLOBAL.MAXID=20000最大值,建议修改到9999999999

  • 1:数据库方式

    分库分表中保证全局主键自增唯一,但是需要执行mycat函数,配置sequence_db_conf.properties

  • 2:时间戳方式

    mycat实现的时间戳,建议varchar类型,要注意id的长度

server.xml

<!-- 修改主键的方式 -->
<property name="sequnceHandlerType">0</property>

sequence_db_conf.properties

#default global sequence
GLOBAL.HISIDS=      # 可以自定义关键字
GLOBAL.MINID=10001  # 最小值
GLOBAL.MAXID=20000  # 最大值
GLOBAL.CURID=10000

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="HEIMADB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="product" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long"/>
	</schema>
	
	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost1" database="db2" />
	<dataNode name="dn3" dataHost="localhost1" database="db3" />
	
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- write -->
		<writeHost host="hostM1" url="localhost:3306" user="root"
				   password="itheima">
		<!-- read -->
		<readHost host="hostS1" url="192.168.203.135:3306" user="root" password="itheima" />
		</writeHost>
	</dataHost>
	
</mycat:schema>

rule.xml

<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		<!-- 数据库的数量 -->
		<property name="count">3</property>
</function>

重启mycat服务

[root@localhost bin]# ./mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@localhost bin]# ./mycat status
Mycat-server is running (22668).
 

-- 创建product表
CREATE TABLE product(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(50),
	price INT
);

-- 添加6条数据
INSERT INTO product(id,NAME,price) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'苹果手机',6999);
INSERT INTO product(id,NAME,price) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'华为手机',5999); 
INSERT INTO product(id,NAME,price) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'三星手机',4999); 
INSERT INTO product(id,NAME,price) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'小米手机',3999); 
INSERT INTO product(id,NAME,price) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'中兴手机',2999); 
INSERT INTO product(id,NAME,price) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'OOPO手机',1999); 

-- 查询product表
SELECT * FROM product; 

垂直拆分配置 

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="HEIMADB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="product" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long"/>
		
		<!-- 动物类数据表 -->
		<table name="dog" primaryKey="id" autoIncrement="true" dataNode="dn4" />
		<table name="cat" primaryKey="id" autoIncrement="true" dataNode="dn4" />
    
       <!-- 水果类数据表 -->
		<table name="apple" primaryKey="id" autoIncrement="true" dataNode="dn5" />
		<table name="banana" primaryKey="id" autoIncrement="true" dataNode="dn5" />
	</schema>
	
	<dataNode name="dn1" dataHost="localhost1" database="db1" />
	<dataNode name="dn2" dataHost="localhost1" database="db2" />
	<dataNode name="dn3" dataHost="localhost1" database="db3" />
	
	<dataNode name="dn4" dataHost="localhost1" database="db4" />
	<dataNode name="dn5" dataHost="localhost1" database="db5" />
	
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- write -->
		<writeHost host="hostM1" url="localhost:3306" user="root"
				   password="itheima">
		<!-- read -->
		<readHost host="hostS1" url="192.168.203.135:3306" user="root" password="itheima" />
		</writeHost>
	</dataHost>
	
</mycat:schema>

mycat 

-- 创建dog表
CREATE TABLE dog(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10)
);
-- 添加数据
INSERT INTO dog(id,NAME) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'哈士奇');
-- 查询dog表
SELECT * FROM dog;


-- 创建cat表
CREATE TABLE cat(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10)
);
-- 添加数据
INSERT INTO cat(id,NAME) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'波斯猫');
-- 查询cat表
SELECT * FROM cat;



-- 创建apple表
CREATE TABLE apple(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10)
);
-- 添加数据
INSERT INTO apple(id,NAME) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'红富士');
-- 查询apple表
SELECT * FROM apple;


-- 创建banana表
CREATE TABLE banana(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10)
);
-- 添加数据
INSERT INTO banana(id,NAME) VALUES (NEXT VALUE FOR MYCATSEQ_GLOBAL,'香蕉');
-- 查询banana表
SELECT * FROM banana;

主从服务器查询

-- 查询dog表
SELECT * FROM dog;
-- 查询cat表
SELECT * FROM cat;


-- 查询apple表
SELECT * FROM apple;
-- 查询banana表
SELECT * FROM banana;

猜你喜欢

转载自blog.csdn.net/qq_41520636/article/details/114882554