赞
踩
本章主要学习最常用的,也是安装起来稍有些麻烦的 MySQL 与 Redis 两种服务器的Docker 安装。至于其它服务器的 Docker 安装,大家可自行查找资料。只要 MySQL 与 Redis这两类服务器学会了安装,其它服务器的安装基本也不会有太大问题了。
在 docker hub 官网的 MySQL 官方镜像中有关于 MySQL 安装的命令。这里要以安装 MySQL5.7 为例来演示安装过程
先拉取 MySQL5.7 的镜像到本地
docker pull mysql:5.7
以分离模式启动 MySQL 容器
docker run --name mysql -dp 3306:3306 -e MYSQL_ROOT_PASSWORD=101022 mysql:5.7
以交互方式进入 mysql 容器。
docker exec -it mysql /bin/bash
mysql -u root -p
通过该客户端创建一个新的数据库 test,并在其中创建一个表 emp(id, name),用于测试该 MySQL 服务。
新建表数据,插入信息
create database test;
use test;
create table emp(id int, name varchar(20), depart varchar(20));
insert into emp values(1, 'zs', 'admin');
当前 mysql 容器好像可以正常运行了。但实际还存在两个较严重的问题。其中一个就是字符编码问题。在表中手工插入一条包含中文的记录,提交时会报错。原因就出现字符编码上
查看当前 mysql 中的字符编码,发现大多数是 latin1,不是 utf8。问题就出在这里。
show variables like 'character%'
如果要解决这个问题,就需要在容器系统的**/etc/mysql/conf.d** 中新建一个 my.cnf 文件,在其中指定字符编码。
除了编码问题,还存在一个严重问题,就是数据安全问题。前面新建了 test 数据库与 emp 表存放在哪里?在容器系统中的/var/lib/mysql 目录中。
mysql 的运行错误日志对于工作中异常的判断非常重要,其存放在哪里?存放在容器系统的/var/log/mysql 目录中。如果容器被不小心删除了,那么无论是数据文件、日志文件,还是设置字符编码的 my.cnf文件,都将消失。在生产中,这是绝对不允许的,所以要保证数据的安全性。
为了保证数据的安全性,在生产环境下安装的 mysql 容器,在启动时都会使用数据卷来持久化数据
使用命令行启动,具体命令如下
docker run --name mysql \
-e MYSQL_ROOT_PASSWORD=101022 \
-v /root/mysql/data:/var/lib/mysql \
-v /root/mysql/log:/var/log/mysql \
-v /root/mysql/conf:/etc/mysql/conf.d \
-dp 3306:3306 \
mysql:5.7
这里指定了三个数据卷:
-v /root/mysql/log:/var/log/mysql
-v /root/mysql/data:/var/lib/mysql
-v /root/mysql/conf:/etc/mysql/conf.d
在宿主机的/root/mysql/conf 目录(数据卷目录)中新建 my.cnf 文件,并在其中键入如下内容:
[client]
default_character_set=utf8
[mysql]
default_character_set=utf8
[mysqld]
character_set_server=utf8
由于修改了 mysql 配置,所以需要重启 mysql 容器,以使新配置生效。
docker restart mysql
此时查看当前 mysql 的字符编码,已经全变为了 utf8。
show variables like 'character%';
create database test;
use test;
create table emp(id int, name varchar(20), depart varchar(20));
insert into emp values(1, 'zs', 'admin');
此时再在表中插入中文记录就没有问题了。
此时再查看宿主机中数据卷目录,已经有了文件。
单机版的 MySQL 存在单点问题,且在高并发场景下性能会急剧下降。所以,生产中对于 MySQL 都是使用读写分离的主从集群。既保证了数据的安全性,又提升了性能。下面要使用 Docker 搭建一个“一主一从”的 MySQL 读写分离集群。
启动 master 容器
docker run --name mysql_master \
-e MYSQL_ROOT_PASSWORD=101022 \
-v /root/mysql_master/data:/var/lib/mysql \
-v /root/mysql_master/log:/var/log/mysql \
-v /root/mysql_master/conf:/etc/mysql/conf.d \
-dp 3316:3306 \
mysql:5.7
新建 my.cnf
在宿主机的/root/mysql_master/conf 目录中新建 my.cnf 文件,并在其中键入如下内容:
[client] # 客户端连接到MySQL时使用的默认字符集。这确保了客户端和服务器之间的字符编码一致性 default_character_set=utf8 [mysql] # 这是MySQL命令行工具连接到服务器时使用的字符集 default_character_set=utf8 [mysqld] # 服务器处理数据时使用的字符集。这影响存储在数据库中的所有字符串数据 character_set_server=utf8 # 为从服务器分配一个唯一的ID,这个ID必须在所有参与复制的服务器中是唯一的。它用于标识二进制日志事件的来源 server_id=01 # 指定不记录哪些数据库的更改到二进制日志。在这个例子中,mysql系统数据库的更改不会被记录。通常,系统数据库不需要复制 binlog-ignore-db=mysql # 指定二进制日志的文件名前缀。尽管在从服务器上通常不需要记录二进制日志,但有时可能需要,例如在循环复制或故障恢复场景中 log-bin=master-log-bin # 每个线程用于缓存二进制日志事件的内存大小。如果从服务器也用作主服务器的一部分,则此设置很重要 binlog_cache_size=1M # 二进制日志的格式。mixed格式结合了statement和row格式的优点,根据事件类型选择最合适的格式 binlog_format=mixed # 设置二进制日志文件自动过期并被删除的天数。这对于磁盘空间管理很有用。 expire_logs_days=7 # 当从服务器遇到指定的错误号时,它会跳过当前事件并继续复制。1062是“Duplicate entry”错误,这可能是因为并发插入导致的 slave_skip_errors=1062
重启 master 容器
# 由于修改了 mysql 配置,所以需要重启 master 容器,以使新配置生效
docker restart mysql_master
进入容器连接 mysql
进入容器并连接上 mysql 后,查看其字符编码,可以看到其是支持中文的
docker exec -it mysql_master /bin/bash
show variables like 'character%'
创建用户并授权
# 为当前 MySQL 创建一个用户。
create user 'slave'@'%' identified by '101022';
# 为用户授权
grant replication slave, replication client on *.* to 'slave'@'%';
启动 Slave 容器
再打开一个会话窗口,在其中启动 Slave 容器。
docker run --name mysql_slave \
-e MYSQL_ROOT_PASSWORD=101022 \
-v /root/mysql_slave/data:/var/lib/mysql \
-v /root/mysql_slave/log:/var/log/mysql \
-v /root/mysql_slave/conf:/etc/mysql/conf.d \
-dp 3326:3306 \
mysql:5.7
新建 my.cnf
在宿主机的/root/mysql_slave/conf 目录中新建 my.cnf 文件,并在其中键入如下内容
[client] # 客户端连接到MySQL时使用的默认字符集。这确保了客户端和服务器之间的字符编码一致性 default_character_set=utf8 [mysql] # 这是MySQL命令行工具连接到服务器时使用的字符集 default_character_set=utf8 [mysqld] # 服务器处理数据时使用的字符集。这影响存储在数据库中的所有字符串数据 character_set_server=utf8 # 为从服务器分配一个唯一的ID,这个ID必须在所有参与复制的服务器中是唯一的。它用于标识二进制日志事件的来源 server_id=02 # 指定不记录哪些数据库的更改到二进制日志。在这个例子中,mysql系统数据库的更改不会被记录。通常,系统数据库不需要复制 binlog-ignore-db=mysql # 指定二进制日志的文件名前缀。尽管在从服务器上通常不需要记录二进制日志,但有时可能需要,例如在循环复制或故障恢复场景中 log-bin=slave-log-bin # 每个线程用于缓存二进制日志事件的内存大小。如果从服务器也用作主服务器的一部分,则此设置很重要 binlog_cache_size=1M # 二进制日志的格式。mixed格式结合了statement和row格式的优点,根据事件类型选择最合适的格式 binlog_format=mixed # 设置二进制日志文件自动过期并被删除的天数。这对于磁盘空间管理很有用 expire_logs_days=7 # 当从服务器遇到指定的错误号时,它会跳过当前事件并继续复制。1062是“Duplicate entry”错误,这可能是因为并发插入导致的 slave_skip_errors=1062 # 指定中继日志文件的名称前缀。中继日志用于存储从主服务器接收到的二进制日志事件 relay_log=relay-log-bin # 如果从服务器本身也是其他从服务器的主服务器,此选项将使从服务器将其更新记录在其自己的二进制日志中 log_slave_updates=1 # 设置从服务器上的所有数据库只读,防止直接写入数据。这是推荐的做法,以避免在从服务器上进行意外的数据修改 # 请注意,server_id应该是唯一的,并且read_only设置可能需要根据具体的应用需求进行调整。此外,binlog_ignore_db和log_bin设置通常在从服务器上不是必需的,除非有特定的需求 read_only=1
重启 slave 容器
由于修改了 mysql 配置,所以需要重启 slave 容器,以使新配置生效
docker restart mysql_slave
进入容器连接 mysql
进入容器并连接上 mysql 后,查看其字符编码,可以看到其是支持中文的。
docker exec -it mysql_slave /bin/bash
show variables like 'character%';
查看 master 状态
在 master 中运行 show master status 命令,查看二进制日志文件名及要开始的位置。
show master status;
slave 指定 master
在 slave 中通过运行 change master to 命令来指定其要连接的 master 相关信息。
# ip为宿主机ip
change master to
master_host='192.168.138.129',master_user='slave',master_password='101022',master_port=3316,master_log_file='master-log-bin.000001',master_log_pos=617,master_connect_retry=30,master_retry_count=3;
查看 slave 状态
在 slave 中查看 slave 状态发现,当前 slave 与 master 的同步复制还没有开始
show slave status \G;
slave 开启同步
在 slave 中使用 start slave 命令开启 slave 的数据同步
start slave;
到这里,一主一从的读写分离集群就搭建完毕了。
下面在 master 中创建一个数据库与表,在 slave 中如果可以查看到,则说明搭建成功。
create database test;
use test;
create table emp(id int, name varchar(20), depart varchar(20));
insert into emp values(1, 'ww', 'admin');
insert into emp values(2, 'zl', 'market');
在slave控制台进行读取数据
发现从节节点可以插入数据
这是因为使用的root用户,root用户拥有全部权限,可以进行插入操作,可以修改超级权限用户在从服务也只能进行读操作
set global super_read_only=1;
首先从 docker hub 拉取 Redis 镜像
docker pull redis
首先要在宿主机/root 目录中创建一个目录 redis,将来用于存放外挂文件 redis.conf
mkdir redis
上传一份 redis 核心配置文件 redis.conf 到宿主机目录/root/redis 中(redis.conf的标准文件在redis官网也可以找到)
# bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 bind 192.168.138.129 -::1 protected-mode no port 6379 tcp-backlog 511 requirepass 101022 timeout 0 tcp-keepalive 300 daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile "" databases 30 always-show-logo yes save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data replica-serve-stale-data yes replica-read-only yes repl-diskless-sync no repl-disable-tcp-nodelay no replica-priority 100 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no replica-lazy-flush no appendonly yes appendfilename "appendonly.aof" no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble yes lua-time-limit 5000 slowlog-max-len 128 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 stream-node-max-bytes 4096 stream-node-max-entries 100 activerehashing yes hz 10 dynamic-hz yes aof-rewrite-incremental-fsync yes rdb-save-incremental-fsync yes
解除 IP 绑定
将 bind 行注释掉,以解除 Redis 对访问者 IP 的绑定,配置自己机器ip地址
关闭保护模式
关闭保护模式,否则只能本机访问自己
关闭守护模式
关闭守护模式对于 Redis 容器安装来说非常重要。由于 docker 本身就是以分离模式运行的,如果 Redis 再以该模式运行,则 Redis 无法启动。
指定持久化目录
这里要指定 RDB 或 AOF 的持久化目录为/data,这样无论是哪种持久化文件,均会保存到该目录。后面会指定容器中的/data 目录为数据卷挂载点目录
docker run --name myredis \
--network host \
-v /root/redis/redis.conf:/etc/redis/redis.conf \
-v /root/redis/data:/data \
-dp 6379:6379 \
redis:latest \
redis-server /etc/redis/redis.conf
这里指定了两个数据卷,其中一个是文件,一个是目录:
-v /root/redis/redis.conf:/etc/redis/redis.conf
-v /root/redis/data:/data
对于该启动命令需要注意的是,其后面运行的命令为 redis-server,且加载的配置文件为挂载点目录/etc/redis 中的 redis.conf。
通过 docker exec 命令进入 Redis 容器后,就可通过 redis-cli 客户端连接上这个 Redis,然后执行 Redis 命令了。
docker exec -it myredis /bin/bash
现要搭建一个“一主两从”的 Redis 集群。这三个容器的端口号都保持默认,但对外暴露出的端口号分别为 6381、6382、6383。其中,6381 的为 master,另外两个为 slave。
现仍在前面的/root/redis 目录中完成配置。复制 redis.conf 并重命名为 redis1.conf,并在文件最后添加如下配置,以对外宣布当前 redis 的 IP 与端口。注意,该 IP 为 docker 宿主机的 IP,端口号为当前 redis 对外暴露的端口号
slave-announce-ip 192.168.138.129
# 其余redis2.conf 以及 redis3.conf 分别配置 6382 6383
slave-announce-port 6381
首先启动 master,即启动 myredis-1 容器。
docker run --name myredis-1 \
-v /root/redis/redis1.conf:/etc/redis/redis.conf \
-v /root/redis/data/6381:/data \
-dp 6381:6379 \
redis: \
redis-server /etc/redis/redis.conf
在启动 slave 的命令中需要指出其slaveof 于谁
docker run --name myredis-2 \
-v /root/redis/redis2.conf:/etc/redis/redis.conf \
-v /root/redis/data/6382:/data \
-dp 6382:6379 \
redis:latest \
redis-server /etc/redis/redis.conf \
--slaveof 192.168.138.129 6381
docker run --name myredis-3 \
-v /root/redis/redis3.conf:/etc/redis/redis.conf \
-v /root/redis/data/6383:/data \
-dp 6383:6379 \
redis:latest \
redis-server /etc/redis/redis.conf \
--slaveof 192.168.138.129 6381
查看这三个容器节点的 info replication,可以看到它们间的主从关系已经建立
docker exec -it myredis-2 redis-cli --pass 101022 info replication
生产环境使用集群模式,不使用哨兵模式,暂时不进行研究
Redis 集群的每个节点中的保存的数据都是相同的。而 Redis 分布式系统的节点中存放的数据可以是不同的。当有数据写入请求到达分布式系统后,系统会采用虚拟槽分区算法将数据写入到相应节点。下面要搭建一个三主三从的 Redis 分布式系统
序号 | 角色 | 容器名称 | 网络模式 | 地址 |
---|---|---|---|---|
1 | master | myredis-1 | host | 192.168.138.129:6381 |
2 | master | myredis-2 | host | 192.168.138.129:6382 |
3 | master | myredis-3 | host | 192.168.138.129:6383 |
4 | slave | myredis-4 | host | 192.168.138.129:6384 |
5 | slave | myredis-5 | host | 192.168.138.129:6385 |
6 | slave | myredis-6 | host | 192.168.138.129:6386 |
在/root 中 mkdir 一个名称为 cluster 的目录,并将前面的配置文件/root/redis/redis.conf复制到这里。
复制 redis.conf 为 redis1.conf,并在其中将下面两个配置前的注释去掉。这两项配置,一个是用于开启 cluster 功能,即分布式系统功能;一个是指定其需要的配置文件名称
cluster-enabled true
cluster-config-file nodes-6379.conf
然后再以 redis1.conf 为模板复制出 5 份,分别为 redis2.conf、redis3.conf、redis4.conf、redis5.conf、redis6.conf。这 6 份配置文件内容完全相同。
启动 6 个 Redis 容器
docker run --name myredis-1 \
--network host \
-v /root/cluster/redis1.conf:/etc/redis/redis.conf \
-v /root/cluster/data/6381:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf --port 6381
docker run --name myredis-2 \
--network host \
-v /root/cluster/redis2.conf:/etc/redis/redis.conf \
-v /root/cluster/data/6382:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf --port 6382
docker run --name myredis-3 \
--network host \
-v /root/cluster/redis3.conf:/etc/redis/redis.conf \
-v /root/cluster/data/6383:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf --port 6383
docker run --name myredis-4 \
--network host \
-v /root/cluster/redis4.conf:/etc/redis/redis.conf \
-v /root/cluster/data/6384:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf --port 6384
docker run --name myredis-5 \
--network host \
-v /root/cluster/redis5.conf:/etc/redis/redis.conf \
-v /root/cluster/data/6385:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf --port 6385
docker run --name myredis-6 \
--network host \
-v /root/cluster/redis6.conf:/etc/redis/redis.conf \
-v /root/cluster/data/6386:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf --port 6386
6 个节点启动后,它们仍是 6 个独立的 Redis,通过 redis-cli --cluster create 命令可将 6个节点创建为一个分布式系统。–cluster replicas 1 指定每个 master 会带有一个 slave 副本。
docker exec -it myredis-1 redis-cli --cluster create --cluster-replicas 1 192.168.138.129:6381 192.168.138.129:6382 192.168.138.129:6383 192.168.138.129:6384 192.168.138.129:6385 192.168.138.129:6386
通过 cluster nodes 命令可以查看到系统中各节点的关系及连接情况。只要能看到每个节点给出 connected,就说明分布式系统已经成功搭建
docker exec -it myredis-1 redis-cli -h 192.168.138.129 -p 6384 cluster nodes
对于如何对分布式系统进行操作,例如,slot 相关查询、故障转移、动态扩容、动态缩容等,与使用虚拟机搭建的分布式系统的操作命令相同,唯一不同的就是,需要首先通过docker exec –it 命令进入到容器内部再执行这些命令。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。