bestvivi

bestvivi 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

bestvivi 发布了文章 · 2015-09-09

MySQL主主复制+LVS+Keepalived实现MySQL高可用性

MySQL复制能够保证数据的冗余的同时可以做读写分离来分担系统压力,如果是主主复制还可以很好的避免主节点的单点故障。但是MySQL主主复制存在一些问题无法满足我们的实际需要:未提供统一访问入口来实现负载均衡,如果其中master宕掉的话需要手动切换到另外一个master,而不能自动进行切换。

这篇文章下面要介绍如何通过LVS+Keepalived的方式来是实现MySQL的高可用性,同时解决以上问题。

Keepalived和LVS介绍

Keepalived是一个基于VRRP(虚拟路由冗余协议)可用来实现服务高可用性的软件方案,避免出现单点故障。Keepalived一般用来实现轻量级高可用性,且不需要共享存储,一般用于两个节点之间,常见有LVS+Keepalived、Nginx+Keepalived组合。

LVS(Linux Virtual Server)是一个高可用性虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。
LVS主要用于多服务器的负载均衡,作用于网络层。LVS构建的服务器集群系统中,前端的负载均衡层被称为Director Server;后端提供服务的服务器组层被称为Real Server。通过下图可以大致了解LVS的基础架构。
abc

LVS有三种工作模式,分别是DR(Direct Routing 直接路由)、TUN(Tunneling IP隧道)、NAT(Network Address Translation 网络地址转换)。其中TUN模式能够支持更多的Real Server,但需要所有服务器支持IP隧道协议;DR也可以支持相当的Real Server,但需要保证Director Server虚拟网卡与物理网卡在同一网段;NAT扩展性有限,无法支持更多的Real Server,因为所有的请求包和应答包都需要Director Server进行解析再生,影响效率。 同时,LVS负载均衡有10中调度算法,分别是rr、wrr、lc、wlc、lblc、lblcr、dh、sh、sed、nq

详细的LVS说明请参见 传送门

本文中将利用LVS实现MySQL的读写负载均衡,Keepalived避免节点出现单点故障。

LVS+Keepalived配置

环境准备

LVS1:192.168.1.2

LVS2:192.168.1.11

MySQL Server1:192.168.1.5

MySQL Server2:192.168.1.6

VIP:192.168.1.100

OS: CentOS 6.4

架构图

Keepalive安装

keepalived下载地址

需要安装以下软件包

# yum install -y kernel-devel openssl openssl-devel

解压keepalived到/usr/local/并进入目录执行配置编译

# ./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/kernels/2.6.32-431.5.1.el6.x86_64/
Keepalived configuration
------------------------
Keepalived version       : 1.2.13
Compiler                 : gcc
Compiler flags           : -g -O2
Extra Lib                : -lssl -lcrypto -lcrypt 
Use IPVS Framework       : Yes
IPVS sync daemon support : Yes
IPVS use libnl           : No
fwmark socket support    : Yes
Use VRRP Framework       : Yes
Use VRRP VMAC            : Yes
SNMP support             : No
SHA1 support             : No
Use Debug flags          : No

# make && make install

默认情况下keepalived启动时会去/etc/keepalived目录下找配置文件,将需要的配置文件拷贝到指定位置


# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/
# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
# cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
# chkconfig mysqld on
# chkconfig keepalived on

LVS安装

ipvsadm下载地址

需要安装以下软件包

# yum install -y libnl* popt*

查看是否加载lvs模块

# modprobe -l |grep ipvs

解压安装

# ln -s /usr/src/kernels/2.6.32-431.5.1.el6.x86_64/ /usr/src/linux
# tar -zxvf ipvsadm-1.26.tar.gz
# make && make install

LVS安装完成,查看当前LVS集群

# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port           Forward Weight ActiveConn InActConn

LVS+Keepalived配置

搭建MySQL主主复制

这里不再赘述,请参考MySQL复制

配置Keepalived

下面是LVS1节点(Keepalived主节点)上的Keepalived配置,LVS2类似

# vim /etc/keepalived/keepalived.conf    

! Configuration File for keepalived

global_defs {
   router_id LVS1
}

vrrp_instance VI_1 {
    state MASTER #指定instance初始状态,实际根据优先级决定.backup节点不一样
    interface eth0 #虚拟IP所在网
    virtual_router_id 51 #VRID,相同VRID为一个组,决定多播MAC地址
    priority 100 #优先级,另一台改为90.backup节点不一样
    advert_int 1  #检查间隔
    authentication {
        auth_type PASS  #认证方式,可以是pass或ha
        auth_pass 1111  #认证密码
    }
    virtual_ipaddress {
        192.168.1.100  #VIP
    }
}

virtual_server 192.168.1.100 3306 {
    delay_loop 6  #服务轮询的时间间隔
    lb_algo wrr  #加权轮询调度,LVS调度算法 rr|wrr|lc|wlc|lblc|sh|sh
    lb_kind DR   #LVS集群模式 NAT|DR|TUN,其中DR模式要求负载均衡器网卡必须有一块与物理网卡在同一个网段
    #nat_mask 255.255.255.0
    persistence_timeout 50  #会话保持时间
    protocol TCP  #健康检查协议

     ## Real Server设置,3306就是MySQL连接端口
    real_server 192.168.1.5 3306 {
        weight 3  ##权重
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 3306
        }
    }
    real_server 192.168.1.6 3306 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 3306
        }
    }
}

配置LVS

编写LVS启动脚本/etc/init.d/realserver

#!/bin/sh
VIP=192.168.1.100
. /etc/rc.d/init.d/functions

case "$1" in
# 禁用本地的ARP请求、绑定本地回环地址
start)
    /sbin/ifconfig lo down
    /sbin/ifconfig lo up
    echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
    echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
    /sbin/sysctl -p >/dev/null 2>&1
    /sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 up #在回环地址上绑定VIP,设定掩码,与Direct Server(自身)上的IP保持通信
    /sbin/route add -host $VIP dev lo:0
    echo "LVS-DR real server starts successfully.\n"
    ;;
