OneProxy实现MySQL读写分离

作者: cmazxiaoma | 来源:发表于2018-11-01 10:44 被阅读89次

    系列文章:
    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%";
    SHOW PROCESSLIST;
    SHOW GLOBAL VARIABLES LIKE '%innodb_log_files_in_group%'
    SHOW GLOBAL VARIABLES LIKE '%innodb_log_group_home_dir%'
    SHOW GLOBAL VARIABLES LIKE '%innodb_log_buffer_size%'
    SHOW GLOBAL VARIABLES LIKE '%max_allowed_packet%'
    SHOW GLOBAL VARIABLES LIKE '%slave_parallel%'
    SHOW GLOBAL VARIABLES LIKE '%max_allowed_packet%'
    

    相关文章

      网友评论

      本文标题:OneProxy实现MySQL读写分离

      本文链接:https://www.haomeiwen.com/subject/iccbtqtx.html