OneProxy实现MySQL读写分离

系列文章: 1.MySQL主从复制 2.OneProxy实现MySQL读写分离

读写分离方案,其实我们可以通过配置动态数据源来实现。也可以通过一些中间件来实现,比如OneProxy,MaxScale,MysqlProxy来实现。下面我们要讲的是如何通过OneProxy来实现MySQL的读写分离。

从OneProxy的官网上,我们能看到OneProxy的介绍:

MySQL的逻辑复制技术可轻松构建多个数据副本来提供服务,并可以消除数据库单点,但需要应用作出相应的代码调整,才能充分利用它的优势。而网络交换机/路由器在理解TCP协议和目的IP地址的情况下,可以帮助人们轻松地组建大大小小的网络, OneProxy for MySQL在理解MySQL通信协议和SQL语句分析的基础上,可以帮助轻松组建数据库集群,避免代价昂贵的应用代码调整。

OneProxy for MySQL可以复用不同应用到后端数据库的连接,有效降低数据库的并发连接数;可以即时踢除不可用的节点,将应用请求转发到其他可用节点,保证业务服务的稳定性。 可透明地将查询语句分发到多个MySQL备库执行,用读写分离方案支持上千万的并发访问;也可以根据SQL语句中的值进行分库分表路由, 均匀分散到多个MySQL主库上,以支持每秒上百万个小事务的并发执行;可实时透明地分析流量数据,统计SQL和事务的运行时间,分析事务的结构,得到各种不同维度的实时性能报告; 还可以进行流理QoS控制,作为数据库防火墙抵挡SQL注入式攻击;根据分片的SQL并行执行,解决了大数据量下的汇总统计性能问题;跨多分片的结果集合并, 极大地简化了应用程序的开发工作量。

更多介绍可以看Oneproxy介绍

首先,搭好Mysql的主从复制结构: master 192.168.10.21 slave 192.168.10.6

1.在master和slave中创建test用户并且给其分配权限。

grant all privileges on *.* to test@'%' identified by 'test'

2.修改demo.sh

image.png

3.给demo.sh赋权限

chmod 777 demo.sh

4.修改启动的脚本,将ONEPROXY_HOME设置你安装的oneproxy的路径

vim oneproxy.service

image.png

5.调用mysqlpwd进行密码加密

[root@localhost oneproxy]# ls
bin   demo.sh  oneproxy.service  sql            testautocommit.sql  trantest.sql
conf  log      README            testadmin.sql  testproxy.sql
[root@localhost oneproxy]# cd bin
[root@localhost bin]# ls
mysqlpwd  oneproxy
[root@localhost bin]# ./mysqlpwd test
1378F6CC3A8E8A43CA388193FBED5405982FBBD3

6.配置oneproxy

[oneproxy]
keepalive = 1
event-threads = 4
log-file = log/oneproxy.log
pid-file = log/oneproxy.pid
lck-file = log/oneproxy.lck
proxy-auto-readonly = 1
proxy-forward-clientip = 1
proxy-trans-debug = 1
mysql-version = 5.7.17
admin-address = 0.0.0.0:4041
proxy-address = 0.0.0.0:3307
proxy-master-addresses = 192.168.10.21:3306@oneproxy
proxy-slave-addresses = 192.168.10.6:3306@oneproxy
proxy-user-list.1 = oneproxy:test/1378F6CC3A8E8A43CA388193FBED5405982FBBD3@rap_test
proxy-part-template = conf/template.txt
proxy-part-tables = conf/part.txt
proxy-charset = utf8mb4_general_ci
proxy-secure-client = 127.0.0.1
proxy-license = A2FF461456A67F28,D2F6A5AD70C9042D
proxy-httpserver = 0.0.0.0:8080
proxy-httpauth = admin:admin
proxy-httptitle = oneProxy[cmazxiaoma]
proxy-group-security = oneproxy:0
proxy-group-policy = oneproxy:2
proxy-sequence-group = oneproxy
proxy-sequence.1 = seq1
network-blocking= 0