stop)
    /sbin/ifconfig lo:0 down
    /sbin/route del $VIP >/dev/null 2>&1
    echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
    echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "LVS-DR real server stopped.\n"
    ;;
status)
    isLoOn=`/sbin/ifconfig lo:0 | grep "$VIP"`
    isRoOn=`/bin/netstat -rn | grep "$VIP"`
    if [ "$isLoON" == "" -a "$isRoOn" == "" ]; then
        echo "LVS-DR real server has run yet."
    else
        echo "LVS-DR real server is running."
    fi
    exit 3
    ;;
*)
    echo "Usage: $0 {start|stop|status}"
    exit 1
esac
exit 0

将lvs脚本加入开机自启动

# chmod +x /etc/init.d/realserver
# echo "/etc/init.d/realserver" >> /etc/rc.d/rc.local

分别启动LVS和keepalived

# service realserver start
# service keepalived start

注意此时网卡的变化,可以看到虚拟网卡已经分配到了realserver上。

此时查看LVS集群状态,可以看到集群下有两个Real Server,调度算法,权重等信息。ActiveConn代表当前Real Server的活跃连接数

# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.100:3306 wrr persistent 50
  -> 192.168.1.5:3306             Route   3      4          1         
  -> 192.168.1.6:3306             Route   3      0          2    

此时LVS+Keepalived+MySQL主主复制已经搭建完成。

测试验证

功能性验证

关闭MySQL Server2

# service mysqld stop

在LVS1查看/var/log/messages中关于keepalived日志,LVS1检测到了MySQL Server2宕机,同时LVS集群自动剔除了故障节点

Sep  9 13:50:53 192.168.1.2 Keepalived_healthcheckers[18797]: TCP connection to [192.168.1.6]:3306 failed !!!
Sep  9 13:50:53 192.168.1.2 Keepalived_healthcheckers[18797]: Removing service [192.168.1.6]:3306 from VS [192.168.1.100]:3306

从新启动MySQL Server2后自动将故障节点自动加入LVS集群

Sep  9 13:51:41 192.168.1.2 Keepalived_healthcheckers[18797]: TCP connection to [192.168.1.6]:3306 success.
Sep  9 13:51:41 192.168.1.2 Keepalived_healthcheckers[18797]: Adding service [192.168.1.6]:3306 to VS [192.168.1.100]:3306

关闭LVS1上的Keepalived(模拟宕机操作),查看LVS1上的日志,可以看到Keepalived移出了LVS1上的VIP

Sep  9 14:01:27 192.168.1.2 Keepalived[18796]: Stopping Keepalived v1.2.13 (09/09,2014)
Sep  9 14:01:27 192.168.1.2 Keepalived_healthcheckers[18797]: Removing service [192.168.1.5]:3306 from VS [192.168.1.100]:3306
Sep  9 14:01:27 192.168.1.2 Keepalived_healthcheckers[18797]: Removing service [192.168.1.6]:3306 from VS [192.168.1.100]:3306
Sep  9 14:01:27 192.168.1.2 Keepalived_vrrp[18799]: VRRP_Instance(VI_1) sending 0 priority
Sep  9 14:01:27 192.168.1.2 Keepalived_vrrp[18799]: VRRP_Instance(VI_1) removing protocol VIPs.

同时查看LVS2上日志,可以看到LVS2成为了Master,并接管了VIP

Sep  9 14:11:24 192.168.1.11 Keepalived_vrrp[7457]: VRRP_Instance(VI_1) Transition to MASTER STATE
Sep  9 14:11:25 192.168.1.11 Keepalived_vrrp[7457]: VRRP_Instance(VI_1) Entering MASTER STATE
Sep  9 14:11:25 192.168.1.11 Keepalived_vrrp[7457]: VRRP_Instance(VI_1) setting protocol VIPs.
Sep  9 14:11:25 192.168.1.11 Keepalived_vrrp[7457]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.1.100
Sep  9 14:11:25 192.168.1.11 Keepalived_healthcheckers[7456]: Netlink reflector reports IP 192.168.1.100 added
Sep  9 14:11:25 192.168.1.11 avahi-daemon[1407]: Registering new address record for 192.168.1.100 on eth0.IPv4.
Sep  9 14:11:30 192.168.1.11 Keepalived_vrrp[7457]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 192.168.1.100

在LVS2上查看LVS集群状态,一切正常。

# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.100:3306 wrr persistent 50
  -> 192.168.1.5:3306             Route   3      2          0         
  -> 192.168.1.6:3306             Route   3      1          0 

总结

  • MySQL主主复制是集群的基础,组成Server Array,其中每个节点作为Real Server。

  • LVS服务器提供了负载均衡的作用,将用户请求分发到Real Server,一台Real Server故障并不会影响整个集群。

  • Keepalived搭建主备LVS服务器,避免了LVS服务器的单点故障,出现故障时可以自动切换到正常的节点。

原文参考
"http://bestvivi.com/2015/09/09/MySQL主主复制+LVS+Keepalived实现MySQL高可用性"

查看原文

赞 15 收藏 62 评论 0

bestvivi 发布了文章 · 2015-09-07

Amobe实现MySQL读写分离

Amobe介绍

Amoeba(变形虫)项目,该开源框架于2008年 开始发布一款 Amoeba for Mysql软件。

这个软件基于Java致力于MySQL的分布式数据库前端代理层,处于在应用和数据库之间,对客户端透明,它主要在应用层访问MySQL的时候充当SQL路由功能,解析应用传递过来的SQL语句,专注于分布式数据库代理层(Database Proxy)开发。具有负载均衡、高可用性、SQL 过滤、读写分离、可路由相关的到目标数据库、可并发请求多台数据库合并结果。 通过Amoeba能够完成多数据源的高可用、负载均衡、数据切片的功能,目前Amoeba已在很多企业的生产线上面使用。

