代码改变世界

Mysql Proxy 美团点评开源的DBProxy

2020-10-23 14:12  宋海宾  阅读(515)  评论(0)    收藏  举报

Mysql读写分离中间件-DBProxy详解

【写在前面】

在互联网应用场景中,使用比较广泛的数据库是mysql,在很多业务场景中涉及到读写分离,目前市面上读写分离中间件不少,比如奇虎360开源的Atlas,百度的DBProxy(未开源),美团点评开源的DBProxy等等。

从个人使用感受来讲,这些中间件都是比较稳定可靠的,考虑到开源和现状,本文结合具体的实践经验聊一下DBProxy。

 

【功能介绍】

本文介绍的中间件是来自美团点评开源的DBProxy,github地址:

https://github.com/Meituan-Dianping/DBProxy

DBProxy是基于奇虎360开源的Atlas基础上进行改进的,根据个人在奇虎360工作经验来看,Atlas还是比较稳定可靠地。个人建议使用Atlas改进版--DBProxy。

DBProxy主要功能如下:

(1)读写分离

可以自动实现读请求路由到slave中,写请求路由到master中,对开发而言,使用方式和mysql一样,只是配置一下DBProxy连接就可以了。

(2)从库负载均衡

如果存在多个slave,支持读请求按照slave的权重,分别路由到各个slave中,分担读请求压力。可以人为设置各个slave的权重,默认权重为1.

(3)IP过滤

支持哪些IP(段)可以访问,提升安全性。

(4)DBA可平滑上下线mysql节点

支持在线扩容slave、调整后端mysql(包括master和slave),不需要重启。

说明:流量高峰期期间,该操作需要慎重。

(5)自动摘除宕机的mysql节点

如果后端某个mysql节点宕机,该节点自动从中间件上下掉,读写请求不再路由到该节点实现自动止损,如果所有slave全部宕机,读请求自动路由到master节点。

(6)监控信息完备

DBProxy打印了比较详细的日志,方便DBA追查问题。

(7)密文存储密码

DBProxy提供了加密工具,对密码加密,然后在配置文件中设置密文密码,可以提高安全性。

(8)解耦业务和mysql

通过DBProxy可以解耦业务和mysql,可以实现透明调整mysql,尤其适合DBA白天操作mysql。

说明:DBProxy官方称目前只支持mysql(percona)5.5和5.6。如果想使用mysql5.7或者8.0,可能需要选择其他方案。

sql限制:

受到限制的sql主要包括不常用的管理命令,以及不带where的dml等,对于一般情况的应用几乎没有影响。考虑到限制的sql点比较多(尽管大部分不常用),建议先测试所有的业务sql,然后再上线DBProxy。

具体sql限制参考:

https://github.com/Meituan-Dianping/DBProxy/blob/master/doc/USER_GUIDE.md#3.2.1

 

【最佳实践】

(1)环境说明

操作系统:centos 6.9 x86_64

mysql版本:percona-server-5.6(二进制版本)

DBProxy版本:0.2.5

glib2: 2.42.0

说明:考虑到master高可用以及DBProxy自身的高可用,本文采用了keepalived+haproxy+MHA方案。

 

(2)安装依赖包

首先需要安装依赖包 glib-2.42,如下:

yum install -y Percona-Server-devel-56.x86_64  Percona-Server-shared-56 jemalloc jemalloc-devel libevent libevent-devel openssl openssl-devel lua lua-devel bison flex libtool.x86_64 libffi.x86_64 libffi-devel.x86_64 gettext.x86_64 gettext-devel.x86_64

说明:由于具体的操作系统有所差别,依赖包安装也存在差别。

 

wget https://src.fedoraproject.org/repo/pkgs/mingw-glib2/glib-2.42.0.tar.xz/

71af99768063ac24033ac738e2832740/glib-2.42.0.tar.xz

xz -d glib-2.42.0.tar.xz

tar -xvf glib-2.42.0.tar

cd glib-2.42.0

autoreconf -ivf

./configure --prefix=/usr/local/glib-2.42  --enable-iconv=no --with-libiconv=gnu

make && make install

 

然后执行:

echo "/usr/local/glib-2.42" >>/etc/ld.so.conf && ldconfig

 

