Rainbond部署Mysql主从集群应用说明

简介: 本文简要说明了Mysql主从集群的工作原理和容器化部署的要点和运行方式,并结合Rainbond云应用平台进行部署。

Mysql主从同步原理

1028337-20181204102924349-2125007754.png

1)在Slave 服务器上执行sart slave命令开启主从复制开关,开始进行主从复制。

2)此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接master服务器,并请求从执行binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容。

3)Master服务器接收到来自Slave服务器的IO线程的请求后,其上负责复制的IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的IO线程。返回的信息中除了binlog中的下一个指定更新位置。

4)当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(Mysql-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容。

5)Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点。

Mysql主从同步注意事项

  • master节点和slave节点的uuid不同
  • master节点和slave节点的server_id不同
  • slave节点需要自动执行向master节点注册的操作

制作Mysql容器镜像

同一镜像创建不同容器的uuid

用同一mysql镜像创建mysql主从集群时,发现每台mysql服务的uuid都是相同的,是因为在数据初始化时将uuid写在了/var/lib/mysql/auto.cnf文件中,造成每个容器的uuid都是相同的。

为了解决不同容器的uuid不同问题,需要在mysql启动生成配置文件后并在启动前 随机生成一个uuid写入到/var/lib/mysql/auto.cnf,这样就可以确保同一镜像生成的容器的uuid都不相同。

为了达成这一目标,我们修改了mysql镜像自带的启动脚本/usr/local/bin/docker-entrypoint.sh

if [ ! -d "$DATADIR/mysql" ]; then
        file_env 'MYSQL_ROOT_PASSWORD'
        if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
            echo >&2 'error: database is uninitialized and password option is not specified '
            echo >&2 '  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
            exit 1
        fi

        mkdir -p "$DATADIR"

        echo 'Initializing database'
        "$@" --initialize-insecure
        echo 'Database initialized'
                # 位于mysql启动脚本90行,新增如下语句
                psd="/proc/sys/kernel/random/uuid"
                str=$(cat $psd)
                uuid="server-uuid="${str}
                echo "[auto]" > /var/lib/mysql/auto.cnf
                echo $uuid >> /var/lib/mysql/auto.cnf

同一服务不同实例的server_id处理

用同一MYSQL镜像创建MYSQL主从集群时,如何确保每个MYSQL服务的server_id不同?

k8s在创建容器时,会为每个容器创建创建一个主机名( 如:gr78648d-0),创建多个容器后面的数字会依次递增,所以可以利用这一特性生成不同的server_id(主机名数字部分 + 指定数字),然后在maser和slave使用不同的数字即可。

从库自动初始化

创建slave数据库时,我们希望salve应用下的每个实例,在扩容后,会自动向主库注册。

这需要salve应用中实例初始化时,自动执行指定的SQL脚本。这要借助于官方MYSQL镜像所提供的特定功能:数据库初始化时,会自动读取/docker-entrypoint-initdb.d/中*.sql 文件并执行。

为了实现上述两个目标,我们在镜像的自定义启动脚本 /run/docker-entrypoint.sh进行指定:

# define server_id and anyother cluster configuration
# 通过环境变量来区分当前镜像创建主库或从库
if [ ${MYSQL_ROLE} == "master" ];then
   # 借助有状态应用主机名特点,截取其中的数字
   server_id=${HOSTNAME#*-}
   # 主库ID设置为1
   MYSQLC_MYSQLD_SERVER_ID=`expr $server_id + 1`
   export MYSQLC_MYSQLD_SERVER_ID
   # 指定生成主库特定的配置
   export MYSQLC_MYSQLD_binlog_ignore_db=mysql
   export MYSQLC_MYSQLD_log_bin=mysql-bin
else 
   # 借助有状态应用主机名特点,截取其中的数字
   server_id=${HOSTNAME#*-}
   # 从库各实例ID,从2开始排序
   MYSQLC_MYSQLD_SERVER_ID=`expr $server_id + 2`
   export MYSQLC_MYSQLD_SERVER_ID
   # 指定生成从库特定配置
   export MYSQLC_MYSQLD_replicate_ignore_db=mysql
   export MYSQLC_MYSQLD_log_bin=mysql-bin
   # 将从库所需要的初始化脚本模版拷贝到指定目录
   cp -a /tmp/init-slave.sql /docker-entrypoint-initdb.d/
   # 根据实例特定的环境变量,对初始化脚本模版进行更改
   sed -i -r -e "s/MYSQL_ROOT_PASSWORD/${MYSQL_ROOT_PASSWORD}/g" \
             -e "s/MYSQL_USER/${MYSQL_USER}/g" /docker-entrypoint-initdb.d/init-slave.sql
fi

关于脚本中通过环境变量生成指定配置,参考项目 env2file

制作镜像的Dockerfile解析

FROM percona:5.7.23-stretch
LABEL creater="barnett"
ENV MYSQL_VERSION=5.7.23
ENV TZ=Asia/Shanghai

RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list; \
    rm -rf /etc/apt/sources.list.d/percona.list && apt-get update; \
    apt-get install -y --no-install-recommends wget net-tools vim; \
    rm -rf /var/lib/apt/lists/*; \
    wget -O /usr/local/bin/env2file -q https://github.com/barnettZQG/env2file/releases/download/0.1.1/env2file-linux; \
    chmod +x /usr/local/bin/env2file;
# 自定义启动脚本
ADD docker-entrypoint.sh /run/docker-entrypoint.sh
# mysql官方启动脚本
ADD ./run/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
ADD ./run/mysqld.cnf /etc/mysql/percona-server.conf.d/mysqld.cnf
# 拷贝slave初始化脚本模版到镜像中,以备调用
ADD ./sql /tmp/
EXPOSE 3306
VOLUME ["/var/lib/mysql", "/var/log/mysql"]
ENV MYSQL_ROOT_PASSWORD=changeme
ENTRYPOINT [ "/run/docker-entrypoint.sh" ]
CMD [ "mysqld" ]

创建并配置mysql-master服务

创建mysql-master服务组件

代码地址:https://github.com/goodrain-apps/percona-mysql.git?dir=5.7

代码分支:cluster

通过Dockerfile创建服务 参考文档 基于Dockerfile源码创建服务

mysql-cluster1.png

mysql-master服务 相关配置

mysql-cluster2.png

  • 开启3306端口对内服务,并更改使用别名为MYSQL
  • 配置关键环境变量
环境变量 说明
MYSQL_ROOT_PASSWORD changeme(默认)自行指定 root密码
MYSQL_USER 自行指定,如admin mysql工作用户
MYSQL_PASSWORD 自行指定 工作用户密码
MYSQL_DATABASE 自行指定 初始化生成数据库
MYSQL_ROLE master 指定角色

其中 除MYSQL_ROLE外,其他环境变量要在服务创建完成后,转移到连接信息中去。

  • 部署属性中,修改应用类型为 有状态应用

创建Slave服务

创建mysql-slave服务组件

创建方式同mysql-master服务组件一致。

mysql-slave服务 相关配置

区别于mysql-master服务组件,mysql-slave服务组件配置如下:

  • 开启3307端口对内服务,并更改使用别名为 MYSQL_SLAVE
  • 配置环境变量
环境变量 说明
MYSQLC_MYSQLD_PORT 3307 mysql-slave监听3307端口
  • mysql-slave服务依赖于mysql-master服务

mysql-slave服务组件,可以随意扩容,脚本中写好的逻辑会让其自动向mysql-master注册。

至此,一个基本的 MYSQL主从集群就已经搭建完成,如需要发布到应用市场供随时下载使用,请参考应用分享与发布

读写分离

机制

MYSQL主从集群的一个好处就是,可以配置master库负责写入,slave库负责查询,slave自动从master同步数据的读写分离结构。

如果设置得当,这样的结构可以大幅度提高数据库性能的同时,降低主库的压力。

使用方法

如果用户的业务程序已经支持读写分离,那么只需要设置:

  • 数据库写入地址为mysql-master服务地址,如果使用Rainbond服务依赖,则可以用 ${MYSQL_HOST}:${MYSQL_PORT}的方式指定连接地址。
  • 数据库查询地址为mysql-slave服务地址,如果使用Rainbond服务依赖,则可以用${MYSQL_SLAVE_HOST}:${MYSQL_SLAVE_PORT}的方式指定连接地址。

如果用户的业务程序不支持读写分离,那么就要靠支持读写分离的中间件实现。

Atlas中间件

Atlas是由奇虎360开源的数据库中间件,基于mysql官方提供的mysql-proxy改良而来。通过将mysql-proxy的LUA脚本,用C语言重新实现,Atlas提供了比mysql-proxy更强大的性能。经由中间件的代理,用户只需要配置数据库连接地址为 Atlas 服务地址,对于数据库的写入和查询,则由 Atlas 来管理。

详细了解Atlas

我们提供的docker化的Atlas组件,用户可以直接基于Dockerfile源码构建这个项目:

Atlas-docker项目地址

Rainbond已经发布的 Mysql主从集群 应用,已经集成了该中间件。

高阶实现

当前架构缺点

目前搭建的 MYSQL主从集群,是一个master节点,对接多个slave节点。这样的架构在小规模集群下没有问题。但是如果集群规模很大、slave节点过多的时候,由master向所有slave节点同步数据这一过程将变成性能的瓶颈。

架构的优化

当用户完全掌握了如何基于Rainbond搭建MYSQL主从集群后,可以自己尝试,专门创建一个slave节点,作为数据同步节点使用。

该节点向上对接 master节点,来同步数据;向下对接slave集群,分发由master节点同步来的数据。

这样做的好处是,master节点只需要对接一个数据同步节点来同步数据,可以更加专注于数据的写入。其他slave节点从数据同步节点来同步数据。

master-new-arch.png

如果有用户实现了这种优化,欢迎将其分享到应用市场中,供更多的人来使用。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
关系型数据库 MySQL 分布式数据库
安全可靠的PolarDB V2.0 (兼容MySQL)产品能力及应用场景
PolarDB分布式轻量版采用软件输出方式,能够部署在您的自主环境中。PolarDB分布式轻量版保留并承载了云原生数据库PolarDB分布式版技术团队深厚的内核优化成果,在保持高性能的同时,显著降低成本。
961 141
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
11月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
1007 6
|
11月前
|
存储 关系型数据库 MySQL
MySQL Docker 容器化部署全指南
MySQL是一款开源关系型数据库,广泛用于Web及企业应用。Docker容器化部署可解决环境不一致、依赖冲突问题,实现高效、隔离、轻量的MySQL服务运行,支持数据持久化与快速迁移,适用于开发、测试及生产环境。
1401 4
|
存储 关系型数据库 MySQL
MYSQL数据加密压缩函数应用实战指南。
总的来说,加密和压缩是维护MySQL数据库中数据安全性和效率的有效手段。使用时需权衡性能与安全,合理应用加密和压缩函数。在设计数据库架构时要考虑到加密字段的查询性能,因为加密可能使得一些索引失效。压缩数据能有效减少存储空间的占用,但在服务器负载较高时应避免实时压缩和解压,以免影响总体性能。
377 10
|
Java 关系型数据库 MySQL
在Linux平台上进行JDK、Tomcat、MySQL的安装并部署后端项目
现在,你可以通过访问http://Your_IP:Tomcat_Port/Your_Project访问你的项目了。如果一切顺利,你将看到那绚烂的胜利之光照耀在你的项目之上!
650 41
|
关系型数据库 MySQL 数据库
为什么 MySQL 不推荐用 Docker 部署?
本文探讨了MySQL是否适合容器化的问题,分析了Docker容器在数据安全、性能瓶颈、状态管理及资源隔离等方面的挑战,并指出目前主流分布式数据库如TDSQL和OceanBase仍倾向于部署在物理机或KVM上。
527 0
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
898 17
|
Java 关系型数据库 MySQL
在Linux操作系统上设置JDK、Tomcat、MySQL以及J2EE后端接口的部署步骤
让我们总结一下,给你的Linux操作系统装备上最强的军队,需要先后装备好JDK的弓箭,布置好Tomcat的阵地,再把MySQL的物资原料准备好,最后部署好J2EE攻城车,那就准备好进军吧,你的Linux军团,无人可挡!
659 18
|
开发框架 关系型数据库 Java
Linux操作系统中JDK、Tomcat、MySQL的完整安装流程以及J2EE后端接口的部署
然后Tomcat会自动将其解压成一个名为ROOT的文件夹。重启Tomcat,让新“植物”适应新环境。访问http://localhost:8080/yourproject看到你的项目页面,说明“植物”种植成功。
421 10

推荐镜像

更多