优点:Amoeba已经具有Query路由,Query过滤,读写分离,负载均衡以及HA机制等相关内容。

缺点:Amoeba暂不支持事务;amoeba不支持跨库join和排序;amoeba不支持分库分表等;

Amoeba 主要解决的以下几个问题:

  1. 数据切分后复杂数据源整合;

  2. 提供数据切分规则并降低数据切分规则给数据库带来的影响;

  3. 降低数据库与客户端的连接数;

  4. 读写分离路由;

Amobe实现读写分离配置

安装环境如下

master 192.168.1.5 rac1-node.tp-link.net

slave 192.168.1.6 rac2-node.tp-link.net

amobe 192.168.1.2 poprodbak.tp-link.net

安装amoeba前要安装jdk,因为amoeba是由java开发的。同时设置JAVA_HOME

下载ameba软件
使用amoeba稳定版

# mkdir amoeba 
# cd amoeba
# tar -zxvf amoeba-mysql-binary-2.2.0.tar.gz

配置amobe

解压完以后,下面进行配置。在conf目录下可以看到很多.xml后缀的文件。其中

amoeba.xml是对amoeba代理的配置,定义读写分离的节点管理信息;

dbServers.xml是对后端service的配置,定义数据库的信息;

rule.xml可以定义高级设置比如数据的水平、垂直切分等;

log4j.xml定义日志等。

配置dbServers.xml

 <!--  
                        Each dbServer needs to be configured into a Pool, 
每个dbServer需要配置一个pool,如果多台平等的mysql需要进行loadBalance,平台已经提供一个具有负载均衡能力的objectPool:    简单的配置是属性加上virtual="true",该Pool不允许配置factoryConfig或者自己写一个ObjectPool
 
                         such as 'multiPool' dbServer    
                --> 
 
        <dbServer name="abstractServer" abstractive="true"> 
                <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory"> 
                        <property name="manager">${defaultManager}</property> 
                        <property name="sendBufferSize">64</property> 
                        <property name="receiveBufferSize">128</property> 
 
                        <!-- mysql port --> 
                        <property name="port">3306</property> 
                                  \\这个是后端数据的端口
                        <!-- mysql schema --> 
                        <property name="schema">test</property> 
                                    \\这个是后端默认的数据库
                        <!-- mysql user --> 
                        <property name="user">root</property> 
 
                        <!--  mysql password 
                        <property name="password">password</property> 
                        --> 
                </factoryConfig> 
 
        </dbServer> 
 \\下面的配置是定义一个主节点和一个从节点。
        <dbServer name="master"  parent="abstractServer">   \\定义一个主节点
                <factoryConfig> 
                        <!-- mysql ip --> 
                        <property name="ipAddress">192.168.1.5</property> 
                        <property name="user">root</property>   \\连接数据库的用户名
                        <property name="password">root</property>  \\连接数据库的密码,此处如果写库跟读库密码一致,可以写在上面公共段,这里会继承上面的设置
                </factoryConfig> 
        </dbServer> 
        <dbServer name="slave"  parent="abstractServer">  \\定义一个从节点
                <factoryConfig> 
                        <!-- mysql ip --> 
                        <property name="ipAddress">192.168.1.6</property> 
                        <property name="user">root</property> 
                        <property name="password">root</property> 
                </factoryConfig> 
        </dbServer> 
             \\定义池,把master和slave加入
        <dbServer name="server1" virtual="true">  \\server1是要把master节点加入
                <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool"> 
                        <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->                               < !  -- 负载均衡参数1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
                        <property name="loadbalance">1</property> 
 
                        <!-- Separated by commas,such as: server1,server2,server1 --> 
                        <property name="poolNames">master</property>  <!--
参与该pool负载均衡的poolName列表以逗号分割 这里只一个主节点所以就一个
 -->
                </poolConfig> 
        </dbServer> 
        <dbServer name="readPool" virtual="true">
                <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
                        <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
                        <property name="loadbalance">1</property>

                        <!-- Separated by commas,such as: server1,server2,server1 -->
                        <property name="poolNames">slave,slave,slave,master</property>
                </poolConfig>
        </dbServer> 
 
</amoeba:dbServers>

配置amobe.xml


<!-- port --> 
                        <property name="port">8066</property> 
                        \\定义amoeba读写分离proxy对外代理的端口
                        <!-- bind ipAddress --> 
                        <!--  
                        <property name="ipAddress">127.0.0.1</property> \\这个是绑定端口的ip,注释掉了,说明8066端口绑定在0.0.0.0/0.0.0.0 上面          --> 
                         <property name="manager">${clientConnectioneManager}</property> 
 
                        <property name="authenticator"> 
                                <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator"> 
 
                                        <property name="user">root</property> 
                                                        \\定义通过amoeba登录的用户名       
                                        <property name="password">root</property> 
                                                         \\相应的这个就是密码了。定义proxy的管理帐号密码,客户端和程序只需要连接proxy的帐号密码即可,相当于中间件封装
 

                <property name="LRUMapSize">1500</property> 
                <property name="defaultPool">master </property> 
 \\定义默认的池,一些除了SELECT\UPDATE\INSERT\DELETE的语句都会在defaultPool执行
 
                <property name="writePool">master</property>
\\定义写的池,这里的master就是在dbServer.xml中的master
                <property name="readPool"> readPool </property> 
                   \\定义读的池,这里的readPool就是在dbserver.xml中的readPool
                <property name="needParse">true</property> 

启动amobe

# ./amoeba start &
[1] 2381
# netstat -tlnp | grep 8066
tcp        0      0 :::8066                     :::*                        LISTEN      2381/java

以上说明amoeb已经正常启动了。

# mysql -h 192.168.1.2 -ulibai --port 8066 –p

连接报错
java.util.NoSuchElementException: Could not create a validated object, cause: ValidateObject failed

修改dbServers.xml配置,factoryConfig中 password默认是被注释掉的,取消注释
还是报错,后来发现原来是schema设置不对,这个是要设置为数据库名。修改后通过amoeba连接数据库正常。

