如何进行读写分离

  • 由开发人员根据所执行的SQL类型连接不同的服务器
  • 由数据库中间层实现读写分离

读写分离时,需要注意,对于实时性要求比较高的数据,不适合在从库上查询(因为主从复制存在一定延迟(毫秒级)),比如库存就应该在主库上查询,如果放在从库上查询,可能会存在超卖的情况

由开发人员根据所执行的SQL类型进行读写分离的方式

优点:

1. 完全由开发人员控制,实现更加灵活

2. 由程序直接连接数据库,所以性能损耗比较少

缺点:

1. 增加了开发的工作量,使程序代码更加复杂

2. 人为控制,容易出现错误

  1. 可采用DNS轮询的方式

DNS轮询:在同一个域名服务器上为同一个域名配置多个不同IP地址的A记录

应用端使用域名来连接数据库服务器,这样在进行域名解析时,域名服务器会循环的将不同的IP返回给应用端,应用端就可以按地址连接不同的只读服务器来进行读取操作

这种操作比较简单,只需要修改域名服务器的配置即可,但是如果某一后端服务器出现故障,则必须通过修改DNS的方式把故障服务器剔除到只读服务器列表之外,性能较差,负载也不均衡,大多数情况下不推荐此方式

  1. 使用LVS/Haproxy 等代理层软件

由于是通用的代理层软件,所以不能自动对SQL语句进行分析,实现读写分离,但是可以完成只读服务器的负载均衡操作

LVS 四层代理,Haproxy 七层代理,所以从性能来看LVS高于Haproxy

  1. F5硬件:成本较高

keepalived+lvs的架构方式

此处使用keepalived+lvs的架构方式,演示如下

优点:

抗负载能力较强,属于四层代理,只进行流量分发,不会对数据内容进行解析,对内存和CPU的消耗也比较低,处理效率更高

工作稳定,自身有完整的双机热备方案,可进行高可用配置

无流量,只分发请求,流量不从它本身出去,不会对主机的网络IO造成影响

服务器信息

# 主DB         IP:192.168.3.100
# 主备DB IP:192.168.3.101
# SlaveDB IP:192.168.3.102
# keepalived vip:192.168.3.99
# lvs manage : 192.168.3.100/101
# lvs vip :192.168.3.98

1. 安装lvs管理工具

在192.168.3.100 和192.168.3.101上安装lvs管理工具

[root@Node1 keepalived]#    yum install -y ipvsadmin.x86_64

2. 加载ipvs模块

在 192.168.3.100 和192.168.3.101以及192.168.3.102 执行以下命令,加载ipvs模块

[root@Node1 keepalived]#    modprobe ip_vs

3. 在slave服务器上编写并运行要使用lvs脚本

在 192.168.3.101和 192.168.3.102上编写脚本

/etc/init.d/lvsrs 脚本文件内容如下

#!/bin/bash
VIP=192.168.3.98
. /etc/rc.d/init.d/functions
case "$1" in
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
/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 "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "LVS-DR real server stopped."
;;
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 to run yet."
else
echo "LVS-DR real server is running."
fi
exit 3
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 1
esac
exit 0

/etc/init.d/lvsrs 需要具有可执行权限

运行脚本

[root@Node1 keepalived]#  /etc/init.d/lvsrs start

运行成功后 通过ip addr 命令 可以看到lo中除了127.0.0.1外还有192.168.3.98

4. 修改主服务器上的keepalived.conf文件,通过keepalived,保证lvs的高可用

! Configuration File for keepalived