配置参数说明:

[oneproxy]
keepalive = 1
event-threads = 4
#指定日志文件路径
log-file = log/oneproxy.log
#指定PID文件路径
pid-file = log/oneproxy.pid
#指定LCK文件路径
lck-file = log/oneproxy.lck
proxy-auto-readonly = 1
proxy-forward-clientip = 1
proxy-trans-debug = 1
#MySQL服务版本
mysql-version = 5.7.17
admin-address = 0.0.0.0:4041
proxy-address = 0.0.0.0:3307
#指定主服务器的IP地址  格式:IP地址:端口@oneproxy组
proxy-master-addresses = 192.168.10.21:3306@oneproxy
#指定从服务器的IP地址  格式:IP地址:端口@oneproxy组
proxy-slave-addresses = 192.168.10.6:3306@oneproxy
#用户列表   格式:用户名/密文密码@数据库名称
proxy-user-list.1 = oneproxy:test/1378F6CC3A8E8A43CA388193FBED5405982FBBD3@rap_test
proxy-part-template = conf/template.txt
#指定分表分库的配置文件
proxy-part-tables = conf/part.txt
#指定数据库字符集
proxy-charset = utf8mb4_general_ci
proxy-secure-client = 127.0.0.1
proxy-license = A2FF461456A67F28,D2F6A5AD70C9042D
指定Web服务的监听端口
proxy-httpserver = 0.0.0.0:8080
#指定Web访问认证信息   格式:用户名:密码
proxy-httpauth = admin:admin
#指定Web页面名称
proxy-httptitle = oneProxy[cmazxiaoma]
#设定安全级别,0默认值,1禁止DDL,2禁止不带条件的查询语句,3只允许SELECT
proxy-group-security = oneproxy:0
#设定预定义策略
#0代表由Lua Script来决定 1代表Read Failover 2代表主节点不参与读 3代表双主结构 4代表主节点参与读操作 5代表随机读取
proxy-group-policy = oneproxy:2
proxy-sequence-group = oneproxy
proxy-sequence.1 = seq1
network-blocking = 0

关于proxy-group-policy这个参数我要重点提一下, 它是用来指定MySQL实例的流量切换和分担的策略,具体如下:

  • master_only:master进行读写操作。
  • read_failover:写流量同“master-only”,针对读流量,如果Master节点可用则从Master节点访问,如果Master节点不可用,则从Slave节点访问。此策略常用于关键配置数据的高可用。
  • read_slave:写流量同“master-only”,针对读流量,先从Slave节点读取,如果没有Slave可用,则从Master节点访问。此策略即一主多备情况下的读写分离策略。
  • read_balance:写流量同“master-only”,针对读流量,先从任一可用节点读取,包括Master和Slave类型。此策略即一主一备情况下的读写分离策略。
  • big_slave:写流量和简单SQL查询流量同“master-only”,针对复杂的SQL语句,先从Slave节点读取,如果没有Slave可用,则从Master节点访问。此策略为一主多备情况下的复杂SQL语句读写分离。
  • big_balance:写流量和简单SQL查询同“master-only”,针对复杂的SQL语句,先从任一可用节点读取,包括Master和Slave类型。此策略为一主一备情况下的复杂SQL语句读写分离。
  • write_failover:写流量同“master-only”,但通常配有多个Master类型节点,可以预防写操作失败;针对读流量,先从任一可用节点读取。
  • write_balance:针对每次写操作,任挑一台Master节点提供服务;针对读流量,先从任一可用节点读取。

如果配置有问题的话是启动不了的,而且oneproxy.log也不会输出任何异常。

7.启动oneproxy,可以看到3307,8080,4041端口信息,说明启动成功了。

