通过容器技术(docker)部署MySQL读写分离

 更新时间:2026年01月27日 08:49:06   作者:ICT董老师  
Mycat作为开源数据库中间件,在MySQL读写分离架构中发挥核心作用,通过智能代理层实现读写请求的自动路由、负载均衡与故障转移,从而提高系统性能和可用性

项目的目录结构

在 MySQL 读写分离架构中,Mycat 作为开源数据库中间件,核心作用是作为智能代理层,透明化实现读写请求的自动路由、负载均衡与故障转移

以下是其具体作用与技术实现的分步解析:

智能路由:读写请求的精准分发

读写分离机制

Mycat 通过解析 SQL 语句,自动识别写操作(如 INSERT/UPDATE/DELETE)和读操作(SELECT),并将写请求路由至主库,读请求分发至从库。例如:

  • 写操作直接发送至配置的 <writeHost> 节点(主库)。
  • 读操作根据负载均衡策略(如 balance="3")分发至 <readHost> 节点(从库)。

配置示例(schema.xml)

xml<dataHost name="node1" balance="3">
  <writeHost host="master_ip" url="master_ip:3306" user="root" password="123"/>
  <readHost host="slave1_ip" url="slave1_ip:3306" user="root" password="123"/>
  <readHost host="slave2_ip" url="slave2_ip:3306" user="root" password="123"/>
</dataHost>
  • balance="3" 表示所有读请求随机分发至从库,主库不承担读压力。

​负载均衡:优化读操作分布

策略支持

Mycat 提供多种负载均衡模式,通过 balance 属性配置:

  • balance="0":所有读请求发送至当前可用的主库(不开启读写分离)。
  • balance="1":读请求在全部从库与备用主库间轮询。
  • balance="2":读请求随机分发至主库或从库。
  • balance="3":读请求仅分发至从库(推荐模式,避免主库/负载)。

动态权重调整

可通过 weight 属性为从库分配权重,实现非对称流量分配(如高性能从库承担更多读请求)。

故障转移:保障高可用性

主库故障切换

  • 自动切换:配置 switchType="1" 时,Mycat 通过心跳检测(如 select user())监控主库状态,若主库宕机,自动将写请求路由至备用主库。
  • 手动切换:通过管理命令(如 switch writeHost)触发主从角色切换。

从库冗余与容错

  • 配置多个从库,当某一从库故障时,Mycat 自动将其从负载均衡池移除,剩余从库继续提供服务。

数据同步:依赖MySQL原生复制

主从复制机制

  • Mycat 不参与数据同步,而是基于 MySQL 的主从复制(Binlog + Relay Log)实现数据一致性。
  • 主库通过 Binlog 记录变更,从库通过 IO 线程拉取并应用日志。

一致性保障

  • 异步复制:主库提交后即返回成功,从库延迟可能影响读一致性(需业务容忍短暂延迟)。
  • 半同步复制:通过插件(如 rpl_semi_sync_master)确保至少一个从库收到日志后再返回成功,平衡性能与一致性。

配置与运维简化

集中化管理

  • 通过 schema.xml 统一配置逻辑库、数据节点及路由规则,避免逐台修改数据库配置。
  • 支持动态重载配置(reload @@config),无需重启 Mycat 即可生效。

监控与日志

  • 提供实时日志(mycat.log)记录路由决策、慢查询及错误信息。
  • 集成 Prometheus 等监控系统,可视化展示集群状态(如 QPS、连接数、主从延迟)。

扩展能力:水平分片与多租户支持

水平分片

Mycat 支持按范围、哈希等策略对单表进行分片(如 rule="auto-sharding-long"),突破单机存储与性能瓶颈。

多租户隔离

通过逻辑库(<schema>)隔离不同业务的数据,实现多租户环境下的资源独立与权限控制。

以下为各配置文件的详细内容

50-server.cnf

[server]
[mysqld]
user=mysql

#skip-networking=0
#bind-address = 0.0.0.0
#require_secure_transport = ON