global_defs {
router_id mysql_ha
}
vrrp_script check_run {
script "/etc/keepalived/check_mysql.sh"
interval 2
} vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 200
priority 99
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1200
} track_script {
check_run
} virtual_ipaddress {
192.168.3.99/24
}
} vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 201
priority 99
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1200
} virtual_ipaddress {
192.168.3.98/24
}
}
virtual_server 192.168.3.99/24 3306 {
delay_loop 5
lb_algo rr
lb_kind DR
persistence_timeout 120
protocol TCP
sorry_server 192.168.3.99 3306
real_server 192.168.3.101 3306 {
weight 1
MISC_CHECK {
misc_path "/etc/keepalived/check_slave.sh -udba_monitor -p123456 -h10.103.9.204 -P3306"
misc_dynamic
}
}
real_server 192.168.3.102 3306 {
weight 1
MISC_CHECK {
misc_path "/etc/keepalived/check_slave.sh -udba_monitor -p123456 -h10.103.9.205 -P3306"
misc_dynamic
}
}

delay_loop :健康检查时间,单位秒

lb_algo :lvs负载均衡调度算法,rr:轮询算法

lb_kind :lvs实现负载均衡的机制,有NAT,TUN,DR三种模式

persistence_timeout:会话保存时间,单位秒,如果要做session保持,可以将值设大点,可以保证同一个连接在指定时间内都会读取到同一台客户端服务器

sorry_server :后端所有服务器失效后,就会访问此服务器

check_slave.sh 用来监测slave服务器是否可用,当slave服务器宕机或者slave服务器延迟比较大时,脚本会把此slave服务器从lvs的读列表中去掉

脚本内容如下

#/bin/bash
# check_slave.sh
MYSQL=`which mysql`
VIP=192.168.3.98
VPORT=3306
function usage()
{
echo "usage:"
echo "example:# mysql -umonitor -pmonitor -P3306 -h192.168.3.100"
echo "-p, --password[=name]"
echo "-P, --port"
echo "-h, --host=name"
echo "-u, --user=name"
} while getopts "u:p:h:P:" option
do
case "$option" in
u)
dbuser="$OPTARG";;
p)
dbpwd="$OPTARG";;
h)
dbhost="$OPTARG";;
P)
dbport="$OPTARG";;
\?)
usage
exit 1;;
esac
done if [ "-$dbuser" = "-" ]; then
usage
exit 1
fi if [ "-$dbpwd" = "-" ]; then
usage
exit 1
fi if [ "-$dbhost" = "-" ]; then
usage
exit 1
fi if [ "-$dbport" = "-" ]; then
usage
exit 1
fi $MYSQL -u$dbuser -p$dbpwd -P$dbport -h$dbhost -e "select @@version;" >/dev/null 2>&1
if [ $? = 0 ] ;then
MySQL_ok=1
else
/sbin/ipvsadm -d -t $VIP:$VPORT -r $dbhost:$VPORT
exit 1
fi slave_status=$(${MYSQL} -u$dbuser -p$dbpwd -P$dbport -h$dbhost -e 'show slave status \G' | awk ' \
/Slave_IO_Running/{io=$2} \
/Slave_SQL_Running/{sql=$2} \
/Seconds_Behind_Master/{printf "%s %s %d\n",io,sql,$2}') >/dev/null 2>&1 arr=($slave_status)
io=${arr[0]}
sql=${arr[1]}
behind=${arr[2]} if [ "$io" == "No" ]||[ "$sql" == "No" ]; then
/sbin/ipvsadm -d -t $VIP:$VPORT -r $dbhost:$VPORT
exit 1
elif [ $behind -gt 60 ]; then
/sbin/ipvsadm -d -t $VIP:$VPORT -r $dbhost:$VPORT
exit 1
else
/sbin/ipvsadm -a -t $VIP:$VPORT -r $dbhost:$VPORT -g
exit 0
fi

5. 创建lvs用于监控后端数据库所使用的数据库账号

[root@Node1 keepalived]# mysql  -uroot -p

mysql> grant all privileges on *.* to dba_monitor@'192.168.3.%' identified  by '123456';

6. 在使用lvs的manage服务器上编写并运行lvs所需要的脚本

在 192.168.3.100 上编写脚本lvsdr

/etc/init.d/lvsdr 脚本文件内容如下

#!/bin/bash
VIP=192.168.3.98
DEV=eth0
. /etc/rc.d/init.d/functions
case "$1" in
start)
echo "1">/proc/sys/net/ipv4/ip_forward
/sbin/ipvsadm -A -t $VIP:3306 -s rr -p 60
/sbin/ipvsadm -a -t $VIP:3306 -r 10.103.9.204:3306 -g
/sbin/ipvsadm -a -t $VIP:3306 -r 10.103.9.205:3306 -g
/sbin/ipvsadm --start-daemon
echo "LVS-DR server starts successfully.\n"
;;
stop)
/sbin/route del $VIP >/dev/null 2>&1
echo "0" >/proc/sys/net/ipv4/ip_forward
/sbin/ipvsadm -C
echo "LVS-DR real server stopped."
;;
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 to run yet."
else
echo "LVS-DR real server is running."
fi
exit 3
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 1
esac
exit 0

/etc/init.d/lvsdr 需要具有可执行权限

运行脚本

[root@Node1 keepalived]#  /etc/init.d/lvsdr start

7. 在从服务器上访问虚拟IP,进行测试

[root@Node3 ~]# mysql  -udba_monitor -p123456 -h192.168.3.98 -e"show variables like ''server_id";

可以通过以上命令查看虚拟IP当前所在服务器的server_id

由于我们persistence_timeout设置的是120秒,所以接下来的120秒如果一直运行以上命令可以发现,一直访问的是同一个server_id

