zoukankan      html  css  js  c++  java
  • MySQL读写分离

    MySQL读写分离的概述

    Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过。但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面。 因此,一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy/Amoeba)来提升数据库的并发负载能力 这样的方案来进行部署与实施的。

    读写分离工作原理:
    这里写图片描述
    基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

    数据内部交换过程:
    这里写图片描述
    为什么要读写分离:
    面对越来越大的访问压力,单台的服务器的性能成为瓶颈,需要分担负载
    1、主从只负责各自的写和读,极大程度的缓解X锁和S锁争用
    2、从库可配置myisam引擎,提升查询性能以及节约系统开销
    3、增加冗余,提高可用性
    实现读写分离的方式
    一般有两种方式实现
    1.应用程序层实现,网站的程序实现
    这里写图片描述
    应用程序层实现指的是在应用程序内部及连接器中实现读写分离
    优点
    A:应用程序内部实现读写分离,安装既可以使用
    B:减少一定部署难度
    C:访问压力在一定级别以下,性能很好
    缺点:
    A:架构一旦调整,代码要跟着变
    B:难以实现高级应用,如自动分库,分表
    C:无法适用大型应用场景
    2.中间件层实现
    中间件层实现是指在外部中间件程序实现读写分离
    常见的中间件程序:
    Mysql-proxy amoeba Atlas (360) Cobar(Alibaba) TDDL(Taobao)
    优点:
    A:架构设计更灵活
    B:可以在程序上实现一些高级控制,如:透明化水平拆分,failover,监控
    C:可以依靠些技术手段提高mysql性能,
    D:对业务代码的影响小,同时也安全
    缺点:
    需要一定的开发运维团队的支持

    MySQL-Proxy概述

    MySQL Proxy是一个处于你的client端和MySQL
    server端之间的简单程序,它可以监测、分析或改变它们的通信。它使用灵活,没有限制,常见的用途包括:负载平衡,故障、查询分析,查询过滤和修改等等。
    MySQL Proxy就是这么一个中间层代理,简单的说,MySQL
    Proxy就是一个连接池,负责将前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负载平衡。对于应用来说,MySQL
    Proxy是完全透明的,应用则只需要连接到MySQL
    Proxy的监听端口即可。当然,这样proxy机器可能成为单点失效,但完全可以使用多个proxy机器做为冗余,在应用服务器的连接池配置中配置到多个proxy的连接参数即可。
    MySQL
    Proxy更强大的一项功能是实现“读写分离”,基本原理是让主数据库处理事务性查询,让从库处理SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群中的从库。

    下载: mysql-proxy
    http://dev.mysql.com/downloads/mysql-proxy/

    端口: mysql-proxy 默认端口:4040
    部署mysql-proxy实现读写分离

    实验环境:
    mysql-proxy服务端: test62 IP:192.168.1.62
    mysql服务器(主,负责写)服务端:test63 IP:192.168.1.63
    mysql服务器(从,负责读)客户端:test64 IP:192.168.1.64
    部署mysql-proxy服务端test62:
    安装前需要系统支持LUA语言环境:
    [root@test62 ~]# yum install lua
    安装mysql-proxy:
    推荐采用已经编译好的二进制版本,因为采用源码包进行编译时,最新版的MySQL-Proxy对automake,glib以及libevent的版本都有很高的要求,而这些软件包都是系统的基础套件,不建议强行进行更新。
    并且这些已经编译好的二进制版本在解压后都在统一的目录内,因此建议选择以下版本:

    [root@test62 ~]# wget http://dev.mysql.com/get/Downloads/MySQL-Proxy/mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz
    [root@test62 ~]# tar -xf mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz -C /usr/local/
    [root@test62 local]# mv mysql-proxy-0.8.5-linux-el6-x86-64bit/ mysql-proxy
    修改系统环境变量:
    [root@test62 local]# vim /etc/profile
    export PATH=/usr/local/mysql-proxy/bin/:/usr/local/mysql/bin:$PATH
    [root@test62 local]# source !$
    mysql-proxy 脚本配置文件位置:
    [root@test62 ~]# ls /usr/local/mysql-proxy/share/doc/mysql-proxy/

    修改配置文件实现读写分离:

    [root@test62 ~]# vim /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
    修改
    40                 min_idle_connections = 4,
     41                 max_idle_connections = 8,
    为
    
    #修改默认连接,进行快速测试,默认最小4个以上的客户端连接才会实现读写分离,最大链接数为8。 
    注:为了验证试验效果将他改成1 .就是当有一个链接的时候,就实现读写分离的功能。为了清晰的看到读写分离的效果,需要暂时关闭MySQL主从复制功能。

    test63上创建数据库和表,用于实现写操作:

    [root@test63 ~]# mysql -usystem -p123456
    mysql> create database db;
    mysql> use db;
    mysql> create table test(id int);
    mysql> insert into test values(6363);
    mysql> grant all on db.* to user1@'%'  identified by '123456' ; 
    test64上创建数据库和表,用于实现读操作:
    [root@test64 ~]# mysql -usystem -p123456
    mysql> create database db;
    mysql> use db;
    mysql> create table test(id int);
    mysql> insert into test values(6464);
    mysql> grant all on db.* to user1@'%'  identified by '123456' ; 
    启动服务mysql-proxy服务
    [root@test62 ~]# mysql-proxy --proxy-read-only-backend-addresses=192.168.1.64:3306 --proxy-backend-addresses=192.168.1.63:3306 --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua &
    
    参数说明:
    --proxy-read-only-backend-addresses=192.168.1.64:3306  # 定义后端只读服务器 
    --proxy-backend-addresses=192.168.1.63:3306   #定义后端mysql主服务器地址,指定mysql写主服务器的端口
    --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua &  #指定lua脚本,在这里,使用的是rw-splitting脚本,用于读写分离
    当有多个只读服务器时,可以写多个以下参数:
    --proxy-read-only-backend-addresses=192.168.1.64:3306  # 定义后端只读服务器
    --proxy-read-only-backend-addresses=192.168.1.65:3306  # 定义后端只读服务器
    #--proxy-address=192.168.1.62:3307 指定mysql proxy的监听端口,默认为:4040

    完整的参数可以运行以下命令查看:

    [root@test62 ~]# mysql-proxy --help-all

    查看proxy是否启动:

    [root@test62 ~]# lsof -i :4040
    COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    mysql-pro 3144 root    9u  IPv4  19597      0t0  TCP *:yo-main (LISTEN)

    测试读写分离
    测试写操作:

    [root@test62 ~]# mysql -uuser1 -p123456 -P4040 -h192.168.1.62
    mysql> use db;
    mysql> insert into test values(636363);  回车,没有报错
    
    ##看不到64数据,可以看到刚写入的数据,说明写操作成功。 因为是第一个客端连接,还没有启动读写分离,所以select读时,没有看到“6464”数据,而是看到主上“6363“数据。
    接下来,多打开几个客户端测试一下读。注:第一个链接,一定是走backend 主mysql服务器的。
    测试读操作:
    [root@test63 ~]# mysql -uuser1 -p123456 -P4040 -h 192.168.1.62
    mysql> use db;
    mysql> insert into test values(636363);
    [root@test64 ~]# mysql -uuser1 -p123456 -P4040 -h 192.168.1.62
    mysql> select * from db.test;
    我们再用62登陆,查看
    [root@test62 ~]# mysql -uuser1 -p123456 -P4040 -h 192.168.1.62
    mysql> select * from db.test;
    #这说明读写分离测试成功。 但是数据还没有保持同步。 保持数据同步,可以通过mysql主从来实现。
    # 查看客户端连接状态:
    mysql> show processlist;

    部署mysql主从并实现读写分离
    在之前的基础上配置主从
    配置test63为master

    [root@test63 ~]# vim /etc/my.cnf
    log-bin=mysql-bin-master
    binlog_format=row
    server-id       = 1
    再修改库授权:
    [root@test63 ~]# mysql -usystem -p123456
    mysql> grant all on *.* to user2@'%' identified by '123456';
    mysql> use db;
    mysql> drop table test;
    [root@test63 ~]# service mysqld restart

    配置test64为slave

    [root@test64 ~]# vim /etc/my.cnf
    server-id       = 2
    [root@test64 ~]# service mysqld restart
    [root@test64 ~]# mysql -usystem -p123456
    mysql> change master to master_host='192.168.1.63',master_user='user2',master_password='123456';
    mysql> use db;
    mysql> drop table test;
    mysql> start slave;
    mysql> show slave statusG
    
    主从同步测试:
    1:Mysql主数据库test63插入数据:
    mysql> use db;
    mysql> create table admin(id int);
    mysql> insert into admin values(63);
    2:Mysql从数据库test64查看同步的数据:
    
    同步后,测试使用mysql-proxy 能否读到同样的数据。
    在test62上测试
    [root@test62 ~]# mysql -uuser2 -p123456 -P4040 -h192.168.1.62
    
    #可以查看到admin中的63记录,说明mysql+proxy+主从读写分离成功。
    插入数据测试:
    mysql> use db;
    mysql> insert into admin values(64);
    
    在test63,test64上查看都有
    当我们slave挂掉后咋样呢
    模拟故障:
    [root@test64 ~]# service mysqld stop
    在test62上测试读写
    mysql> insert into admin values(65);
    
    Xuegod63上查看连接状态,确认关闭slave后,读写都是访问test63
    
    总结:当停止掉 slave 数据库,proxy 的查询就会转移到 master 上,当把 slave 启动后,proxy 依然在读 master,当有新的链接进来的时候才会重新去读取 slave 的数据。有时可能需要重启下 mysql-proxy。
    如果主数据库挂了:
    主从也没了,在test62上只能查看数据
    [root@test62 ~]# mysql -uuser1 -p123456 -P4040 -h192.168.1.62
    
  • 相关阅读:
    textArea打印时,内容不显示
    自定义Metadata验证属性
    C# 扩展类与分布类
    JSON基础 JS操作JSON总结
    如何查看别人公众号的粉丝量
    Powerdesigner逆向工程从sql server数据库生成pdm
    springMVC中前台ajax传json数据后台controller接受对象为null
    Mybatis报错: Invalid bound statement (not found)
    Mysql批量插入数据性能问题
    java中String编码转换 UTF-8转GBK
  • 原文地址:https://www.cnblogs.com/flyhgx/p/6367966.html
Copyright © 2011-2022 走看看