一个小实验,验证一个大受欢迎数据库的容器化
时下大受欢迎的数据库
笔者在IBM工作期间,曾进行过大量Oracle RAC的功能性测试,尤其是与双活存储的配合问题。而时下,随着技术的发展,分布式数据库越来越受到关注。MySQL已经排到了第二名:(参照https://db-engines.com/en/ranking):
而一份针对开发者的数据库调查显示,MySQL是最受欢迎的。
而目前,Docker、K8S技术非常火;那么,能否将大火的MySQL部署在大火的Docker+K8S以及时下挺火的Openshift中呢?
接下来,本文会对MySQL集群进行介绍,并通过实验方式,展示MySQL集群容器化的实现。
Mysql集群的实现方式
目前,MySQL集群实现方式主要有以下两种:
1. 主从复制
2. 基于Galera协议复制
基于Galera协议复制的方式,对应能损耗较大,本文篇幅有限,暂不进行讨论。
基于主从复制的Mysql集群,有三种配置方式。
- 一主一从
2. Master High Availability集群(MHA)
MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
3. Master-Master replication manager for MySQL(MMM)
MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM使用Perl语言开发,主要用来监控和管理MySQL Master-Master(双主)复制,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热,可以说MMM这套脚本程序一方面实现了故障切换的功能,另一方面其内部附加的工具脚本也可以实现多个slave的read负载均衡。
在以上三种模式中,双节点主从配置最简单高效;MHA最为成熟,MMM比较复杂,不建议使用。本文在接下来的实验中,先介绍基于容器的一主一从方式。
一主一从MySQL集群容器化实现
在实验环境中,笔者使用两个节点的Openshift 3.6(一个Opensift Master节点、一个Opensift Node节点),两个节点分别部署MySQL的Master和Slave。端口采用HostPort的方式(3306)。存储采用HostPath的方式,直接使用宿主机的本地目录:
首先,配置一个MySQL配置 Json文件(由于内容较多,只节选关键点)。
{
"kind": "Template",
"apiVersion": "v1",
"metadata": {
"name": "mysql-replication-openshift",
"annotations": {
"description": "MySQL Replication for OpenShift",
"iconClass": "icon-database",
"tags": "database,mysql,replication"
}
},
"parameters": [
{
"name": "MYSQL_MASTER_SERVICE_NAME",
"description": "Service name for MySQL master service",
"value": "mysql-master"
},
{
"name": "MYSQL_MASTER_USER",
"description": "The username used for master-slave replication",
"value": "master"
},
{
"name": "MYSQL_MASTER_PASSWORD",
"description": "The password used for the MYSQL_MASTER_USER",
"generate": "expression",
"from": "[a-zA-Z0-9]{12}"
},
{
"name": "MYSQL_USER",
"description": "The username that clients will use to connect to the server",
"value": "user"
},
{
"name": "MYSQL_PASSWORD",
"description": "The password for the MYSQL_USER",
"generate": "expression",
"from": "[a-zA-Z0-9]{12}"
},
{
"name": "MYSQL_DATABASE",
"description": "The name of the database that will be created and replicated",
"value": "userdb"
},
{
"name": "MYSQL_ROOT_PASSWORD",
"description": "The password for the root user",
"generate": "expression",
"from": "[a-zA-Z0-9]{12}"
},
{
"name": "VOLUME_CAPACITY",
"displayName": "Volume Capacity",
"description": "Volume space available for data, e.g. 512Mi, 2Gi.",
"value": "1Gi",
"required": true
}
],
"objects": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "${MYSQL_MASTER_SERVICE_NAME}",
"labels": {
"name": "mysql-master"
}
},
"spec": {
"ports": [
{
"port": 3306
}
],
"selector": {
"name": "mysql-master"
},
"clusterIP": "None"
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "mysql-slave",
"labels": {
"name": "mysql-slave"
}
},
"spec": {
"ports": [
{
"port": 3306
}
],
"selector": {
"name": "mysql-slave"
},
"clusterIP": "None"
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "mysql-master"
},
"spec": {
"strategy": {
"type": "Recreate"
},
"triggers": [
{
"type": "ConfigChange"
}
],
"replicas": 1,
"selector": {
"name": "mysql-master"
},
"template": {
"metadata": {
"labels": {
"name": "mysql-master"
}
},
"spec": {
"volumes": [
{
"name": "mysql-master-data",
"hostPath": {
"path": "/opt/mysql_data"
{
"name": "mysql-slave-data",
"mountPath": "/var/lib/mysql/data"
}
],
"imagePullPolicy": "IfNotPresent"
}
],
"hostNetwork": true,
"nodeSelector": {
"mysql-replica-node": "slave"
接下来,使用json文件创建template,然后部署template,生成两个pod:
MySQL集群创建成功:
接下来,查看Service ,因为容器使用HostNetwork方式,所以Endpoint的IP就是Openshift节点的IP。
Master:
Slave:
登录MySQL master的容器:
查看主节点状态:
在master中创建一个用户用于复制:
create user 'david'@'192.168.137.11' identified by '123456';
在master机上为slave机添加一同步帐号: grant replication slave on *.* to 'david'@'192.168.137.10' identified by '123456';
查看MySQL master配置文件:
binlog_do_db 指定需要同步的数据库,如果没有本行,即表示同步所有的数据库。
修改MySQL Slave的配置文件:
修改成如下内容,指定Master的IP,负责同步的MySQL账号、密码:
在Slave节点上执行,立即生效:
mysql> change master to master_host='192.168.137.11',master_user='david',master_password='123456';
确保从slave,用复制账号david可以成功登录master:
然后在slave上查看复制状态,一定要确保红色标识框里的两行全都是Yes状态:
如果 Slave_SQL_Running这一行是no,通常需要做数据同步:
在slave节点先执行 stop slave,然后在slave上执行(命令行中标黄部分的数值,在Master上执行show master status可以查看):
mysql> change master to master_host='192.168.137.11', master_user='david', master_password='123456', master_port=3306, master_log_file='mysql-bin.000006', master_log_pos=1172;
然后启动slave,再次查看,通常可以解决问题。
创建表测试,首先查看哪些数据库目前在复制状态:
使用mysql 这个database:
分别在master和slave上查看tables,得到结果相同,都只是包含默认的系统表:
接下来,在Master创建一个新的table zdavid:
到Slave上查看表,马上就可以看到:
我们查看Slave上的mysql log:
我们可以看到,slave执行了与Master上相同的SQL:
接着,在master上给tables插入一行数据:
到slave上查看数据库表,可以看到内容是一致的:
查看slave上mysql的log:
通过本文这个小实验,大家应该对MySQL在Openshift下的运行有简单的了解。至于很多人担心的容器化MySQL的性能问题,主要取决于底层持久存储的性能。
参考文献:
https://db-engines.com/en/ranking
http://www.cnblogs.com/lben/archive/2012/11/19/2777632.html
http://www.cnblogs.com/gomysql/p/3671896.html
- list.add(),向List集合插入对象报空指针异常
- 使用angular4和asp.net core 2 web api做个练习项目(三)
- 即学即用系列一:纯函数
- Java之StringBuffer,StringBuilder,Math,Date,SimpleDateFormat,UUID,File
- React编程思想
- 前台分页,以及类别选择
- 使用angular4和asp.net core 2 web api做个练习项目(二), 这部分都是angular
- 数据库 105道题目整理与吐血总结
- 使用angular4和asp.net core 2 web api做个练习项目(一)
- =.=
- JavaScript经典面试题之for循环click
- 学习docker on windows (1): 为什么要使用docker
- 使用VS Code开发asp.net core (下)
- 使用VS Code开发asp.net core (上)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 震惊! 再也不怕蹭网被发现了!
- 国标GB28181协议客户端EasyGBS国标视频平台级联EasyNVR:EasyNVR到EasyGBS上是如何注册及注销的?
- git全局忽略文件配置
- 2018-10-16近期vue开发总结
- 有赞埋点实践
- 树莓派配置LEDE(openwrt衍生版)拨号
- Android 沉浸式解析和轮子使用
- 腾讯云CDN使用(接入方式:COS源)
- 工作流引擎在有赞 DevOps 中的实践
- 微信带备注群发真好玩!
- 微信机器人-定时群发+智能回复
- 治电EggJS开发规范
- jenkins远程部署项目
- puppeteer爬取house365租房数据
- 视频上云网关平台EasyNTS组网硬件设备连接断线无法重连,该如何解决?