下面我们在192.168.3.102上查看一下ipvs的状态,命令如下

 [root@Node2 init.d]#  ipvsadm -L -n

可以看到 192.168.3.98:3306 对应了两个服务器ip 192.168.3.101 和192.168.3.102

接下来我们模拟其中一个服务器宕机的情况

[root@Node3 ~]# /etc/init.d/mysqld stop

然后我们再来查询ipvs状态

 [root@Node1 keepalived]#  ipvsadm -L -n

发现 192.168.3.98:3306 现在只对应了1个服务器ip 192.168.3.101,而192.168.3.102已被剔除

二. 由数据库中间层完成读写分离

常用中间层软件有:MysqlProxy、MaxScale、OneProxy 、 ProxySQL等

优点:

1. 由中间件根据查询语法分析,自动完成读写分离

通过判断SQL语句如果是select语句则使用slave,如果是update、insert、delete、create语句则使用master服务器,无法判断的则使用master

2. 对程序透明,对于已有程序不用做任何调整

3. 前面所说到的一些中间层软件除了能做到读写分离外,还具有能对多个只读数据库进行负载均衡的功能

缺点:

1. 由于增加了中间层,所以对查询效率有损耗

2. 对于延迟敏感的业务无法自动在主库执行

使用MaxScale解决读压力大的问题

MaxScale介绍

支持高可用,负载均衡,良好扩展的插件式数据库中间层软件

MaxScale允许用户开发和定制适合自己的插件,目前MaxScale提供的插件功能主要分为5个种类

1. 认证插件

提供数据库登录认证的功能

2. 协议插件

负责 MaxScale和外部系统间接口的协议,包括客户端到MaxScale的接口,以及MaxScale 到后端数据库的接口

3. 路由插件

ReadConnRoute 用来解决多台读服务器的负载均衡

ReadWriteSplit 用来实现读写分离

4. 监控插件

用于对后端数据库进行实时监控,以便将前端请求发送到正确的(即正常的可以对外提供服务的)数据库中

5. 过滤和日志插件

提供了简单的数据库防火墙功能,可以对某些SQL进行过滤和改写,可以进行一些简单的SQL容错和语句的自动转换

使用MaxScale

安装方法自行百度

服务器信息

MaxScale 节点 192.168.3.102
Master DB:192.168.3.100
Slave DB:192.168.3.101
Slave DB:192.168.3.102

1. 为监控模块创建mysql账号

mysql> create user scalemon@'192.168.3.%' identified by '123456';
mysql> grant replication slave,replication client on *.* to scalemon@'192.168.3.%';

2. 为路由模块创建mysql账号

用来读取mysql系统库下的表,获取后端数据库的权限

mysql> create user scaleroute@'192.168.3.%' identified by '123456';
mysql> grant select on mysql.* to scaleroute@'192.168.3.%';

3. 对数据库密码进行加密

因为maxScale的配置文件是一个文本格式的明文文件,在文件中直接书写mysql密码是不安全的

maxScale提供了加密mysql密码的命令,这个命令是在maxScale节点中运行

[root@Node3 tools]#  maxpassword  /var/lib/maxscale/    123456
E3AEE4B7125B9C76BF742AE6246ECC5C

生成了密码123456对应的加密字符串

4. 对maxscale进行配置

[root@Node3 tools]#   vim /etc/maxscale.cnf

参数说明

[maxscale]
thread=1 # 不要超过cpu的数量 [server1]
type=server
address=192.168.3.100
port=3306
protocol=MySQLBackend [server2]
type=server
address=192.168.3.101
port=3306
protocol=MySQLBackend [server3]
type=server
address=192.168.3.102
port=3306
protocol=MySQLBackend [MySQL Monitor]
type=monitor
module =mysqlmon
servers=server1,server2,server3
user=scalemon
passwd=E3AEE4B7125B9C76BF742AE6246ECC5C # 使用刚刚的加密字符串
monitor_interval=1000 # 毫秒 [Read-Write Service]
type=service
router=readwritesplit
servers=server1,server2,server3
user=scalerouter
passwd=E3AEE4B7125B9C76BF742AE6246ECC5C # 使用刚刚的加密字符串
max_slave_connections=100%
max_slave_replication_lag=60 [MaxAdmin Service]
type=service
router=cli [Read-Write Listener]
type=listener
service=Read-Write Service
protocol=MySQLClient
port=4006 [MaxAdmin Listener]
type=listener
service=MaxAdmin Service
protocol=maxscaled
port=6603

5. 启动maxscale服务

[root@Node3 tools]# maxscale -f /etc/maxscale.cnf

6. 查看maxscale服务状态

maxscale是使用maxadmin进行管理的,默认账号是admin,密码是mariadb

 [root@Node3 tools]#    maxadmin --user=admin --password=mariadb
