docker搭建mysql集群
搭建mysql集群
NaN. 单机版的 MySQL 存在单点问题,且在高并发场景下性能会急剧下降。所以,生产中对于 MySQL 都是使用读写分离的主从集群。既保证了数据的安全性,又提升了性能。下面要使用 Docker 搭建一个“一主一从”的 MySQL 读写分离集群。
NaN. 由于mysql版本差异性,所以可能存在配置文件错误导致容器无法运行,可以使用docker logs <container_name>
查看错误信息。
NaN. 首先我们需要创建一个 Docker 网络,使 MySQL 主库和从库能够在同一个网络中通信:docker network create mysql-cluster-net
。
> chatgpt推荐创建 Docker 网络(使用默认 bridge 可以通过`--link`参数配置定向连接解决):
>
> NaN. **容器间通信便捷**: 当容器在同一个 Docker 网络中时,它们可以通过容器名称相互通信。例如,`mysql-slave` 可以通过容器名 `mysql-master` 来访问主库,而不需要通过 IP 地址。这极大地简化了配置。
>
> NaN. **避免使用动态 IP**: Docker 分配给容器的 IP 地址可能会变化。使用容器名称而不是硬编码的 IP 地址可以确保容器即使重新启动后也能保持连接,避免 IP 地址的管理问题。
>
> NaN. **网络隔离和安全性**: Docker 网络可以为容器提供额外的隔离。通过创建一个专用的网络(如 `mysql-cluster-net`),可以确保你的 MySQL 主从实例与外部服务隔离,防止非预期访问和数据泄露。
>
> NaN. **简化主从复制配置**: 在主从配置时,你需要指定 `MASTER_HOST`,如果没有 Docker 网络,你必须使用主库的 IP 地址。而通过 Docker 网络,主库和从库可以通过名称互相访问,简化了配置。
>
NaN. 启动主库容器拉取并启动 MySQL 主库容器,并配置好主库的必要参数。
NaN. 编辑主库的配置文件 my.cnf
(位于 ~/mysql/master/conf/my.cnf
),配置以下内容:
NaN. 由于修改了 mysql 配置,所以需要重启 master 容器,以使新配置生效:docker restart mysql-master
。
NaN. 接着,启动 MySQL 从库容器,并配置好从库的相关参数。
NaN. 编辑从库的配置文件 my.cnf
(位于~/mysql/slave/conf/my.cnf
),确保包含以下内容:
NaN. 完成配置后,重启从库容器:docker restart mysql-slave
NaN. 在主库( mysql-master )上创建复制用户:进入主库容器,创建用于主从复制的用户并赋予它权限。
> NaN. `grant replication slave, replication client`:授予用户 `slave` 两个复制相关的权限:
>
> * `replication slave`:允许该用户读取二进制日志(用于复制)。
>
> * `replication client`:允许该用户执行查看复制状态的命令,如 `SHOW SLAVE STATUS`。
>
> NaN. `on *.* to 'slave'@'%'`:其中`on *.*` 表示这些权限适用于所有数据库和所有表。`to 'slave'@'%'`表明授予这些权限给 `slave` 用户,`'%'` 表示该用户可以从任意 IP 地址访问。
>
> NaN. `flush privileges`:刷新 MySQL 的权限表,使得新创建的用户和权限更改立即生效。
>
NaN. 执行以下命令来获取当前二进制日志文件的名称和位置,这些信息将用于配置从库:show master status;
(在mysql8.4中命令更改为show binary log status;
,参考官方文档:1、2),记下 File 和 Position 的值(如下面 mysql-bin.000001
和 879
)。注意:每次重启数据库都会导致下面的数据发生改变!!!
NaN. 进入从库( mysql-slave )容器,设置从库复制:docker exec -it mysql-slave mysql -uroot -p
NaN. 在从库的 MySQL 命令行中,使用主库的 IP 地址、日志文件和位置配置复制(目前命令已发生修改,参考官方文档:1、2):这里 MASTER_HOST 还可以是主机的 ip ,此时就是通过主机访问主库,需要使用映射端口 3316。
NaN. 查看从库的状态,以确保配置成功:SHOW SLAVE STATUS G;
(8.0.22之后请使用SHOW REPLICA STATUS G;
,官方说明),确保 Slave_IO_Running
和 Slave_SQL_Running
均为 Yes
。
NaN. 此外后面也可以尝试使用 docker-compose 搭建 mysql 主从集群: 待补
Replica_IO_Running: Connecting解决
其实这个错误的原因很简单,就是我直接参考b站的教学视频搭建主从服务器。但是老师使用的是虚拟机,当然这不是重点,重点是老师使用的是主机的 ip +映射端口 3316 。而我后面是使用的docker网络,此时就是使用端口 3306 。
NaN. 使用SHOW REPLICA STATUS G;
查看从库的状态时,我得到:
NaN. 首先就是考虑用户和权限问题:
NaN. 使用 root 用户登录主库并查看 slave 权限是否足够,这里显然足够:
NaN. 在主库使用 slave 用户登录验证密码无错误: `docker exec -it mysql-master mysql -u slave -p`
NaN. 查看网桥信息 docker network inspect mysql-cluster-net
,这里显然存在两个容器,没有问题。注意记录主库ip地址。
NaN. 查阅资料得知,可能是UUID重复。查阅 auto.cnf 的 UUID 配置(但其实只要 server-id 正确配置,并且使用 docker 不存在虚拟机的复制的情况,一般不会有问题):
NaN. 尝试在从库中连接主库:
NaN. 查看官方 dockerfile ,得知 mysql 镜像 使用的基础镜像为`oraclelinux:9-slim`,其安装部分软件包的命令如下:
NaN. 在从库中使用 ip 连接主库数据库,连接失败:
NaN. 这时候就要判断是 ip 无法连接,还是端口号出现问题,在从库中使用 ping 连接主库,连接成功:
NaN. 此时大致可以猜测为端口号的原因,于是乎脑子一抽,我认为是 window 的 3316 端口被占用(但是实际上这和 windows 没有半毛钱关系,这里是在wsl内部,不会经过windows)。没有端口被占用。
NaN. 这时,退而求其次,怀疑是 wsl 的 archlinux 的端口被占用 netstat -tunlp | grep 3316
。确实占用了,但是是 mysql 容器占用的。
NaN. 到这里基本上就要崩溃了,后面就是无止境的删除并重新搭建,然后尝试换成默认的 bridge 网络,都没有作用。直到某次在从库中连接主库的时候,尝试把端口号由3316改成3306,然后就成功了。
NaN. 实际上,上述的错误本质上还是对docker、wsl(archlinux)、windows三种之间的网络和端口映射没有捋清楚。docker中的每个容器都运行在自己独立的网络命名空间。容器之间的通信通过 Docker 网络进行,此时相当于是不经过主机( archlinux )。我们在从库中通过 ip 访问主库,是否可以视作主库和从库是在局域网中的两台主机,二者通过网桥交流,此时访问 主库中的数据库,端口仍然为 3306 。而其端口映射,则是通过主机( archlinux ) 访问 3316 时,经过 docker 内部的处理逻辑,将访问转发到对应容器的 3306 端口。(但是其实这里还有一个疑问没有解决:对于一个docker中运行的mysql容器(3316->3306),我在 wsl 中发现3316被监听占用,但是在windows中并未对 3316 端口监听)
其他错误解决
NaN. 补充(万一哪天用上了): skip-networking 启用时,MySQL 将禁用网络功能,只允许本地连接。skip-name-resolve 启用时禁用 DNS 解析,MySQL 只能使用 IP 地址进行连接。可以直接在 MySQL 中使用 SHOW VARIABLES
命令来查看当前的配置项。对于 skip-networking
和 skip-name-resolve
,你可以运行以下 SQL 查询:
NaN. 查看 `skip-networking` 是否启用:`SHOW VARIABLES LIKE 'skip_networking';`
NaN. 查看 `skip-name-resolve` 是否启用:`SHOW VARIABLES LIKE 'skip_name_resolve';`
NaN. 修改配置。开启或者关闭上述功能:
NaN. ERROR 3021 (HY000): This operation cannot be performed with a running replica io thread;
解决措施:
NaN. SHOW REPLICA STATUS G
输出`Replica_SQL_Running: No
,意味着 SQL 线程没有运行,通常是因为有错误导致复制暂停。若是不在乎该错误,可以尝试跳过该错误并继续复制:
NaN. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
这个错误表明在尝试连接到主服务器时,使用的身份验证插件 caching_sha2_password 要求建立一个安全连接(SSL/TLS),但当前的连接未启用安全连接。尝试在主库mysql中运行ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '<your_password>';
,使主服务器的 slave
用户使用 mysql_native_password
插件,这个插件不要求 SSL 连接。但是实际上还是会报错显示 mysql_native_password
插件未加载,最终解决措施:参考文章
参数说明(gpt总结,待验证)
NaN. 主库配置文件常用配置:
NaN. 关于主库配置文件的介绍:
NaN. `erver_id`定义 MySQL 服务器的唯一标识符。在主从复制环境中,每个服务器必须有一个唯一的 `server_id`,以便于区分不同的服务器。
NaN. `binlog-ignore-db`:用于指定不记录到二进制日志的数据库。此处 mysql 数据库不会被记录到二进制日志中,因此从库不会复制该数据库中的操作。
NaN. `log-bin`:启用二进制日志记录,并将二进制日志文件命名为 `master-log-bin`。二进制日志用于记录所有写操作(INSERT、UPDATE、DELETE等),这些日志可以用于从库同步和数据恢复。
NaN. `binlog_cache_size`:设置二进制日志缓存的大小。如果一个事务在写入二进制日志时生成的数据超过了这个大小,MySQL 会将日志写入磁盘。较大的值可以提升性能,特别是在执行大事务时。
NaN. `binlog_format`:定义二进制日志的格式,有三种可选格式:
* `STATEMENT`:基于语句的日志记录,每个 SQL 语句都会被记录。
* `ROW`:基于行的日志记录,记录每行数据的具体更改。
* `MIXED`:混合模式,通常使用基于语句的日志,但在某些需要更高精度的情况下(如存储过程)会自动切换到基于行的日志。`MIXED` 提供了较好的兼容性和性能平衡。
NaN. `expire_logs_days`:mysql8.x不在支持改用:`binlog_expire_logs_seconds=604800`设置二进制日志的保留天数。这里设置为 7 天,表示二进制日志文件超过 7 天后将被自动删除,避免日志占用过多的磁盘空间。
NaN. `slave_skip_errors`:设置从库在同步时跳过特定错误,这里跳过的是错误代码 `1062`,即重复键错误(Duplicate Entry)。在某些情况下,可能主从库之间的数据不完全一致,使用该配置可以让从库跳过重复键错误,继续执行同步。但需要谨慎使用,以避免数据不同步的问题。
NaN. `binlog-do-db`:指定二进制日志只记录特定数据库的更改。在此配置下,只有 `mydb` 数据库的操作会被记录到二进制日志中,从而被从库复制。如果要记录多个数据库的更改,可以多次使用此选项。
NaN. `max_connections` 参数定义 MySQL 允许的最大并发客户端连接数。在这里设置为 `200`,表示主库可以同时处理 200 个客户端连接。
NaN. `auto_increment_increment` 定义了自增字段的步长(增量),即每次生成自增值时,数值增大的幅度。这里设置为 `2`。在主从复制环境下,多个服务器可能同时进行写操作,而自增字段(如 `AUTO_INCREMENT` 主键)可能会发生冲突。通过设置不同的 `auto_increment_increment` 和 `auto_increment_offset` 值,可以避免这种冲突。
NaN. `auto_increment_offset` 定义自增字段的起始值偏移量。在主库中设置为 `1`,表示主库从 1 开始生成自增主键值。
NaN. `innodb_flush_log_at_trx_commit` 控制 InnoDB 如何将事务日志(redo log)写入磁盘。其值为 `1` 表示每次事务提交时,InnoDB 都会将日志立即写入磁盘并进行同步(即物理写盘)。
NaN. `sync_binlog` 控制 MySQL 二进制日志(binlog)写入磁盘的同步频率。值为 `1` 表示每次事务提交后,二进制日志都会被同步到磁盘。
NaN. 从库配置文件常用配置:
NaN. 关于从库配置文件的介绍:
NaN. 首先需要说明一点,从库也可以作为其它从库的主库,故而是可以配置主库的一些配置。此外作为从库,它也存在一些自己的配置。
NaN. `relay_log`:启用从库的中继日志。中继日志记录从主库接收到的二进制日志事件,从库使用这些日志来执行相同的更改。中继日志文件的前缀为 relay-log-bin 。
NaN. `log_slave_updates`:确保从库将自己接收到的更改写入二进制日志。这个配置对多级复制(链式复制)至关重要。如果启用此选项,从库会将自己从主库接收到的更改记录到二进制日志,从而允许其他从库继续复制。
NaN. `read_only`:将从库设置为只读,防止直接修改数据库中的数据。这个设置确保了从库仅作为读取数据的副本存在,不能在从库上执行写入操作。
NaN. `super_read_only:与` read_only` 相似,但更加严格。即使是具有超级用户权限的账户也无法在从库上执行写操作。这个设置确保从库不会在任何情况下发生写操作,进一步加强了数据的一致性。
NaN. `auto_increment_increment 和` auto_increment_offset:这些设置用于在多主环境或主从复制中防止自增主键冲突。
NaN. `max_connections`:限制 MySQL 允许的最大连接数。在这个配置中,最多允许 100 个客户端连接到数据库。这个设置用于控制并发连接的数量,避免过多的连接消耗过多的系统资源。
NaN. `replicate-do-db`和 `replicate-ignore-db`:这些配置控制从库应该复制哪些数据库的数据。
* `replicate-do-db=mydb`:仅复制 `mydb` 数据库的内容。
* `replicate-ignore-db=test_db`:忽略 `test_db` 数据库的内容,不将其复制到从库。
NaN. `relay_log_purge`:设置是否自动清除过期的中继日志。启用此选项(`1`)时,MySQL 会自动删除已经应用过的中继日志文件。这样可以节省磁盘空间。
NaN. 关于只读从库:read_only=1
可以将从库设置为只读,防止直接修改数据库中的数据。但是该配置对于具有超级用户权限的账户是无效的;并且一般也不建议使用super_read_only=1
。