[root@localhost oneproxy]# ./demo.sh
[root@localhost oneproxy]# netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:3307            0.0.0.0:*               LISTEN      5693/oneproxy       
tcp        0      0 0.0.0.0:9100            0.0.0.0:*               LISTEN      2115/grunt          
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      5693/oneproxy       
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      979/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1193/master         
tcp        0      0 0.0.0.0:4041            0.0.0.0:*               LISTEN      5693/oneproxy       
tcp6       0      0 :::22                   :::*                    LISTEN      979/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      1193/master         
tcp6       0      0 :::3306                 :::*                    LISTEN      4739/mysqld         
[root@localhost oneproxy]# 

8.我们可以进入OneProxy的admin模式。默认账号是admin,密码是OneProxy

image.png

  1. 查看读写分离状态。
mysql> list backend\g
+------+--------------------+------+--------+--------+----------+----------+---------+------------------+
| INDX | ADDRESS            | TYPE | STATUS | MARKUP | REQUESTS | GROUP    | Seconds | SyncTime         |
+------+--------------------+------+--------+--------+----------+----------+---------+------------------+
|    2 | 192.168.10.21:3306 | RW   | UP     |      1 |        0 | oneproxy |   22639 | 1540957748819753 |
|    3 | 192.168.10.6:3306  | RW   | UP     |      1 |        0 | oneproxy |       0 | 1540980388023589 |
+------+--------------------+------+--------+--------+----------+----------+---------+------------------+
2 rows in set (0.00 sec)

mysql> list pool\g
+------+--------------------+------+--------+------+---------+---------+----------+
| INDX | ADDRESS            | USER | LENGTH | SIZE | MINIDLE | MAXIDLE | REQUESTS |
+------+--------------------+------+--------+------+---------+---------+----------+
|    2 | 192.168.10.21:3306 | test |     20 |   20 |      20 |     200 |        0 |
|    3 | 192.168.10.6:3306  | test |     20 |   20 |      20 |     200 |       40 |
+------+--------------------+------+--------+------+---------+---------+----------+
2 rows in set (0.00 sec)

mysql> 

10.通过访问8080端口,我们可以通过Web界面可视化数据,更好的观察读写分离状态。

image.png

11.访问3307端口,也就是oneProxy代理的地址。rap_test库和date_demo是我们之前测试MySQL主从复制建立的数据库和表。我们可以看到多了一个oneproxy_replication_timestamp。在我们的master和slave中的rap_test库也可以看到这张表。这张表用来检测读节点的复制延迟。

image.png

master.png

slave.png

12.我们通过web界面和oneProxy.log发现延迟了。也就是oneproxy_replication_timestamp里面的时间戳不一致。

image.png

image.png

13.我们进入3307端口,看一下master和slave的状态。slave的状态是ok的。

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.10.21
                  Master_User: sync
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 178305
               Relay_Log_File: localhost-relay-bin.000002
                Relay_Log_Pos: 589
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 178305
              Relay_Log_Space: 800
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 21
                  Master_UUID: 67ccaaf1-e4b4-11e7-a07f-c8d3ffc0c026
             Master_Info_File: /usr/local/mysql/data/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

查看master的状态,我们发现OneProxy依赖的是master的mysql-bin.000001文件,而slave复制依赖的是master的mysql-bin.000002文件。

mysql> ^C
mysql> show master status\g
+------------------+-----------+--------------+------------------+-------------------+
| File             | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 129901019 |              |                  |                   |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql> 

14.我们在master上,查看master 的状态。发现master的binlog文件时mysql-bin.000002文件。

image.png

15.查看master的所有binlog文件

mysql> show binary logs\g
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       201 |
| mysql-bin.000002 |    178305 |
+------------------+-----------+
2 rows in set (0.00 sec)

16.查看binlog文件中的事件

