IT基础设施:基于docker的Mysql集群搭建及性能对比

前言

在高可用的需求下,我们通常用集群和负载均衡来解决问题,通过实时热备的多台主机提供相同的服务,即使部分节点故障,对外仍然能正常提供服务。本文探索在docker环境下快速构建Mysql集群,并与docker单节点、宿主机单节点进行写入性能对比。

本文默认看官懂得 docker 知识,有Mysql,C#实践基础。

Percona XtraDB Cluster

简称 PXC,是针对MySQL 用户的高可用性和扩展性解决方案,基于Percona Server,特点为:
  (1)同步复制,事务在所有集群节点要么同时提交,要么不提交。
  (2)多主复制,可以在任意一个节点写入。
  (3)从服务器上的并行应用事件,真正的“并行复制”。
  (4)自动配置节点。
  (5)数据一致性,没有不同步的从服务器。

HAProxy

HAProxy是一款提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,HAProxy是完全免费的、借助HAProxy可以快速并且可靠的提供基于TCP和HTTP应用的代理解决方案。

Mysql通信工作在TCP层,所以这里选择了HAProxy做为负载代理。

过程

拉取percona-xtradb-cluster镜象

docker pull percona/percona-xtradb-cluster

原名称太长,我们使用tag功能,给他取个别名

 docker tag percona/percona-xtradb-cluster pxc

创建专用网络

docker network create --subnet=172.1.0.0/16 net1

分别为各节点创建本地卷

docker volume create mysql_data1
docker volume create mysql_data2
docker volume create mysql_data3
docker volume create mysql_data4
docker volume create mysql_data5

创建主节点

docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=abc12345 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc12345 -v mysql_data1:/var/lib/mysql -v backup:/data --privileged --name=mysql_node1 --net=net1 --ip 172.1.0.2 pxc

创建第2个MySQL节点

通过CLUSTER_JOIN联接主节点

docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=abc12345 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc12345 -e CLUSTER_JOIN=mysql_node1 -v mysql_data2:/var/lib/mysql -v backup:/data --privileged --name=mysql_node2 --net=net1 --ip 172.1.0.3 pxc

创建第3个MySQL节点

docker run -d -p 3309:3306 -e MYSQL_ROOT_PASSWORD=abc12345 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc12345 -e CLUSTER_JOIN=mysql_node1 -v mysql_data3:/var/lib/mysql --privileged --name=mysql_node3 --net=net1 --ip 172.1.0.4 pxc

创建第4个MySQL节点

docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=abc12345 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc12345 -e CLUSTER_JOIN=mysql_node1 -v mysql_data4:/var/lib/mysql --privileged --name=mysql_node4 --net=net1 --ip 172.1.0.5 pxc

创建第5个MySQL节点

docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=abc12345 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc12345 -e CLUSTER_JOIN=mysql_node1 -v mysql_data5:/var/lib/mysql -v backup:/data --privileged --name=mysql_node5 --net=net1 --ip 172.1.0.6 pxc

负载均衡网关布署

拉取镜象

docker pull haproxy

创建配置文件

mkdir /home/haproxy
vim /home/haproxy/haproxy.cfg

内容如下:

global
    #工作目录
    chroot /usr/local/etc/haproxy
    #日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
    log 127.0.0.1 local5 info
    #守护进程运行
    daemon
​
defaults
    log global
    mode    http
    #日志格式
    option  httplog
    #日志中不记录负载均衡的心跳检测记录
    option  dontlognull
    #连接超时(毫秒)
    timeout connect 5000
    #客户端超时(毫秒)
    timeout client  50000
    #服务器超时(毫秒)
    timeout server  50000
​
#监控界面   
listen  admin_stats
    #监控界面的访问的IP和端口
    bind  0.0.0.0:8888
    #访问协议
    mode        http
    #URI相对地址
    stats uri   /dbs
    #统计报告格式
    stats realm     Global\ statistics
    #WEB管理帐号
    stats auth  admin:abc12345
#数据库负载均衡
listen  proxy-mysql
    #访问的IP和端口
    bind  0.0.0.0:3306
    #网络协议
    mode  tcp
    #负载均衡算法(轮询算法)
    #轮询算法:roundrobin
    #权重算法:static-rr
    #最少连接算法:leastconn
    #请求源IP算法:source 
    balance  roundrobin
    #日志格式
    option  tcplog
    option  mysql-check user haproxy
    server  MySQL_1 172.1.0.2:3306 check weight 1 maxconn 2000  
    server  MySQL_2 172.1.0.3:3306 check weight 1 maxconn 2000  
    server  MySQL_3 172.1.0.4:3306 check weight 1 maxconn 2000 
    server  MySQL_4 172.1.0.5:3306 check weight 1 maxconn 2000
    server  MySQL_5 172.1.0.6:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option  tcpka  

运行haproxy

docker run -it -d -p 9001:8888 -p 3306:3306 -v /home/haproxy:/usr/local/etc/haproxy --name haproxy_1 --privileged --net=net1 --ip 172.1.0.7 haproxy

通过访问http://宿主机地址:9001/dbs即可查看网关dashboard

数据写入测试

创建测试数据库,以及表

CREATE SCHEMA `Awp` DEFAULT CHARACTER SET utf8mb4 ;

用户表