# 查看后端服务器列表
MaxScale> list servers # 查看是否读取到了后端数据库服务器的账号
MaxScale> show dbusers "Read-Write Service"

引入MaxScale后的架构

将双主架构改为了单主架构,因为MaxScale会自动识别后端服务器的角色,如果使用双主架构,则无法分清当前的主是哪一个

(10) 如何MySQL读压力大的问题的更多相关文章

  1. 高并发大流量专题---10、MySQL数据库层的优化

    高并发大流量专题---10.MySQL数据库层的优化 一.总结 一句话总结: mysql先考虑做分布式缓存,过了缓存后就做mysql数据库层面的优化 1.mysql数据库层的优化的前面一层是什么? 数 ...

  2. Mysql千万级大表优化

    Mysql的单张表的最大数据存储量尚没有定论,一般情况下mysql单表记录超过千万以后性能会变得很差.因此,总结一些相关的Mysql千万级大表的优化策略. 1.优化sql以及索引 1.1优化sql 1 ...

  3. mysql+mycat压力测试一例【转】

    前言 有很多人担心生产系统上新东西的程序怕压力跟不上和稳定性不行,是的,大家都怕,所以领导要求做一次压力测试,我个人也觉得是有必要的. 如果按原理来说,mycat如果不做分片,纯粹只是代理的话,他所做 ...

  4. 如何优化MySQL千万级大表

    很好的一篇博客,转载 如何优化MySQL千万级大表 原文链接::https://blog.csdn.net/yangjianrong1985/article/details/102675334 千万级 ...

  5. 第 10 章 MySQL Server 性能优化

    前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的 ...

  6. 10 个 MySQL 经典错误【转】

    Top 1:Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行) 问题还原 mysql> show variables like '%max_connec ...

  7. MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化

    第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化, ...

  8. 重新学习MySQL数据库10:MySQL里的那些日志们

    重新学习MySQL数据库10:MySQL里的那些日志们 同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志, ...

  9. mysql之 mysql数据库压力测试工具(mysqlslap)

    mysqlslap是从MySQL的5.1.4版开始就开始官方提供的压力测试工具.通过模拟多个并发客户端并发访问MySQL来执行压力测试,同时提供了较详细的SQL执行数据性能报告,并且能很好的对比多个存 ...

随机推荐

  1. Linux学习笔记 1 环境变量 2 vi命令

    1 环境变量篇 1.1  修改 查看 生效 系统环境变量 1 涉及系统环境变量的文件   -->  .bash_profile --> /etc/profile 2 该文件位置 /root ...

  2. 845. Greatest Common Divisor

    描述 Given two numbers, number a and number b. Find the greatest common divisor of the given two numbe ...

  3. VBA中FIND方法的使用说明zz

    Find 方法在区域中查找特定信息. 语法 表达式.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, ...

  4. Yahoo Programming Contest 2019.F.Pass(DP)

    题目链接 惊了这是什么F题...怎么我都能做出来...以后atcoder的比赛也不能走神了万一有个这样的F呢(CF已有多次了= =) \(f[i][j]\)表示Takahashi现在一共有\(i\)个 ...

  5. HDU.5765.Bonds(DP 高维前缀和)

    题目链接 \(Description\) 给定一张\(n\)个点\(m\)条边的无向图.定义割集\(E\)为去掉\(E\)后使得图不连通的边集.定义一个bond为一个极小割集(即bond中边的任意一个 ...

  6. MySQL 一对多查询

    group_concat简单来说,这个函数的作用就是连接多个字段 数据表首先我们先建立两个表 CREATE TABLE `student` ( `id` ) NOT NULL AUTO_INCREME ...

  7. Django——ModuleNotFoundError: No module named 'asgiref.sync'

    Django+channels运行时报错 Unhandled exception in thread started by <function check_errors.<locals&g ...

  8. Space Elevator [POJ2392] [DP][优化]

    题目大意 n件物品,第i件hi高,有ci件,最高的一件不能超过ai的高度.问最高能堆多高 输入: 第一行,一个n 接下来每一行,为hi,ai,ci 输出,最高堆多高 样例输入: 37 40 35 23 ...

  9. 3. Spring 核心之 IOC(控制反转) & DI(依赖注入)

    注:此文摘自 http://blog.csdn.net/it_man/article/details/4402245 IOC(DI):其实这个Spring架构核心的概念没有这么复杂,更不像有些书上描述 ...

  10. vue使用babel+sass出错解决

    按照官网的步骤先将vue项目建立好,这时如果使用lang="babel",lang="scss"会报错. 这时终端进入项目文件夹下输入以下命令: npm ins ...