mysql> show binlog events in 'mysql-bin.000001'\g
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 |   4 | Format_desc    |        21 |         123 | Server ver: 5.7.17-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids |        21 |         154 |                                       |
| mysql-bin.000001 | 154 | Rotate         |        21 |         201 | mysql-bin.000002;pos=4                |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
3 rows in set (0.00 sec)
mysql> show binlog events in 'mysql-bin.000002' limit 10\g
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                       |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------+
| mysql-bin.000002 |   4 | Format_desc    |        21 |         123 | Server ver: 5.7.17-log, Binlog ver: 4                                      |
| mysql-bin.000002 | 123 | Previous_gtids |        21 |         154 |                                                                            |
| mysql-bin.000002 | 154 | Anonymous_Gtid |        21 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                       |
| mysql-bin.000002 | 219 | Query          |        21 |         353 | use `rap_master`; DROP TABLE `date_demo` /* generated by server */         |
| mysql-bin.000002 | 353 | Anonymous_Gtid |        21 |         418 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                       |
| mysql-bin.000002 | 418 | Query          |        21 |         517 | drop database `rap_master`                                                 |
| mysql-bin.000002 | 517 | Anonymous_Gtid |        21 |         582 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                       |
| mysql-bin.000002 | 582 | Query          |        21 |         738 | create database `rap_test`character set utf8mb4 collate utf8mb4_general_ci |
| mysql-bin.000002 | 738 | Anonymous_Gtid |        21 |         803 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                       |
| mysql-bin.000002 | 803 | Query          |        21 |         898 | drop database `rap_test`                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------+
10 rows in set (0.00 sec)

17.重置master的binlog

mysql> reset master\g
Query OK, 0 rows affected (0.82 sec)
mysql> show binary logs\g
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       154 |
+------------------+-----------+
1 row in set (0.00 sec)

mysql> 

18.重新配置slave

mysql> reset slave\g
Query OK, 0 rows affected (0.01 sec)

mysql> change master to
    -> master_host="192.168.10.21",
    -> master_user="sync",
    -> master_password="sync",
    -> master_log_file="mysql-bin.000001",
    -> master_log_pos=154\g
Query OK, 0 rows affected, 2 warnings (0.10 sec)

19.重启oneproxy,通过web界面查看还是存在延迟。我们还忽略了一个点,master地址竟然是192.168.10.6。master地址应该是192.168.10.21。

image.png

20.我们连接192.168.10.6:3306,查看是否配置过master。难怪,oneproxy显示master的binlog一直是mysql-bin.000001(这个binlog是slave开启master模式所产生的binglog)。slave竟然是slave还是master,雌雄同体,WTF。

mysql> show master status\g
+------------------+-----------+--------------+------------------+-------------------+
| File             | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 138280148 |              |                  |                   |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql> 

21.感觉这是oneproxy的一个bug,我重启oneProxy,再通过web界面查看,一切正常。

image.png

22.我们连接OneProxy的3307端,调用select @@server_id语句,返回的是6,证明查询语句是在slave端执行。因为之前配置主从复制的时候,master的server_id是21,slave的server_id是6.

mysql> show master status\g
+------------------+-----------+--------------+------------------+-------------------+
| File             | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 141160929 |              |                  |                   |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql> select @@server_id\g
+-------------+
| @@server_id |
+-------------+
|           6 |
+-------------+
1 row in set (0.00 sec)

mysql> 

23.我们在3307端口插入2条记录。然后我们在master和slave查看是否成功插入这2条记录。

mysql> select * from oneproxy_replication_timestamp \g
+--------------------------+------------------+
| proxy_uuid               | proxy_stamp      |
+--------------------------+------------------+
| AYCE-ZUSM-OIIN-UYAW-CZEG | 1541038193999142 |
+--------------------------+------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO date_demo VALUES(NULL,NOW(),NOW(),NOW(),NOW(),NOW())\g
Query OK, 1 row affected, 1 warning (1.06 sec)

mysql> INSERT INTO date_demo VALUES(NULL,NOW(),NOW(),NOW(),NOW(),NOW())\g
Query OK, 1 row affected, 1 warning (0.46 sec)