(3)编译安装DBProxy

从github下载  DBProxy-master.zip 

unzip  DBProxy-master.zip && cd  DBProxy-master

首先修改bootstrap.sh,修改后的内容如下:

#!/bin/sh

base=$(cd "$(dirname "$0")"; pwd)

cd $base

./configure --prefix=/usr/local/mysql-proxy CFLAGS="-g -O0" \

GLIB_CFLAGS="-I/usr/local/glib-2.42/include/glib-2.0 -I/usr/local/glib-2.42/lib/glib-2.0/include" \

GLIB_LIBS="-L/usr/local/glib-2.42/lib -lglib-2.0" \

GMODULE_CFLAGS="-pthread -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include" \

GMODULE_LIBS="-L/usr/local/glib-2.42/lib -Wl,--export-dynamic -lgmodule-2.0 -pthread -lrt" \

GTHREAD_CFLAGS="-pthread -I/usr/local/glib-2.42/include/glib-2.0 -I/usr/local/glib-2.42/lib/glib-2.0/include" \

GTHREAD_LIBS="-L/usr/local/glib-2.42/lib -lgthread-2.0 -pthread -lrt"

 

说明:/usr/local/glib-2.42 是之前glib-2.42编译安装的目录,此处要保持一致

建议prefix设置为:/usr/local/mysql-proxy

然后执行:

cd DBProxy-master

sh autogen.sh

sh bootstrap.sh

make && make install

 

安装完成后,可以拷贝 /usr/local/glib-2.42 和 /usr/local/mysql-proxy 到其他服务器对应目录即可。

(4)集成MHA和haproxy

MHA作为mysql比较常用的高可用方案,可以实现master高可用

在DBProxy配置文件中,相关设置:

proxy-backend-addresses = <mha-vip>:<mysql-port>

<mha-vip>就是mha对应的vip

<mysql-port>就是mysql的端口号

 

 

图1

说明:

1) LVS采用keepalived + haproxy方案,可以解决DBProxy单点问题,

2) MHA解决mysql master单点问题。

3) 2个或者多个DBProxy,避免DBProxy自身单点,还可以实现负载均衡,提高并发。

4) 根据实际需求,部署1个或者多个slave,提升度请求并发量。

5) 盖家沟实现了mysql master和slave高可用。,同时实现了读写分离。

 

【配置文件介绍】:

主要参数配置如下,仅供参考

 

[mysql-proxy]

admin-username=admin_user

admin-password=admin_pwd

### mysql_pwd1 mysql_pwd2为密文

pwds=mysql_user1:mysql_pwd1,mysql_user2:mysql_pwd2

backend-monitor-pwds=monitor_user:monitor_pwd

 

admin-user-hosts=10.111.12%,10.151.%

user-hosts=%@10.111.12%,%@10.151.%

 

admin-address=0.0.0.0:23456

proxy-address=0.0.0.0:13456

proxy-backend-addresses=10.111.123.135:3456

proxy-read-only-backend-addresses=10.111.123.137:3456@10

 

log-path=/usr/local/mysql-proxy/log

sql-log=ON

sql-log-buffer-size=256

sql-log-file-size=1073741824

sql-log-file-num=3

sql-log-mode=ALL

log-trace-modules=0

 

daemon=true

keepalive=true

query-response-time-stats=1

mysql-version=5.6

event-threads=8

instance=proxy3456

user=dba

 

max-connections=5000

long-wait-time=1000

long-query-time=100

wait-timeout=7200

db-connection-idle-timeout=7200

backend-max-thread-running=0

thread-running-sleep-delay=10

remove-backend-timeout=1024

shutdown-timeout=60

 

check-state-interval=4

check-state-conn-timeout=1

 

说明:密文密码生成方法:

cd /usr/local/mysql-proxy/bin && ./encrypt <raw_pwd>

<raw_pwd>表示原始密码,该命令生成一个密文密码

 

启停DBProxy:

/usr/local/mysql-proxy/bin/mysql-proxyd $instance start|stop|status|restart

$instance:DBProxy的instance参数值

也可以自行封装脚本管理。

 

【管理DBProxy】

登录管理端口,可以执行:select * from help;

查看所有的管理功能