至此,amoeba正常启动,客户端可以通过amoeba正常连接MySQL数据库。

验证测试

使用tcpdump抓包工具分析,读写是否分离到master和slave上。

在master和slave上分别执行

# tcpdump -i eth2 -s 0 -A -n -p port 3306 and src 192.168.1.2 | grep -i 'SELECT\|INSERT'

其中192.168.1.2是amoeba服务器

在amoeba服务器上执行select操作

slave上可以抓取到如下信息,查询三次以后,可以从master抓取到查询信息(因为此时master和slave节点数据刚好不一致,可以非常清晰地确实是在master上执行的)。因此可以大概验证amoeba设置的读操作slave和master 3比1的比例。

...p(Y.......select * from t
13:59:36.355619 IP 192.168.1.2.24489 > 192.168.1.6.mysql: Flags [.], ack 869, win 96, options [nop,nop,TS val 85451120 ecr 676978448], length 0

在amoeba服务器上执行insert操作

master抓包如下信息,slave上没有任何变化。因此可以验证写操作完全在master节点上完成。

14:06:47.578469 IP 192.168.1.2.58575 > 192.168.1.5.mysql: Flags [P.], seq 68:90, ack 94, win 46, options [nop,nop,TS val 85882307 ecr 677373872], length 22
E..JF.@.@.p|............>K....AM...........
..u.(_.......set names latin1.
14:06:47.578830 IP 192.168.1.2.58575 > 192.168.1.5.mysql: Flags [.], ack 105, win 46, options [nop,nop,TS val 85882308 ecr 677413229], length 0
E..4F.@.@.p.............>K.+..AX.....d.....
..u.(`.m
14:06:47.579712 IP 192.168.1.2.58575 > 192.168.1.5.mysql: Flags [P.], seq 90:135, ack 105, win 46, options [nop,nop,TS val 85882309 ecr 677413229], length 45
E..aF.@.@.pc............>K.+..AX...........
..u.(`.m)....insert into t values(5,'this_is_amoeba')
14:06:47.622539 IP 192.168.1.2.58575 > 192.168.1.5.mysql: Flags [.], ack 116, win 46, options [nop,nop,TS val 85882352 ecr 677413233], length 0
E..4F.@.@.p.............>K.X..Ac...........
..u.(`.q

性能对比

针对MySQL Proxy和Amoeba进行了简单的性能对比测试

分别查询14W条数据,proxy和amoeba表现几无差别。

第一次(s) 第二次 3 4 5 平均(s)

Mysql-proxy 0.27 0.27 0.28 0.29 0.26 0.274

Amoeba 0.23 0.26 0.33 0.25 0.34 0.282

分别插入14W条数据,proxy平均为1.8S,amoeba平均为1.95S。

可以看出mysqlproxy和amobe几无差别,可能是因为数据量比较小。

查看原文

赞 3 收藏 15 评论 1

bestvivi 发布了文章 · 2015-09-07

MySQL读写分离介绍及搭建

MySQL读写分离介绍

MySQL读写分离基本原理是让master数据库处理写操作,slave数据库处理读操作。master将写操作的变更同步到各个slave节点。

MySQL读写分离示意图

MySQL读写分离能提高系统性能的原因在于:

  • 物理服务器增加,机器处理能力提升。拿硬件换性能。

  • 主从只负责各自的读和写,极大程度缓解X锁和S锁争用。

  • slave可以配置myiasm引擎,提升查询性能以及节约系统开销。

  • master直接写是并发的,slave通过主库发送来的binlog恢复数据是异步。

  • slave可以单独设置一些参数来提升其读的性能。

  • 增加冗余,提高可用性。

MySQLProxy介绍

下面使用MySQL官方提供的数据库代理层产品MySQLProxy搭建读写分离。
MySQLProxy实际上是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy,然后经由MySQLProxy进行相应的分析,判断出是读操作还是写操作,分发至对应的MySQLServer上。对于多节点Slave集群,也可以起做到负载均衡的效果。

MySQLProxy示意图

MySQL读写分离配置

MySQL环境准备

master 192.168.1.5

slave 192.168.1.6

proxy 192.168.1.2

MySQL:5.5.37

MySQL-proxy:mysql-proxy-0.8.4-linux-rhel5-x86-64bit.tar.gz

创建用户并分配权限

    mysql> create user libai identified by 'libai';
    mysql> grant all on *.* to libai@'192.168.1.%' identified by 'libai';

在配置了MySQL复制,以上操作在master执行会同步到slave节点。

启用MySQL复制

MySQL复制配置请参考这里

先关闭并清除之前的复制。

    mysql> stop slave;
    mysql> reset slave all;

启用新的复制同步。启用之前需要清除日志

mysql> change master to master_host='192.168.1.5',master_user='libai',master_password='libai',master_port=3306,master_log_file='mysql-bin.000001',master_log_pos=0;

主库

    # mysql -h localhost -ulibai -plibai
    mysql> create database d;
    mysql> use d;
    mysql> create table t(i int);
    mysql> insert into t values(1);

从库

    mysql> select * from t;
    +------+
    | i    |
    +------+
    |    1 |

启用MySQLProxy代理服务器

代理服务器上创建mysql用户

    # groupadd mysql
    # useradd -g mysql mysql

解压启动mysql-proxy

    # ./mysql-proxy --daemon --log-level=debug --user=mysql --keepalive --log-file=/var/log/mysql-proxy.log --plugins="proxy" --proxy-backend-addresses="192.168.1.5:3306" --proxy-read-only-backend-addresses="192.168.1.6:3306" --proxy-lua-script="/root/soft/mysql-proxy/rw-splitting.lua" --plugins=admin --admin-username="admin" --admin-password="admin" --admin-lua-script="/root/soft/mysql-proxy/lib/mysql-proxy/lua/admin.lua"

其中proxy-backend-addresses是master服务器,proxy-read-only-backend-addresses是slave服务器。可以通过./mysql-proxy --help 查看详细说明。

查看启动后进程

    # ps -ef | grep mysql
    root     25721     1  0 11:33 ?        00:00:00 /root/soft/mysql-proxy/libexec/mysql-proxy --daemon --log-level=debug --user=mysql --keepalive --log-file=/var/log/mysql-proxy.log --plugins=proxy --proxy-backend-addresses=192.168.1.5:3306 --proxy-read-only-backend-addresses=192.168.1.6:3306 --proxy-lua-script=/root/soft/mysql-proxy/rw-splitting.lua --plugins=admin --admin-username=admin --admin-password=admin --admin-lua-script=/root/soft/mysql-proxy/lib/mysql-proxy/lua/admin.lua
    mysql    25722 25721  0 11:33 ?        00:00:00 /root/soft/mysql-proxy/libexec/mysql-proxy --daemon --log-level=debug --user=mysql --keepalive --log-file=/var/log/mysql-proxy.log --plugins=proxy --proxy-backend-addresses=192.168.1.5:3306 --proxy-read-only-backend-addresses=192.168.1.6:3306 --proxy-lua-script=/root/soft/mysql-proxy/rw-splitting.lua --plugins=admin --admin-username=admin --admin-password=admin --admin-lua-script=/root/soft/mysql-proxy/lib/mysql-proxy/lua/admin.lua

4040是proxy端口,4041是admin管理端口

    # lsof -i:4040
    COMMAND     PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    mysql-pro 25722 mysql   10u  IPv4 762429      0t0  TCP *:yo-main (LISTEN)
    # lsof -i:4041
    COMMAND     PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    mysql-pro 25722 mysql   11u  IPv4 762432      0t0  TCP *:houston (LISTEN)

测试

保证mysqlproxy节点上可执行mysql 。通过复制同步帐号连接proxy

    # mysql -h 192.168.1.2 -ulibai -p --port=4040
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | d                  |
    | mysql              |
    | performance_schema |
    | test               |
    +--------------------+

登录admin查看状态

    # mysql -h 192.168.1.2 -u admin -p --port=4041
    mysql> select * from backends;
    +-------------+------------------+-------+------+------+-------------------+
    | backend_ndx | address          | state | type | uuid | connected_clients |
    +-------------+------------------+-------+------+------+-------------------+
    |           1 | 192.168.1.5:3306 | up    | rw   | NULL |                 0 |
    |           2 | 192.168.1.6:3306 | up    | ro   | NULL |                 0 |
    +-------------+------------------+-------+------+------+-------------------+
    2 rows in set (0.00 sec)

可以从以上查询中看到master和slave状态均为up。

1)登录proxy节点,创建数据库dufu,并创建一张表t

    mysql> create database dufu;
    mysql> show databases;
    mysql> use dufu;
    mysql> create table t(id int(10),name varchar(20));
    mysql> show tables;

创建完数据库及表后,主从节点上应该都可以看到

2)关闭同步,分别在master和slave上插入数据

    mysql> slave stop;

master

    mysql> insert into t values(1,'this_is_master');

slave

    mysql> insert into t values(2,'this_is_slave');

3)proxy上查看结果

    mysql> use dufu;
    mysql> select * from t;
    +------+---------------+
    | id   | name          |
    +------+---------------+
    |    2 | this_is_slave |
    +------+---------------+
    1 row in set (0.00 sec)

从结果可以看到数据是从slave上读取的,并没考虑master节点上的数据。

直接从proxy上插入数据

    mysql> insert into t values(3,'this_is_proxy');

再次查询

    mysql> select * from t;
    +------+---------------+
    | id   | name          |
    +------+---------------+
    |    2 | this_is_slave |
    +------+---------------+

结果显示查询数据没有变化,因为proxy上执行insert相当于写入到了master上,而查询的数据是从slave上读取的。

master上查询

    mysql> select * from t;
    +------+----------------+
    | id   | name           |
    +------+----------------+
    |    1 | this_is_master |
    |    3 | this_is_proxy  |
    +------+----------------+

启用复制,proxy查询

    mysql> select * from t;
    +------+----------------+
    | id   | name           |
    +------+----------------+
    |    2 | this_is_slave  |
    |    1 | this_is_master |
    |    3 | this_is_proxy  |
    +------+----------------+

说明此时master上的数据同步到了slave,并且在proxy查询到数据是slave数据库的数据。此时,可以看到MySQLProxy实现了分离。

查看原文

赞 20 收藏 154 评论 5

bestvivi 发布了文章 · 2015-09-07

MySQL复制介绍及搭建

MySQL复制介绍

MySQL复制就是一台MySQL服务器(slave)从另一台MySQL服务器(master)进行日志的复制然后再解析日志并应用到自身,类似Oracle中的Data Guard。

MySQL复制有那些好处:

  • 第一是解决宕机带来的数据不一致,因为MySQL复制可以实时备份数据;

  • 第二点是减轻数据库服务器的压力,多台服务器的性能一般比单台要好。但是MySQL复制不适合大数据量,大数据量推荐使用集群。

MySQL复制过程分成三步:

  • master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;

  • slave将master的binary log events拷贝到它的中继日志(relay log);

  • slave重做中继日志中的事件,将改变应用到自己的数据库中。

MySQL复制是异步的且串行化的

MySQL复制原理图

MySQL复制搭建

环境准备

master 192.168.1.5 rac1-node.tp-link.net

slave 192.168.1.6 rac2-node.tp-link.net

OS:Oracle Linux 6.1

MySQL:5.5.37

Master配置

分配复制权限

    mysql> grant replication client,replication slave on *.* to root@'192.168.1.%' identified by 'root';
    Query OK, 0 rows affected (0.00 sec)

清空日志文件

    mysql> show binary logs;
    +------------------+-----------+
    | Log_name         | File_size |
    +------------------+-----------+
    | mysql-bin.000001 |     26636 |
    | mysql-bin.000002 |   1069399 |
    | mysql-bin.000003 |     26636 |
    | mysql-bin.000004 |   1069399 |
    | mysql-bin.000005 |       536 |
    +------------------+-----------+
    5 rows in set (0.00 sec)

    mysql> reset master;
    Query OK, 0 rows affected (0.01 sec)
    +------------------+-----------+
    | Log_name         | File_size |
    +------------------+-----------+
    | mysql-bin.000001 |       107 |
    +------------------+-----------+
    1 row in set (0.00 sec)

Slave设置

1) 修改从服务器server-id

    # vim /etc/my.cnf
    server-id = 2

修改完以后需要重启数据库

2)清空日志文件,同Master

3)让slave连接master并开始重做master二进制日志中的事件

    mysql> change master to

MASTER_LOG_POS的值为0,因为它是日志的开始位置

这里注意:默认情况下,会同步该用户下所有的DB,可以在/etc/my.inf中通过参数binlog-do-db、binlog-ignore-db设置需要同步的数据库。

4)开启slave

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

5)确认Slave是否和Mater成功通信。如果 Slave_IO_Running和Slave_SQL_Running都是yes,则证明配置成功

    mysql> show slave status\G;
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.1.5
                      Master_User: root
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000001
              Read_Master_Log_Pos: 107
                   Relay_Log_File: rac-node2-relay-bin.000002
                    Relay_Log_Pos: 253
            Relay_Master_Log_File: mysql-bin.000001
                **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: 107
                  Relay_Log_Space: 413
                  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: 1
    1 row in set (0.00 sec)

测试

Master创建数据库

    mysql> create database d;
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | d                  |
    | mysql              |
    | performance_schema |
    | test               |
    +--------------------+

Slave查看数据库已同步

    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | d                  |
    | mysql              |
    | performance_schema |
    | test               |
    +--------------------+
    mysql> use d
    mysql> create table t(id int);

Slave查看

    mysql> show tables;
    mysql> select * from t;
    +------+
    |    1 |
    +------+

通过以上验证,可以看到主服务器上的修改能够正常同步到从服务器。

其他复制方式

主主复制

master-slave只能进行单向操作,像网络中的半双工。master-master可以实现服务器之间互相同步。主主复制最大的问题就是数据插入或更新冲突。配置方法同主从复制,反过来让slave同步master。注意master_log_file和master_log_pos参数要与master上对应。具体可以参考这里

单一master和多slave

由一个master和多个slave组成的复制系统比较简单。slave之间并不互相通信,只能与master通信。如果写操作较少,读操作很多,可以采用。可以将读操作分布到其他slave,从而减轻master的压力。但slave增加到一定数量时,slave对master的负载以及网络带宽都会成为问题。

主从多级复制

读操作很多可以采用单一maste和多slave,但增大到一定slave后连到master的slaveIO线程太多会造成master压力增大,从而造成数据复制延时。
多级复制就是为了解决这个问题。

mysql多级复制

当然,增加复制的级联层次,同一个变更传到最底层的Slave所需要经过的MySQL也会更多,同样可能造成延时较长的风险。如果条件允许,倾向于通过拆分成多个Replication集群来解决

原文地址 http://bestvivi.com

查看原文

赞 3 收藏 32 评论 1

bestvivi 发布了文章 · 2015-09-07

MySQL Cluster搭建MySQL高可用性方案讨论

MySQLCluster介绍以及搭建可以参考 传送门

MySQL Cluster主要包括三种节点:

  • 数据节点:存储集群的数据,同时集群软件会自动对数据进行分片并冗余。图中NDB

  • SQL节点:查询入口。因为需要消耗较大资源,因此可以进行分布式管理。图中SQL

  • 管理节点:负责整个Cluster 集群中各个节点的管理工作,包括集群的配置,启动关闭各节点,以及实施数据的备份恢复等。 图中MGM

MySQLCluster基础版

作为集群,数据节点以及SQL节点都应该能够进行扩展。MySQL Cluster可以很容易实现扩展,只需要在管理节点中进行配置即可。如图。这里的SQL节点有多个,因此就会有多个访问集群的入口。

MySQLCluster扩展版

MySQLCluster扩展版中入口节点有多个,如果在SQL上在添加一层负载均衡层就可以实现对SQL节点的分布式管理,统一对集群访问入口并实现负载均衡的功能,同时避免单点故障。

MySQLCluster加强版

Load balance层,可以选用软件负载均衡,包括我在测试中使用的是lvs+keepalived,既能保证负载均衡也能保证单点故障。也可以采用硬件负载均衡的方式,比如F5来实现。

查看原文

赞 0 收藏 0 评论 0

bestvivi 发布了文章 · 2015-09-07

MySQL Cluster搭建及配置

MySQL Cluster介绍

MySQL Cluster是一个高性能、可扩展、集群化数据库产品。MySQL Cluster是一个基于NDB Cluster存储引擎的完整分布式数据库系统,采用无共享的数据存储技术,实时同步且支持快速故障切换、事务。NDB是一种in-memory的存储引擎,它具有可用性高和数据一致性好的特点。

MySQL Cluster可由多台服务器组成的、同时对外提供数据管理服务的分布式集群系统。通过合理的配置,可以将服务请求在多台物理机上分发实现负载均衡 ;同时内部实现了冗余机制,在部分服务器宕机的情况下,整个集群对外提供的服务不受影响,从而能达到99.999%以上的高可用性。

MySQLCluster组成

MySQL Cluster分为三类节点:

  • 数据节点(Data Nodes):用于存储集群的数据。实现底层数据存储的功能,保存Cluster 的数据。每一个NDB 节点保存完整数据的一部分(或者一份完整的数据,视节点数目和配置而定),在MySQL Cluster 里面叫做一个fragment。而每一个fragment,正常情况来讲都会在其他的主机上面有一份(或者多分)完全相同的镜像存在。这些都是通过配置来完成的,所以只要配置得当,MySQL Cluster 在存储层不会出现单点的问题。数据节点是用命令ndbd启动的。

  • SQL节点(SQL Nodes):向外提供一个标准的SQL语言编程接口。SQL节点负责向数据节点传送访问请求,具体集群过程以及数据库底层均对外透明。
    SQL节点提供用户SQL指令请求,解析、连接管理,query优化和响、cache管理等、数据merge、sort,裁剪等功能,当SQL节点启动时,将向管理节点同步架构信息,用以数据查询路由。SQL节点作为查询入口,需要消耗大量cpu及内存资源,可使用分布式管理节点,并在SQL节点外封装一层请求分发及HA控制机制可解决单点及性能问题,其提供了线性扩展功能。SQL节点是使用命令mysqld -ndbcluster启动的,或将ndbcluster添加到“my.cnf”后使用“mysqld”启动。

  • 管理节点(NDB Management Server):负责整个Cluster 集群中各个节点的管理工作,包括集群的配置,启动关闭各节点,以及实施数据的备份恢复等。管理节点会获取整个Cluster 环境中各节点的状态和错误信息,并且将各Cluster 集群中各个节点的信息反馈给整个集群中其他的所有节点。通常只需配置一个管理节点;然而为了排除单点故障需要,有可能的话,尽量增加管理节点的数量。MGM节点是用命令ndb_mgm启动的。

MySQL Cluster搭建

环境准备

数据节点:192.168.1.5 192.168.1.6
SQL节点:192.168.1.2 192.168.1.11
管理节点:192.168.1.10

Mysql集群软件:mysql-cluster-gpl-7.2.8-linux2.6-x86_64.tar.gz 下载地址

管理节点配置

将MySQL集群软件拷贝到管理节点的/usr/local目录下并解压为mysql,MySQLCluster管理节点默认是要安装在/usr/local下的,否则启动会报错

添加用户及用户组

# groupadd mysql
# useradd -g mysql mysql

更改所属用户和组

# chown -R mysql:mysql mysql

拷贝配置文件

# cp mysql-cluster/support-files/ndb-config-2-node.ini /etc/ndb-config.ini

修改配置文件,管理节点的配置文件非常重要,会影响整个集群

# vim /etc/ndb-config.ini

[ndbd default]
NoOfReplicas= 2  #定义在Cluster环境中复制份数
DataMemory= 80M #分配的数据内存大小,根据本机服务器内存适量来分配,实际运用中需要分配很大
IndexMemory= 24M #设定用于存放索引(非主键)数据的内存段大小
#一个NDB节点能存放的数据量是会受到DataMemory和IndexMemory两个参数设置的约束,两者任何一个达到限制数量后,都无法再增加能存储的数据量。如果继续存入数据系统会报错“table is full”。
DataDir= /var/lib/mysql-cluster  #用于存放集群日志信息

DataMeomory=1400M
IndexMemory=600M
LockPagesInMainMemory=1  # 会有问题
MaxNoOfConcurrentOperations=500000
TimeBetweenLocalCheckpoints=20
TimeBetweenGlobalCheckpoints=1000
TimeBetweenEpochs=100
TimeBetweenWatchdogCheckInitial=60000
TransactionInactiveTimeout =50000
MaxNoOfExecutionThreads=8 
BatchSizePerLocalScan=512 
MaxNoOfOrderedIndexes=512
MaxNoOfConcurrentOperations= 10000

[ndb_mgmd]
Id=1
Hostname=192.168.1.10  # Hostname or IP address
#确定该目录存在,并修改所属用户为mysql
DataDir= /var/lib/mysql-cluster # Directory for MGM node logfiles

[ndbd]
Id= 2
HostName= 192.168.1.5 # Hostname or IP address
datadir=/usr/local/mysql/data # Directory for this data node's datafiles,数据节点存放数据的目录

[ndbd]
Id= 3
HostName= 192.168.1.6
datadir=/usr/local/mysql/data

[mysqld]
Id= 4
HostName= 192.168.1.2
#可以预留一些节点
# choose an unused port number
# in this configuration 63132, 63133, and 63134
# will be used
[tcp default]
PortNumber= 63132

配置完后启动管理节点

# ./ndb_mgmd --initial -f /etc/ndb-config.ini 
MySQL Cluster Management Server mysql-5.5.27 ndb-7.2.8
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 31: [MGM] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 35: [DB] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 39: [DB] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 43: [API] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 50: [tcp] PortNumber is deprecated
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 31: [MGM] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 35: [DB] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 39: [DB] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 43: [API] Id is deprecated, use NodeId instead
2014-08-29 11:22:04 [MgmtSrvr] WARNING  -- at line 50: [tcp] PortNumber is deprecated

其中--initial指定初始化加载,每次修改管理节点的配置重启都需要加上,否则不会生效;-f指定管理节点的参数文件

确定ndb_mgm进程及端口号

# netstat -langput | grep mgm
tcp        0      0 0.0.0.0:1186                0.0.0.0:*                   LISTEN      3427/ndb_mgmd       
tcp        0      0 127.0.0.1:45251             127.0.0.1:1186              ESTABLISHED 3427/ndb_mgmd       
tcp        0      0 127.0.0.1:1186              127.0.0.1:45251             ESTABLISHED 3427/ndb_mgmd

其中1186是管理节点的服务端口

查看集群信息

#  ./ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)]    2 node(s)
id=2 (not connected, accepting connect from 192.168.1.5)
id=3 (not connected, accepting connect from 192.168.1.6)

[ndb_mgmd(MGM)]    1 node(s)
id=1    @192.168.1.10  (mysql-5.5.27 ndb-7.2.8)

[mysqld(API)]    1 node(s)
id=4 (not connected, accepting connect from 192.168.1.2)

可以看到当前只有管理节点,其他节点还未启动。

数据节点和SQL节点配置

解压MySQLCluster软件到指定目录/usr/local,数据节点可以不用放在/usr/local目录下

添加用户及用户组

# groupadd mysql
# useradd -g mysql mysql

更改所属用户和组

# chown -R mysql:mysql mysql

安装数据库

# /usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --user=mysql

拷贝配置文件


# cp /usr/local/mysql/support-files/my-medium.cnf /etc/my.cnf

修改配置文件

vim /etc/my.cnf

# Options for mysqld process:
[MYSQLD]                       
ndbcluster                      # run NDB engine
character_set_server=utf8
ndb-connectstring=198.168.1.10  # location of MGM node
 
# Options for ndbd process:
[MYSQL_CLUSTER]                 
ndb-connectstring=198.168.1.10  # location of MGM node

启动数据节点

# ./ndbd --initial
2014-08-29 14:04:54 [ndbd] INFO     -- Angel connected to '192.168.1.10:1186'
2014-08-29 14:04:54 [ndbd] INFO     -- Angel allocated nodeid: 2

启动SQL节点

# ./mysqld_safe --user=mysql &

SQL节点启动可以添加到系统服务

拷贝运行脚本,添加可执行权限

# cp support-files/mysql.server /etc/init.d/mysqld
# chmod +x /etc/init.d/mysqld

启动数据库

# service mysqld start
Starting MySQL....                                         [  OK  ]

查看集群信息

# ndb_mgm -e show
Cluster Configuration
---------------------
[ndbd(NDB)]    2 node(s)
id=2    @192.168.1.5  (mysql-5.5.27 ndb-7.2.8, Nodegroup: 0, Master)
id=3    @192.168.1.6  (mysql-5.5.27 ndb-7.2.8, Nodegroup: 0)

[ndb_mgmd(MGM)]    1 node(s)
id=1    @192.168.1.10  (mysql-5.5.27 ndb-7.2.8)

[mysqld(API)]    2 node(s)
id=4    @192.168.1.2  (mysql-5.5.27 ndb-7.2.8)
id=5    @192.168.1.11  (mysql-5.5.27 ndb-7.2.8)

可以看到当前所有节点均已启动

集群管理

查看集群内存使用情况

ndb_mgm> all report memoryusage;

关闭集群顺序:SQL节点->数据节点->管理节点 或者使用# ./ndb_mgm -e shutdown命令关闭集群

启动集群顺序: 管理节点->数据节点->SQL节点

验证测试

通过SQL节点(192.168.1.2记为SQL1/192.168.1.11记为SQL2)连入MySQL数据库

# ./mysql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| ndbinfo            |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.04 sec)

修改密码


mysql> set password=password('root');

数据同步测试

连接SQL1,创建数据库dufu,创建成功

连接SQL2,查看到创建成功的数据库dufu

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| dufu               |
| mysql              |
| ndbinfo            |
| performance_schema |
| test               |
+--------------------+
6 rows in set (0.00 sec)

SQL1创建表,插入数据

mysql> use dufu;
Database changed

mysql> create table t(i int,name varchar(10)) engine=ndbcluster;
Query OK, 0 rows affected (0.22 sec)

mysql> insert into t values(1,'this_sql1');
Query OK, 1 row affected (0.01 sec)

SQL2查询

mysql> select * from t;
+------+-----------+
| i    | name      |
+------+-----------+
|    1 | this_sql1 |
+------+-----------+
1 row in set (0.01 sec)

通过以上测试,SQL集群数据是同步的。

可用性测试

关掉数据节点1或SQL节点1,看集群是否能够正常工作
经过测试,关闭冗余节点不会对MySQL集群造成影响,失败节点重新启动后会再次加入加群。可以通过管理节点查看到各个节点的状态

遇到的问题

以上测试只是针对MySQLCluster简单的验证测试,后面我们组织了一次更大压力的测试,400~1000并发,每个连接执行100次循环,每个查询约有5000条数据,同时执行进行的读操作在40000~100000之间,出现了很多问题。

首先是数据节点启动问题:

Ndb kernel thread 4 is stuck in: Job Handling elapsed=100 Watchdog: User time: 82 System time: 667 
Ndb kernel thread 4 is stuck in: Job Handling elapsed=200
Watchdog: User time: 82 System time: 668 
Ndb kernel thread 4 is stuck in: Job Handling elapsed=300 Watchdog: User time: 82 System time: 669 
Ndb kernel thread 4 is stuck in: Job Handling elapsed=400 Watchdog: User time: 82 System time: 670

内存不够或者datamemory、indexmemory设置过大、maxnooflocalscans设置过大导致,通过增大服务器硬件资源以及调大内存设置大小解决。

并发加大后出现:


too many connections

SQL节点的max_connections默认参数为150,调整该参数大小为1000解决。

并发加大后出现:

ERROR 1205 (HY000) at line 10208: Lock wait timeout exceeded; try restarting transaction

TransactionDeadlockDetectionTimeout默认只有1200,调整该参数为10000后解决。调整完后需要重启集群

并发加到1000后,错误率急剧上升,出现:

got temporary error 245 'too many active scans' from ndbcluster

NaxNoOfConcurrentScans参数太小,默认最大为500.调整为500后,还是继续报错-_-!,可能与MaxNoOfLocalScans参数有关。

更新操作,并发加到1000后,出现:

ERROR 1297 (HY000): Got temporary error 410 'REDO log files overloaded (decrease TimeBetweenLocalCheckpoints or increase NoOfFragmentLogFiles)' from NDBCLUSTER

改错表示redo日志可能太小,需要调整redo日志大小,设置TimeBetweenLocalCheckpoints=30
NoOfFragmentLogFiles=128(还未试验)

查看原文

赞 5 收藏 42 评论 3

bestvivi 回答了问题 · 2015-08-13

解决mysql cluster集群停掉一台数据节点后整个集群挂掉,包括其他数据节点和sql节点全部和管理节点断开

已找到答案,管理节点参数设置以及数据节点内存过小导致的

关注 1 回答 1

认证与成就

  • 获得 47 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 1 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-07-28
个人主页被 530 人浏览