pid-file=/run/mysqld/mysqld.pid
socket=/run/mysqld/mysqld.sock
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
lc-messages-dir=/usr/share/mysql
query_cache_size=16M
log_error=/var/log/mysql/error.log
server-id=2
log_bin=mysql-bin
expire_logs_days=10
binlog_ignore_db=mysql
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
[embedded]
[mariadb]
[mariadb-10.3]

docker-compose.yml

version: "3.8"
services:
  db1:
    image: ubuntu:db1
    build:
      context: .
      dockerfile: MDockerfile
    networks:
      - db_network

  db2:
    image: ubuntu:db2
    build:
      context: .
      dockerfile: SDockerfile
    networks:
      - db_network

  mycat:
    image: ubuntu:mycat
    build:
      context: .
      dockerfile: MycatDockerfile

    ports:
      - 8066:8066
      - 9066:9066

    networks:
      - db_network

networks:
  db_network:
    driver: bridge

MDockerfile

FROM ubuntu:latest
LABEL maintainer="dong"
COPY sources.list /etc/apt
RUN apt-get update && apt-get dist-upgrade -y \
    && apt-get install mariadb-server -y
COPY 50-server.cnf /etc/mysql/mariadb.conf.d/50-server.cnf
RUN /etc/init.d/mariadb start \
    && mysql -uroot -e"create user'root'@'%'identified by'123456'" \
    && mysql -uroot -e"grant all on *.* to 'root'@'%'" \
    && mysql -uroot -e"create database student_manager" \
    && mysql -uroot -e"create table student_manager.student(id int primary key auto_increment,name varchar(20))" \
    && mysql -uroot -e"insert into student_manager.student values(null,'zhangsan')"

EXPOSE 3306
CMD /usr/bin/mysqld_safe

/MycatDockerfile

FROM ubuntu:latest
LABEL maintainer="dong"
ADD sources.list /etc/apt
ADD Mycat-server-1.6.7.5-release-20200410174409-linux.tar.gz /root

RUN apt-get update && apt-get dist-upgrade -y && apt-get install openjdk-8-jdk -y

RUN apt-get install supervisor -y
ADD schema.xml /root/mycat/conf
ADD server.xml /root/mycat/conf
ADD schema.dtd /root/mycat/conf
ADD supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]

schema.dtd

    name            CDATA #REQUIRED
    checkSQLschema  (true|false) "true"
    sqlMaxLimit     CDATA #IMPLIED
    dataNode        CDATA #REQUIRED
>

<!-- 定义 dataNode 元素 -->
<!ELEMENT dataNode EMPTY>
<!ATTLIST dataNode
    name        CDATA #REQUIRED
    dataHost    CDATA #REQUIRED
    database    CDATA #REQUIRED
>

<!-- 定义 dataHost 元素 -->
<!ELEMENT dataHost (heartbeat, writeHost+)>
<!ATTLIST dataHost
    name            CDATA #REQUIRED
    maxCon          CDATA #REQUIRED
    minCon          CDATA #REQUIRED
    balance         (0|1|2|3) #REQUIRED
    dbType          (mysql|oracle|pg) #REQUIRED
    dbDriver        (native|jdbc) #REQUIRED
    writeType       (0|1) #REQUIRED
    switchType      (1|2|3) #REQUIRED
    slaveThreshold  CDATA #REQUIRED
>