CREATE TABLE `Users` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Username` varchar(45) DEFAULT NULL,
  `Password` varchar(45) DEFAULT NULL,
  `Locked` bit(1) DEFAULT NULL,
  `CreateDate` datetime DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=49999 DEFAULT CHARSET=utf8mb4;

单线程写入

测试用代码(dotnet core C#)

        static void Main(string[] args)
        {
            DapperExtensions.DapperExtensions.SqlDialect = new MySqlDialect();
            DapperExtensions.DapperExtensions.DefaultMapper = typeof(PluralizedAutoClassMapper<>);

            const int total = 10000;
            var Ctx = new MySqlConnection("server=192.168.0.226;database=Awp;uid=root;pwd=abc12345;charset='utf8';Character Set=utf8");
            var st = new Stopwatch();
            st.Start();
            for (var i = 0; i < total; i++)
            {
                var user = new User
                {
                    Username = $"testuser{i}",
                    Password = "12345678901234567890123456789022",
                    Locked = false,
                    CreateDate = DateTime.Now
                };
                Ctx.Insert(user);
            }
            st.Stop();
            Console.WriteLine($"Insert {total} users paid {st.ElapsedMilliseconds / 1000.0} seconds.");
            
        }

测试结果

# Mysql docker cluster(Mysql 5.7)
E:\Workspace\Repos\ConsoleCore\ConsoleCore\bin\Release\netcoreapp2.0>dotnet ConsoleCore.dll
Insert 10000 users paid 46.069 seconds.

# 物理机 Mariadb (5.5.60)
E:\Workspace\Repos\ConsoleCore\ConsoleCore\bin\Release\netcoreapp2.0>dotnet ConsoleCore.dll
Insert 10000 users paid 17.061 seconds.

# Mariadb docker (10.3.15)
E:\Workspace\Repos\ConsoleCore\ConsoleCore\bin\Release\netcoreapp2.0>dotnet ConsoleCore.dll
Insert 10000 users paid 31.782 seconds.

多线程写入

测试用代码(dotnet core C#)

        static void Main(string[] args)
        {
            DapperExtensions.DapperExtensions.SqlDialect = new MySqlDialect();
            DapperExtensions.DapperExtensions.DefaultMapper = typeof(PluralizedAutoClassMapper<>);

            const int total = 10000;
            var st = new Stopwatch();
            st.Start();

            Parallel.For(0, total, i =>
            {
                using (var db = new MySqlConnection("server=192.168.0.226;database=Awp;uid=root;pwd=abcd123456;charset='utf8';Character Set=utf8"))
                {
                    var user = new User
                    {
                        Username = $"testuser{i}",
                        Password = "12345678901234567890123456789022",
                        Locked = false,
                        CreateDate = DateTime.Now
                    };
                    db.Insert(user);
                }
            });
            st.Stop();
            Console.WriteLine($"Insert {total} users paid {st.ElapsedMilliseconds / 1000.0} seconds.");
            
        }

测试结果

# Mysql docker cluster(Mysql 5.7)
E:\Workspace\Repos\ConsoleCore\ConsoleCore\bin\Release\netcoreapp2.0>dotnet ConsoleCore.dll
Insert 10000 users paid 6.601 seconds.

# 物理机 Mariadb (5.5.60)
E:\Workspace\Repos\ConsoleCore\ConsoleCore\bin\Release\netcoreapp2.0>dotnet ConsoleCore.dll
Insert 10000 users paid 4.047 seconds.

# Mariadb docker (10.3.15)
E:\Workspace\Repos\ConsoleCore\ConsoleCore\bin\Release\netcoreapp2.0>dotnet ConsoleCore.dll
Insert 10000 users paid 6.444 seconds.

结论

由于测试环境有限,目前只能看出在docker环境下,集群化并不会导致吞吐量的下降,写入性能较物理机相对较弱,后续有米加机器了再尝试物理机集群。

问题

当我停止了集群,去测试宿主机Mysql和docker mariadb之后,想重新启动集群,结果node1无法启动,日志是显示2019-05-21T22:17:16.289015Z 0 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node. It was not the last one to leave the cluster and may not contain all the updates. To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .,这里需要到相应的卷下编辑grastate.dat文件,修改safe_to_bootstrapsafe_to_bootstrap,例如:

vim /var/lib/docker/volumes/mysql_data1/_data/grastate.dat

修改如下:

# GALERA saved state
version: 2.1
uuid:    e5b2c3e9-7c16-11e9-8115-975d6d143cf4
seqno:   -1
safe_to_bootstrap: 1

这个修改是一次性的,当节点运行后,它还会变回0

额外闲得蛋痛的测试

# 树莓派3B 两台(一台跑脚本,一台单独Mariadb)
root@imud-web01:/home/test# /root/dotnet/dotnet ConsoleCore.dll
Insert 10000 users paid 189.774 seconds.

# 树莓派3B一台跑脚本,Mariadb为1C1G虚拟机)
root@imud-web01:/home/test# /root/dotnet/dotnet ConsoleCore.dll
Insert 10000 users paid 81.676 seconds.

# 树莓派3B一台跑脚本,Mariadb为2C2G虚拟机)
root@imud-web01:/home/test# /root/dotnet/dotnet ConsoleCore.dll
Insert 10000 users paid 88.178 seconds.

# i5-6600K(宿主机跑脚本,Mariadb为1C1G虚拟机)
E:\publish>dotnet ConsoleCore.dll
Insert 10000 users paid 27.46 seconds.

# i5-6600K(宿主机跑脚本,Mariadb为2C2G虚拟机)
E:\publish>dotnet ConsoleCore.dll
Insert 10000 users paid 26.32 seconds.

# 2C2G虚拟机本机
E:\publish>dotnet ConsoleCore.dll
Insert 10000 users paid 22.79 seconds.

引用

1. docker 搭建Mysql集群

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355

推荐阅读更多精彩内容