常用的功能如下:

(1) 查看backend

 

图2

(2)调整backend节点

下线backend

 

图3

 

上线backend:

 

图4

移除backend:

 

图5

添加slave节点:

 

图6

说明:本操作常用于mysql节点调整,假设迁移一个slave节点到另外一台服务器,流程如下:

    1)做数据

在新服务器上,可以采用镜像或者在线热备方式,启动一个新slave节点,直到同步追上

    2)添加slave节点

按照上述方法添加一个slave,并且观察是否接入流量

    3)下掉老slave节点

可以先下线该节点,然后再移除该节点

    如果迁移master节点,可以执行MHA在线切换命令,不需要上下线这里的 rw节点。

这样,mysql节点调整对开发是透明的,是一种比较友好的方式。

(3)添加删除用户

删除用户

 

图7

添加用户

 

图8

说明:添加用户也可以使用 ADD ENPWD <user_name>:<encrypted_password>

<encrypted_password>是密文密码

(4)调整IP白名单

添加用户IP白名单

 

图9

删除用户IP白名单

 

图10

添加管理host:

 

图11

删除管理host:

 

图12

说明:在增加IP段的场景下,可以参照以上操作添加或者删除IP白名单;也可以在线增加用户,在线修改参数后,可以执行 SAVE CONFIG 持久化保存。

(5)监控proxy状态

 

图13

通过执行该命令,采集状态值,结合zabbix系统,可以有效监控proxy运行情况。

(6)sql过滤

如果希望某些sql禁止访问,可以参照如下操作:

 

图14

登录proxy端口,执行如下命令验证:

 

图15

去除blacklist:

 

图16

说明:在生产环境中,谨慎使用sql过滤功能,避免影响业务。

(7)其他参数设置

     登录管理端口,执行:select * from help; 查看其它参数设置的方法,这里不再赘述。

 

【使用建议】

(1)端口设置

     DBProxy涉及到如下端口:

     1)mysql主库端口

     2)mysql从库端口

     3)proxy端口

     4)管理端口

为了方便管理和使用DBProxy,可以如下命名这些端口:

    比如,mysql主库端口为3456,从库和主库保持一致,proxy端口为13456,管理端口为23456,同时,可以设置 instance=proxy3456

 

(2)读请求走主库方法

     如果写完数据,确保可以立即查询出结果,可以人为路由该请求到主库,方式如下:

/*MASTER*/ select c1,c2,c3 from tab1  where xxx;

(3)读请求路由到指定的slave

     如果希望读请求路由到某个指定的slave节点,可以设置tag,然后sql改为如下方式:/*slave@$slave_tag*/ sql-statement;这样,该查询就可以路由到指定的slave了

 

【注意事项】

   从使用经验看,DBProxy可以很不错地解决mysql读写分离的需求,支持php,java等编程语言,但是,需要注意:

(1)不支持mysql5.7以及更高版本

(2)不支持java-mysql 1.8版本,笔者使用的是5.1.46 java-mysql驱动包

(3)Php访问DBProxy时候,不支持MYSQLI_CLIENT_COMPRESS设置

(4)停止更新维护,期待“有志之士”继续维护更新。

    同时,笔者也测试了cetus读写分离,和DBProxy相比,cetus存在如下缺点:

(1)cetus日志不够详细

(2)如果mysql主从节点不在同一个网段,登陆cetus管理后台,查看从库状态为unknown,估计是不支持跨网段

(3) 需要配置默认db,使用起来不方便

(4) 不支持设置slave权重

(5) 密码明文保存

    当然,cetus也存在优点:比如支持高版本mysql等。

以上是对比测试结果,如有纰漏,欢迎交流指正。

 

【写在最后】

DBProxy作为读写分离中间件,比较可靠稳定的解决了mysql读写分离的需求,维护简单。它实现了slave高可用,同时,结合MHA可以解决master单点问题,结合keepalived+haproxy,可以解决DBProxy自身的单点问题,尤其适合于中小规模业务场景。另外,需要注意haproxy和DBProxy监控,从而保障整个链路的可用性。

 

【参考文献】

https://github.com/Meituan-Dianping/DBProxy/blob/master/doc/USER_GUIDE.md