第8章 常用服务器安装
本章主要学习最常用的,也是安装起来稍有些麻烦的 MySQL
与 Redis
两种服务器的Docker
安装。至于其它服务器的 Docker
安装,大家可自行查找资料。只要 MySQL
与 Redis
这两类服务器学会了安装,其它服务器的安装基本也不会有太大问题了。
1. MySQL 官网安装
在 docker hub
官网的 MySQL
官方镜像中有关于 MySQL
安装的命令。
这里要以安装 MySQL5.7
为例来演示安装过程。
1.1 拉取镜像
先拉取 MySQL5.7 的镜像到本地。
1.2 启动MySQL容器
以分离模式启动 MySQL
容器。
docker run --name mysql -dp 3306:3306 -e MYSQL_ROOT_PASSWORD=111 mysql:5.7
-e MYSQL_ROOT_PASSWORD=111
:设置环境变量MYSQL_ROOT_PASSWORD
的值为 “111”,这将设置MySQL
的 **root **用户密码为 “111”。
1.3 进入容器
以交互方式进入 mysql
容器。
docker exec -it mysql bash
1.4 客户端连接MySQL
在 mysql
容器内,使用 mysql
客户端连接 mysql
服务。
mysql -uroot -p
1.5 创建数据库与表
通过该客户端创建一个新的数据库 test
,并在其中创建一个表 emp(id, name,depart)
,用于测试该 MySQL
服务。
1.6 Navicat连接MySQL
在 window
系统中使用 Navicat
连接上这个 mysql
容器提供的 mysql
服务。然后就可以看到新建的 test
数据库与 emp
表了。
1.7 字符编码问题
当前 mysql
容器好像可以正常运行了。但实际还存在两个较严重的问题。其中一个就是字符编码问题。
在表中手工插入一条包含中文的记录,提交时会报错。原因就出现字符编码上。
查看当前 mysql
中的字符编码,发现大多数是 latin1
,不是 utf8
。问题就出在这里。
如果要解决这个问题,就需要在容器系统的/etc/mysql/conf.d
中新建一个my.cnf
文件,在其中指定字符编码。
1.8 数据安全问题
除了编码问题,还存在一个严重问题,就是数据安全问题。
前面新建了 test
数据库与 emp
表存放在哪里?在容器系统中的/var/lib/mysql
目录中。
mysql
的运行错误日志对于工作中异常的判断非常重要,其存放在哪里?存放在容器系统的/var/log/mysql
目录中。
如果容器被不小心删除了,那么无论是数据文件、日志文件,还是设置字符编码的 my.cnf
文件,都将消失。在生产中,这是绝对不允许的,所以要保证数据的安全性。
2. MySQL 生产安装
为了保证数据的安全性,在生产环境下安装的 mysql
容器,在启动时都会使用数据卷来持久化数据。
2.1 启动MySQL容器
docker run --name mysql \
-e MYSQL_ROOT_PASSWORD=111 \
-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/mys
-v /root/mysql/log:/var/log/mys
-v /root/mysql/log:/var/log/mys
2.2 新建my.cnf
在宿主机的/root/mysql/conf
目录(数据卷目录)中新建my.cnf
文件,并在其中键入如下内容:
[client]
default_character_set=utf8
[mysql]
default_character_set=utf8
[mysqld]
character_set_server=utf8
2.3 重启MySQL容器
docker restart mysql
2.4 进入容器连接mysql
2.5 查看字符编码
此时查看当前 mysql
的字符编码,已经全变为了 utf8
。
2.6 创建数据库和表
2.7 Navicat插入中文记录
此时再在表中插入中文记录就没有问题了。
2.8 查看宿主机数据卷
此时再查看宿主机中数据卷目录,已经有了文件。
3. MySQL 集群安装
单机版的 MySQL
存在单点问题,且在高并发场景下性能会急剧下降。所以,生产中对于 MySQL
都是使用读写分离的主从集群。既保证了数据的安全性,又提升了性能。
下面要使用 Docker
搭建一个“一主一从”的 MySQL
读写分离集群。
3.1 Master的安装与配置
3.1.1 启动 master 容器
docker run --name mysql_master \
-e MYSQL_ROOT_PASSWORD=111 \
-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
3.1.2 新建 my.cnf
在宿主机的/root/mysql_master/conf
目录中新建 my.cnf
文件,并在其中键入如下内容:
[client]
default_character_set=utf8
[mysql]
default_character_set=utf8
[mysqld]
character_set_server=utf8
server_id=01
binlog-ignore-db=mysql
log-bin=master-log-bin
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
slave_skip_errors=1062
[client]
和[mysql]
:这两个部分分别指定了 MySQL 客户端和服务器的默认字符集为 UTF-8 编码。[mysqld]
:该部分包含了 MySQL 服务器的其他参数设置。character_set_server=utf8
:设置 MySQL 服务器默认字符集为 UTF-8 编码。server_id=01
:设置 MySQL 服务器的唯一标识符为 “01”。binlog-ignore-db=mysql
:设置 MySQL 服务器忽略所有对mysql
数据库的更新操作。log-bin=master-log-bin
:启用二进制日志功能,并设置二进制日志的名称为 “master-log-bin”。binlog_cache_size=1M
:设置二进制日志缓存大小为 1MB。binlog_format=mixed
:设置二进制日志的格式为混合模式,这种模式可以同时记录语句和行级别的变更。expire_logs_days=7
:设置二进制日志的过期时间为 7 天,过期的日志将会被自动删除。slave_skip_errors=1062
:如果 MySQL 从服务器在执行 SQL 语句时发生了唯一键冲突(Error 1062),则自动跳过该错误并继续执行。
3.1.3 重启 master 容器
由于修改了 mysql
配置,所以需要重启 master
容器,以使新配置生效。
3.1.4 进入容器连接 mysql
进入容器并连接上 mysql
后,查看其字符编码,可以看到其是支持中文的。
3.1.5 创建用户
为当前 MySQL
创建一个用户。
CREATE USER
:创建用户关键字。'slave'@'%'
:用户名称和主机名。'slave'
为用户名称,'%'
表示该用户可以在任何主机上连接到 MySQL 服务器。IDENTIFIED BY '123456'
:设置用户的密码为 ‘123456’。
3.1.6 授权用户
为新创建的用户授权。
GRANT
:授权关键字。REPLICATION SLAVE
和REPLICATION CLIENT
:授权的权限类型,分别为复制从服务器和复制客户端。*.*
:授权的数据库和表,*
表示任意数据库和表。TO 'slave'@'%'
:授权给名为 ‘slave’ 的用户,该用户可以在任何主机上连接到 MySQL 服务器。%
表示任意主机
3.2 Slave的安装与配置
3.2.1 启动 Slave 容器
再打开一个会话窗口,在其中启动 Slave
容器。
docker run --name mysql_slave \
-e MYSQL_ROOT_PASSWORD=111 \
-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
3.2.2 新建 my.cnf
在宿主机的/root/mysql_slave/conf
目录中新建 my.cnf
文件,并在其中键入如下内容:
[client]
default_character_set=utf8
[mysql]
default_character_set=utf8
[mysqld]
character_set_server=utf8
server_id=02
binlog-ignore-db=mysql
log-bin=slave-log-bin
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
slave_skip_errors=1062
relay_log=relay-log-bin
log_slave_updates=1
read_only=1
[client]
:客户端配置节,用于设置客户端的默认字符集为 utf8。[mysql]
:MySQL 配置节,用于设置 MySQL 的默认字符集为 utf8。[mysqld]
:MySQL 服务器配置节,用于设置 MySQL 服务器的各种选项。
在 [mysqld]
节中,具体的配置选项如下:
character_set_server
:设置服务器的默认字符集为 utf8。server_id
:设置 MySQL 服务器的唯一 ID,用于在主从复制中区分不同的服务器。binlog-ignore-db=mysql
:设置不将 mysql 数据库的操作写入二进制日志。log-bin=slave-log-bin
:启用二进制日志,并设置二进制日志文件的前缀为 slave-log-bin。binlog_cache_size=1M
:设置二进制日志缓存的大小为 1MB。binlog_format=mixed
:设置二进制日志格式为 mixed,即按需选择使用语句复制或行复制。expire_logs_days=7
:设置二进制日志文件自动清理的时间为 7 天。slave_skip_errors=1062
:设置当出现错误码为 1062(即唯一键冲突)时跳过该错误。relay_log=relay-log-bin
:启用中继日志,并设置中继日志文件的前缀为 relay-log-bin。log_slave_updates=1
:设置从服务器将接收到的修改操作写入自己的二进制日志中。read_only=1
:设置从服务器为只读模式,禁止在从服务器上进行写操作
3.2.3 重启 slave 容器
由于修改了 mysql
配置,所以需要重启 slave
容器,以使新配置生效。
3.2.4 进入容器连接 mysql
进入容器并连接上 mysql
后,查看其字符编码,可以看到其是支持中文的。
3.3 配置主从复制
3.3.1 查看 master 状态
在 master
中运行 show master status
命令,查看二进制日志文件名及要开始的位置。
3.3.2 slave 指定 master
在 slave
中通过运行change master to
命令来指定其要连接的 master
相关信息
这是 MySQL
主从复制中用于设置从服务器连接主服务器的命令。具体的解释如下:
change master to
:用于启动从服务器连接主服务器的命令。master_host='192.168.254.131'
:设置主服务器的 IP 地址为 192.168.254.131。master_user='slave'
:设置连接主服务器的用户名为 slave。master_password='123456'
:设置连接主服务器的密码为 123456。master_port=3316
:设置连接主服务器的端口为 3316。
3.3.3 查看 slave 状态
在 slave
中查看 slave
状态发现,当前 slave
与 master
的同步复制还没有开始。
show slave status \G
是 MySQL
中用于查看从服务器的状态信息的命令,\G
参数表示使用纵向格式显示结果,更方便查看。具体的解释如下:
show slave status
:用于显示从服务器的状态信息。\G
:使用纵向格式显示结果。
这个命令会返回一个包含多个字段的结果集,其中一些比较重要的字段如下:
Slave_IO_Running
和Slave_SQL_Running
:用于表示从服务器 I/O 线程和 SQL 线程的运行状态,一般应该都为Yes
。Master_Host
和Master_Port
:用于表示从服务器连接的主服务器的 IP 地址和端口号。Master_User
和Master_Log_File
:用于表示从服务器连接主服务器时使用的用户名和从服务器读取 binlog 文件时的文件名。Exec_Master_Log_Pos
和Read_Master_Log_Pos
:用于表示从服务器 SQL 线程当前读取的 binlog 文件中的位置。Seconds_Behind_Master
:用于表示从服务器相对于主服务器的延迟时间,一般应该为 0,表示从服务器已经和主服务器保持同步。
3.3.4 slave 开启同步
在 slave
中使用 start slave
命令开启 slave
的数据同步
start slave
此时再次查看 slave
的状态,发现同步已经开始。
3.4 测试
到这里,一主一从的读写分离集群就搭建完毕了。下面在 master
中创建一个数据库与表,在 slave
中如果可以查看到,则说明搭建成功。
3.4.1 在 master 中写入
3.4.2 在 slave 中读取
在 slave
中可以查看到在 master
中写入的数据,说明集群搭建成功。
4. Redis 单机版安装
注意:
从下面一部分开始,Redis这一块其实有点问题,待后续我更新内容
4.1 拉取Redis
首先从 docker hub
拉取 Redis
镜像,这里拉取最新版。
4.2 创建数据卷目录
首先要在宿主机/root
目录中创建一个目录 redis
,将来用于存放外挂文件 redis.conf
。
mkdir redis
4.3 启动redis容器
docker run --name myredis \
-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
。
4.4进入容器连接Redis
通过 docker exec
命令进入 Redis
容器后,就可通过 redis-cli
客户端连接上这个 Redis
,然后执行 Redis
命令了。
5. Redis 一主两从集群搭建
现要搭建一个“一主两从”的 Redis
集群。这三个容器的端口号都保持默认,但对外暴露出的端口号分别为 6381、6382、6383
。其中,6381
的为 master
,另外两个为 slave
。
5.1 启动master
首先启动 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:latest \
redis-server /etc/redis/redis.conf
5.2 启动两个slave
在启动 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.254.131 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.254.131 6381
5.3 关系查看
查看这三个容器节点的 info replication
,可以看到它们间的主从关系已经建立
5.4 数据测试
在 master
节点 myredis-1(主)
中写入数据
在 slave
节点 myredis-2
与 myredis-3
节点中可读出数据。
6. Redis 高可用集群搭建
主从集群存在的问题是,其容灾方式只能采用冷处理方案,无法在生产中使用。所以,这里要搭建一个“一主两从三哨兵”的高可用集群,以达到热处理的容灾方案。
对于“一主两从”集群,仍使用前面的即可。下面直接搭建三个 Sentinel
节点的集群。这三个容器的端口号都保持默认,但对外暴露出的端口号分别为 26381、26382、26383
。
6.1 启动sentinel
启动三个 sentinel
容器
docker run --name mysentinel-1 \
-v /root/redis/sentinel1.conf:/etc/redis/sentinel.conf \
-dp 26381:26379 \
redis:latest \
redis-sentinel /etc/redis/sentinel.conf
docker run --name mysentinel-2 \
-v /root/redis/sentinel2.conf:/etc/redis/sentinel.conf \
-dp 26382:26379 \
redis:latest \
redis-sentinel /etc/redis/sentinel.conf
docker run --name mysentinel-3 \
-v /root/redis/sentinel3.conf:/etc/redis/sentinel.conf \
-dp 26383:26379 \
redis:latest \
redis-sentinel /etc/redis/sentinel.conf
6.2 关系查看
sentinel_masters
: 当前监控的Redis主节点数量sentinel_tilt
: Sentinel模式下,被认为是瘫痪的节点的数量sentinel_running_scripts
: 当前正在运行的脚本数量sentinel_scripts_queue_length
: 等待运行的脚本数量sentinel_simulate_failure_flags
: 模拟失败的标志数量
以上命令的查看结果说明 sentinel
对 master
的监视成功,说明高可用集群搭建成功。连接任何一个 sentinel
容器节点查看到的信息与上面的都是相同的。
6.3 故障转移测试
为了验证高可用性,现将充当 master
的容器 myredis-1
停掉。
此时,再查看另外两个 redis
容器的状态数据,发现 myredis-2
成为了 myredis-3
的 slave
,即 myredis-3
成为了新的 master
。
此时再次 myredis-1
容器启动
再查看 myredis-1
的状态数据,发现其成为了 myredis-3
的 slave
7. Redis 分布式系统搭建
Redis
集群的每个节点中的保存的数据都是相同的。而 Redis
分布式系统的节点中存放的数据可以是不同的。当有数据写入请求到达分布式系统后,系统会采用虚拟槽分区算法将数据写入到相应节点。
下面要搭建一个三主三从的 Redis
分布式系统。
序号 | 角色 | 容器名称 | 网络模式 | 暴露地址 |
---|---|---|---|---|
1 | master | myredis-1 | host | 192.168.254.131:6381 |
2 | master | myredis-2 | host | 192.168.254.131:6382 |
3 | master | myredis-3 | host | 192.168.254.131:6383 |
4 | slave | myredis-4 | host | 192.168.254.131:6384 |
5 | slave | myredis-5 | host | 192.168.254.131:6385 |
6 | slave | myredis-6 | host | 192.168.254.131:6386 |
7.1 准备目录与配置文件
在/root
中 mkdir
一个名称为 cluster
的目录,并将前面的配置文件/root/redis/redis.conf
复制到这里。
7.2 复制六份redis.conf
复制 redis.conf
为 redis1.conf
,并在其中将下面两个配置前的注释去掉。这两项配置,一个是用于开启 cluster
功能,即分布式系统功能;一个是指定其需要的配置文件名称。
然后再以 redis1.conf
为模板复制出 5 份,分别为 redis2.conf、redis3.conf、redis4.conf、redis5.conf、redis6.conf
。这 6 份配置文件内容完全相同。
7.3 启动Redis
启动 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
7.4 创建系统
6 个节点启动后,它们仍是 6 个独立的 Redis
,通过 redis-cli --cluster create
命令可将 6个节点创建为一个分布式系统。--cluster replicas 1
指定每个 master
会带有一个 slave
副本。
回车后即可看到如下的计划日志:
键入 yes 后再回车,即可按照上面的计划完成系统创建。
7.5 查看节点信息
通过 cluster nodes
命令可以查看到系统中各节点的关系及连接情况。只要能看到每个节点给出 connected
,就说明分布式系统已经成功搭建
7.6 系统操作
对于如何对分布式系统进行操作,例如,slot 相关查询、故障转移、动态扩容、动态缩容等,与使用虚拟机搭建的分布式系统的操作命令相同,唯一不同的就是,需要首先通过docker exec –it 命令进入到容器内部再执行这些命令。