<!-- 定义 heartbeat 元素 -->
<!ELEMENT heartbeat (#PCDATA)>

<!-- 定义 writeHost 元素 -->
<!ELEMENT writeHost (readHost*)>
<!ATTLIST writeHost
    host    CDATA #REQUIRED
    url     CDATA #REQUIRED
    user    CDATA #REQUIRED
    password CDATA #REQUIRED
>

<!-- 定义 readHost 元素 -->
<!ELEMENT readHost EMPTY>
<!ATTLIST readHost
    host    CDATA #REQUIRED
    url     CDATA #REQUIRED
    user    CDATA #REQUIRED
    password CDATA #REQUIRED
>

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns="http://io.mycat/">
    <schema name="USERDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1"/>
    <dataNode name="dn1" dataHost="localhost1" database="student_manager"/>
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
             dbType="mysql" dbDriver="native" writeType="0"
             switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="hostM1" url="db1:3306" user="root" password="123456">
            <readHost host="hostS1" url="db2:3306" user="root" password="123456"/>
        </writeHost>
    </dataHost>
</mycat:schema>

SDockerfile

FROM ubuntu:latest
LABEL maintainer="dong"
COPY sources.list /etc/apt
RUN apt-get update && apt-get dist-upgrade -y \
    && apt-get install mariadb-server -y \
    && sed -i 's/bind-address/#bind-address/g' /etc/mysql/mariadb.conf.d/50-server.cnf \
    && /etc/init.d/mariadb start \
    && mysql -uroot -e"change master to master_host='db1', \
       master_user='root',master_password='123456'" \
    && mysql -uroot -e"start slave"

EXPOSE 3306
CMD /usr/bin/mysqld_safe

server.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
    <property name="nonePasswordLogin">0</property>
    <property name="ignoreUnknownCommand">0</property>
    <property name="useHandshakeV10">1</property>
    <property name="removeGraveAccent">1</property>
    <property name="useSqlStat">0</property>
    <property name="useGlobalTableCheck">0</property>
    <property name="sqlExecuteTimeout">300</property>
    <property name="sequenceHandlerType">1</property>
    <property name="sequenceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>
    <property name="subqueryRelationshipCheck">0</property>
    <property name="sequenceHandlerClass">io.mycat.route.sequence.handler.HttpIncrSequenceHandler</property>
    <property name="processorBufferPoolType">0</property>
    <property name="handleDistributedTransactions">0</property>
    <property name="useOffHeapForMerge">0</property>
    <property name="memoryPageSize">8m</property>
    <property name="spillsFileBufferSize">1m</property>
    <property name="useStreamOutput">0</property>
    <property name="systemReserveMemorySize">384m</property>
    <property name="useZKSwitch">false</property>
    <property name="strictTxIsolation">0</property>
    <property name="parallelExecute">0</property>
</system>
<user name="root">
    <property name="password">123456</property>
    <property name="schemas">USERDB</property>
    <property name="usingDecrypt">0</property>
</user>
</mycat:server>

sources.list

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb http://mirrors.aliyun.com/ubuntu jammy main restricted
# deb-src http://mirrors.aliyun.com/ubuntu jammy main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://mirrors.aliyun.com/ubuntu jammy-updates main restricted
# deb-src http://mirrors.aliyun.com/ubuntu jammy-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb http://mirrors.aliyun.com/ubuntu jammy universe
# deb-src http://mirrors.aliyun.com/ubuntu jammy universe
deb http://mirrors.aliyun.com/ubuntu jammy-updates universe
# deb-src http://mirrors.aliyun.com/ubuntu jammy-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb http://mirrors.aliyun.com/ubuntu jammy multiverse
# deb-src http://mirrors.aliyun.com/ubuntu jammy multiverse
deb http://mirrors.aliyun.com/ubuntu jammy-updates multiverse
# deb-src http://mirrors.aliyun.com/ubuntu jammy-updates multiverse

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://mirrors.aliyun.com/ubuntu jammy-backports main restricted universe multiverse
# deb-src http://mirrors.aliyun.com/ubuntu jammy-backports main restricted universe multiverse

deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted
# deb-src http://security.ubuntu.com/ubuntu/ jammy-security main restricted
deb http://security.ubuntu.com/ubuntu/ jammy-security universe
# deb-src http://security.ubuntu.com/ubuntu/ jammy-security universe
deb http://security.ubuntu.com/ubuntu/ jammy-security multiverse
# deb-src http://security.ubuntu.com/ubuntu/ jammy-security multiverse

supervisord.conf

  • 该文件是 supervisor 服务的配置文件,其中定义了启动 mycat 的指令。
  • supervisor 是一个进程管理程序,它可以将一个指令变为服务,并监控服务状态。
  • 将启动 mycat 的指令通过 supervisor 启动后,指令不退出,可以保持容器不关闭。
[supervisord]
nodaemon=true

[program:mycat]
command=/bin/bash /root/mycat/bin/mycat start

启动服务并运行

使用指令docker compose up -d启动服务并在后台运行

通过访问主机的8066端口使用数据库服务,查询数据,并插入一条数据。由于mycat假定在生产环境中均处于内网,因此不支持mysql 8客户端默认加密登录方式,需要添加参数–default-auth=mysql_native_password,方可登录。

mysql --default-auth=mysql_native_password -h 127.0.0.1 -P8066 -uroot -p123456

insert into student values(null,'lisi')

登录数据库后,通过show databases查看当前所有数据库,在mycat上,可以查询到schema.xml中所定义的逻辑库USERDB,该逻辑库中保存了db1的student_manager库中的student表,操作USERDB中的student表即可操作db1的student_manager中的student表。

通过访问主机的9066端口查看读写分离集群运行情况。

mysql --default-auth=mysql_native_password -h 127.0.0.1 -P9066 -uroot -p123456 \
-e"show @@datasource"

总结

Mycat 在 MySQL 读写分离中,通过智能路由、负载均衡、故障转移、数据同步兼容及集中化配置,构建了高性能、高可用的数据库中间层。其价值体现在:

  • 性能提升:分摊读写压力,提升系统吞吐量。
  • 成本优化:通过从库横向扩展,避免垂直升级主库的高昂成本。
  • 运维简化:统一管理数据库集群,降低主从切换、分片扩容等操作的复杂度。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 使用Docker Compose编排本地容器的详细步骤

    使用Docker Compose编排本地容器的详细步骤

    Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具,通过 docker-compose.yml 文件,你可以轻松地将多个本地容器组合成一个完整的应用,本文给大家介绍了使用Docker Compose编排本地容器的详细步骤,需要的朋友可以参考下
    2025-09-09
  • Docker Stack部署Java Web项目的实现

    Docker Stack部署Java Web项目的实现

    本文主要介绍了Docker Stack部署Java Web项目的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • docker配置阿里云镜像仓库的实现

    docker配置阿里云镜像仓库的实现

    本文主要介绍了docker配置阿里云镜像仓库的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Docker 镜像分层及dockerfile 编写技巧

    Docker 镜像分层及dockerfile 编写技巧

    Docker镜像是由特殊的文件系统叠加而成,镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,这篇文章主要介绍了Docker 镜像分层及dockerfile 编写,需要的朋友可以参考下
    2022-01-01
  • docker上安装和卸载MySQL数据库详细图文教程

    docker上安装和卸载MySQL数据库详细图文教程

    Docker是一种容器化技术,可以快速方便地部署和管理应用程序,Mysql 是一个开源的关系型数据库管理,系统这篇文章主要给大家介绍了关于docker上安装和卸载MySQL数据库的相关资料,需要的朋友可以参考下
    2024-05-05
  • docker容器中切换用户,提示权限不足的解决

    docker容器中切换用户,提示权限不足的解决

    这篇文章主要介绍了docker容器中切换用户,提示权限不足的解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • docker如何快速搭建几个常用的第三方服务详解

    docker如何快速搭建几个常用的第三方服务详解

    这篇文章主要给大家介绍了关于利用docker如何快速搭建几个常用的第三方服务的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • 解决运行Docker镜像报错:version `GLIBC_2.32‘ not found问题

    解决运行Docker镜像报错:version `GLIBC_2.32‘ not found

    文章介绍了解决Docker镜像运行时因GLIBC版本不匹配导致的错误,建议使用AlpineLinux作为基础镜像,并在其中安装所需的运行时库,作者还分享了个人经验,提醒读者尝试其他方法无效后可以寻求帮助
    2024-12-12
  • Linux新建用户并允许docker及docker基本命令

    Linux新建用户并允许docker及docker基本命令

    这篇文章给大家介绍了Linux新建用户并允许docker及docker的容器创建及基本命令讲解,需要的朋友参考下本文吧
    2017-12-12
  • Docker容器内存限制的方法

    Docker容器内存限制的方法

    本篇文章主要介绍了Docker容器内存限制的方法,具有一定的参考价值,有兴趣的可以了解一下。
    2017-01-01

最新评论