mysql> select * from date_demo\g
+----+----------+---------------------+---------------------+------------+----------------+
| id | time     | timestamp           | datetime            | date       | int_date       |
+----+----------+---------------------+---------------------+------------+----------------+
|  1 | 10:18:07 | 2018-10-30 10:18:07 | 2018-10-30 10:18:07 | 2018-10-30 | 20181030101807 |
|  2 | 11:18:57 | 2018-10-30 11:18:57 | 2018-10-30 11:18:57 | 2018-10-30 | 20181030111857 |
|  3 | 18:45:40 | 2018-10-31 18:45:40 | 2018-10-31 18:45:40 | 2018-10-31 | 20181031184540 |
|  4 | 10:10:08 | 2018-11-01 10:10:08 | 2018-11-01 10:10:08 | 2018-11-01 | 20181101101008 |
|  5 | 10:10:36 | 2018-11-01 10:10:36 | 2018-11-01 10:10:36 | 2018-11-01 | 20181101101036 |
+----+----------+---------------------+---------------------+------------+----------------+
5 rows in set (0.00 sec)

master.png

slave.png

24.我们可以用OneProxy Web界面查看SQLS、TableS、DMLS可视化数据统计。可以发现date_demo执行Insert语句有3次。

image.png

image.png

25.将binlog转换成SQL语句,我们在output.sql可以看到我们刚才插入的sql语句。

#mysqlbinlog -d rap_test mysql-bin.000001 -r output.sql

image.png

image.png

26.最后记录一下MySQL性能监控的一些参数。

SHOW GLOBAL VARIABLES LIKE '%max_connections%'
SHOW GLOBAL STATUS LIKE '%Threads_created%'
SHOW GLOBAL STATUS LIKE '%threads_running%'
SHOW GLOBAL VARIABLES LIKE 'innodb_file_per_table'
SHOW GLOBAL VARIABLES LIKE 'show_query_log'
SHOW VARIABLES LIKE '%partition%'
SHOW VARIABLES LIKE "%innodb_buffer_pool_size%";

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

Oracle RAC基本维护指令

所有实例和服务的状态 $ srvctl status database -d orcl Instance orcl1 is running on node l...

22770
来自专栏散尽浮华

mysqldump数据导出问题和客户端授权后连接失败问题

1,使用mysqldump时报错(1064),这个是因为mysqldump版本太低与当前数据库版本不一致导致的。 mysqldump: Couldn't exe...

25590
来自专栏性能与架构

MySQL 5.7 多主一从的复制结构

多源复制的作用 MySQL 5.7.6 开始,添加了一个新特性:多源复制 Multi-Source Replication 可以让你同时从多个master中并行...

44990
来自专栏数据和云

你不可不看的 Oracle RAC 日常基本维护命令

$ srvctl status instance -d orcl -i orcl2

12640
来自专栏乐沙弥的世界

使用pt-table-checksum校验MySQL主从复制

pt-table-checksum是一个基于MySQL数据库主从架构在线数据一致性校验工具。其工作原理在主库上运行, 通过对同步的表在主从段执行checksum...

25320
来自专栏数据和云

【循序渐进Oracle】Oracle的物理备份(上)

编辑手记:备份重于一切,我们必需知道,系统总是要崩溃的,没有有效的备份只是等哪一天死!今天你备份了吗?我们一起来回顾Oracle的物理备份,本文摘自《循序渐进O...

35680
来自专栏乐沙弥的世界

只读表空间的备份与恢复

--====================== --  只读表空间的备份与恢复 --====================== 一、只读表空间的特性...

9820
来自专栏乐沙弥的世界

Percona XtraDB Cluster 5.7 event是否重复执行?

最近的某个业务系统即将由单点转入PXC集群,碰到的问题是mysql单实例上运行的那些event,再转入集群之后,该如何执行呢?带着这个问题,做了个实验,并给出相...

8710
来自专栏Java学习123

powerdesigner 15 如何导出sql schema

30450
来自专栏YG小书屋

mysql主从配置与数据移植

22150

扫码关注云+社区

领取腾讯云代金券