Centos 服务器相关环境搭建
网卡启动&配置开机启动
#查看网卡信息
ip address
#启动相关网卡
ifup ensXXX
#配置网卡开机启动
ll /etc/sysconfig/network-scripts/ifcfg*
#ensXX为网卡名称,请根据自己网卡进行填写
vi /etc/sysconfig/network-scripts/ifcfg-ensXX
#设置ONBOOT属性为yes
#配置文件生效
source /etc/sysconfig/network-scripts/ifcfg-ensXX
#重启网络
service network restart
docker安装
#更新 yum 包
yum -y update
#安装需要的软件包
yum install -y yum-utils device-mapper-persistent-data lvm2
#设置阿里yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装vim
yum install vim
#安装docker-ce
yum -y install docker-ce
#启动docker并设置开机启动
systemctl start docker
systemctl enable docker
docker安装mysql一主二从
#拉取MySQL8镜像
docker pull mysql:8
#确认拉取是否成功
docker images
# 创建主服务的配置目录和数据目录
mkdir -p /usr/local/mysqlData/master/cnf
mkdir -p /usr/local/mysqlData/master/data
# 创建1号从服务器的配置目录和数据目录
mkdir -p /usr/local/mysqlData/slave/cnf
mkdir -p /usr/local/mysqlData/slave/data
# 创建2号从服务器的配置目录和数据目录
mkdir -p /usr/local/mysqlData/slave2/cnf
mkdir -p /usr/local/mysqlData/slave2/data
# 配置主服务器的配置文件,配置文件如下
vim /usr/local/mysqlData/master/cnf/mysql.cnf
主服务器配置参考如下
[mysqld]
## 设置server_id,注意要唯一
server-id=1
## 开启binlog
log-bin=mysql-bin
## binlog缓存
binlog_cache_size=1M
## binlog格式(mixed、statement、row,默认格式是statement)
binlog_format=mixed
##设置字符编码为utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
从服务器参考配置如下,注意1号的server-id设置为2,2号的server-id设置为3,不可以重复
# 1号从服务器
vim /usr/local/mysqlData/slave/cnf/mysql.cnf
# 2号从服务器
vim /usr/local/mysqlData/slave2/cnf/mysql.cnf
[mysqld]
## 设置server_id,注意要唯一
server-id=2
## 开启binlog
log-bin=mysql-slave-bin
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin
## 如果需要同步函数或者存储过程
log_bin_trust_function_creators=true
## binlog缓存
binlog_cache_size=1M
## binlog格式(mixed、statement、row,默认格式是statement)
binlog_format=mixed
##设置字符编码为utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
slave_skip_errors=1062
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
服务实例化
# 主服务器实例化
docker run -itd -p 3307:3306 --name master -v /usr/local/mysqlData/master/cnf:/etc/mysql/conf.d -v /usr/local/mysqlData/master/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8
# 1号从服务器实例化
docker run -itd -p 3308:3306 --name slaver -v /usr/local/mysqlData/slave/cnf:/etc/mysql/conf.d -v /usr/local/mysqlData/slave/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8
# 2号从服务器实例化
docker run -itd -p 3309:3306 --name slaver2 -v /usr/local/mysqlData/slave2/cnf:/etc/mysql/conf.d -v /usr/local/mysqlData/slave2/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8
参数解释
-p 指定容器暴露的端口,宿主机(物理机)端口: docker实例端口
-p 3307:3306 把物理机的3307端口给实例的端口3306端口进行映射
-v 给容器挂载存储卷,挂载到容器的某个目录
-v /usr/local/mysqlData/master/cnf:/etc/mysql/conf.d 把刚创建的配置文件夹映射成实例的/etc/mysql/conf.d
-v /usr/local/mysqlData/master/data:/var/lib/mysql 数据文件夹的映射
-e 指定环境变量,容器中可以使用该环境变量
-e MYSQL_ROOT_PASSWORD=123456 设置MySQL的root账号密码为123456
#检查docker实例是否成功启动
docker ps -a
#进入主数据库创建从数据库用于同步数据的用户
docker exec -it master mysql -uroot -p123456
# 创建用户 reader设置密码为reader
CREATE USER reader IDENTIFIED BY 'reader';
# 给予reader同步权限
GRANT REPLICATION SLAVE ON *.* to 'reader'@'%';
#更改密码策略(当遇到从服务器start slave失败报错Authentication plugin 'caching_sha2_password' reported error时操作!)
ALTER USER 'reader'@'%' IDENTIFIED WITH mysql_native_password BY 'reader';
FLUSH PRIVILEGES;
#获取主数据库的信息,记录第一个bin文件的Position值
SHOW MASTER STATUS;
#退出
EXIT
#获取主数据库在docker中的IP地址
docker inspect --format='{{.NetworkSettings.IPAddress}}' master
#进入从数据库
docker exec -it slaver mysql -uroot -p123456
# 配置连接的参数, 注意IP地址为刚才获取到的主服务器docker地址,master_log_pos填写刚才查到的Position值
change master to master_host='172.17.0.2',master_user='reader',master_password='reader',master_log_file='mysql-bin.000003',master_log_pos=1312;
# 启动同步
start slave;
# 查看是否成功
show slave status\G
# 两项都为Yes时代表成功。
# Slave_IO_Running: Yes
# Slave_SQL_Running: Yes
# 失败需要使用停止连接后检查其他账号密码,地址,pos等参数
# 停止连接,如果一次成功无需使用该命令
stop slave;
Docker 搭建 Redis Cluster 集群环境
主要步骤包括
- 创建网络;
- 下载 Redis 镜像(其实这步可以省略,因为创建容器时,如果本地镜像不存在,就会去远程拉取);
- 编写 Redis 配置文件;
- 创建 Redis 容器;
- 创建 Redis Cluster 集群。
拉取redis镜像
docker pull redis
创建网络
为什么需要创建网络?因为:默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。说简单点就是为了让容器可以直接通过容器名称进行通信。但是使用 Docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。
#创建redis网络
docker network create redis-net
#查看网络模式
docker network ls
docker network inspect redis-net
编写 Redis 配置文件
# 创建目录
mkdir -p /usr/local/docker-redis/redis-cluster
# 切换至指定目录
cd /usr/local/docker-redis/redis-cluster/
# 编写 redis-cluster.tmpl 文件,内容如下
vi redis-cluster.tmpl
port ${PORT}
requirepass 1234
masterauth 1234
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.10.10(换成宿主机的IP地址)
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
port:节点端口;
requirepass:添加访问认证;
masterauth:如果主节点开启了访问认证,从节点访问主节点需要认证;
protected-mode:保护模式,默认值 yes,即开启。开启保护模式以后,需配置 bind ip 或者设置访问密码;关闭保护模式,外部网络可以直接访问;
daemonize:是否以守护线程的方式启动(后台启动),默认 no;
appendonly:是否开启 AOF 持久化模式,默认 no;
cluster-enabled:是否开启集群模式,默认 no;
cluster-config-file:集群节点信息文件;
cluster-node-timeout:集群节点连接超时时间;
cluster-announce-ip:集群节点 IP,这里需要特别注意一下,如果要对外提供访问功能,需要填写宿主机的 IP,如果填写 Docker 分配的 IP(172.x.x.x),可能会导致外部无法正常访问集群;
cluster-announce-port:集群节点映射端口;
cluster-announce-bus-port:集群节点总线端口。
每个 Redis 集群节点都需要打开两个 TCP 连接。一个用于为客户端提供服务的正常 Redis TCP 端口,例如 6379。还有一个基于 6379 端口加 10000 的端口,比如 16379。第二个端口用于集群总线,这是一个使用二进制协议的节点到节点通信通道。节点使用集群总线进行故障检测、配置更新、故障转移授权等等。客户端永远不要尝试与集群总线端口通信,与正常的 Redis 命令端口通信即可,但是请确保防火墙中的这两个端口都已经打开,否则 Redis 集群节点将无法通信。
# 在 redis-cluster 目录下执行以下命令循环创建 6371 ~ 6376 相关的目录及文件
for port in `seq 6371 6376`; do \
mkdir -p ${port}/conf \
&& PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \
&& mkdir -p ${port}/data;\
done
查看命令执行结果,如果没有 tree 命令先安装 yum install -y tree
也可以通过以下命令来查看文件配置
cat /usr/local/docker-redis/redis-cluster/637{1..6}/conf/redis.conf
创建Redis容器
将宿主机的 6371 ~ 6376 之间的端口与 6 个 Redis 容器映射,并将宿主机的目录与容器内的目录进行映射(目录挂载)。记得指定网络模式,使用创建好的的 redis-net 网络。
for port in $(seq 6371 6376); do \
docker run -di -p ${port}:${port} -p 1${port}:1${port} \
--restart always --name redis-${port} --net redis-net \
-v /usr/local/docker-redis/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-v /usr/local/docker-redis/redis-cluster/${port}/data:/data \
redis redis-server /usr/local/etc/redis/redis.conf; \
done
#查看容器是否创建成功
docker ps -n 6
#查看给每个节点分配的IP信息
docker network inspect redis-net | grep -i -E "name|ipv4address"
创建 Redis Cluster 集群
# 随便进入一个容器
docker exec -it redis-6371 bash
# 切换至指定目录
cd /usr/local/bin/
#创建Redis Cluster 集群,出现提示信息时,输入 yes
redis-cli -a 1234 --cluster create 172.18.0.2:6371 172.18.0.3:6372 172.18.0.4:6373 172.18.0.5:6374 172.18.0.6:6375 172.18.0.7:6376 --cluster-replicas 1
#检查集群状态
# 使用 IP
redis-cli -a 1234 --cluster check 192.168.10.10:6371
# 使用容器名称
redis-cli -a 1234 --cluster check redis-6372:6372
#查看集群信息和节点信息
# 连接至集群某个节点
redis-cli -c -a 1234 -h redis-6373 -p 6373
# 查看集群信息
redis-cli -a 1234 --cluster info 192.168.10.10:6371
验证set/get分布
# 进入容器并连接至集群某个节点
docker exec -it redis-6371 /usr/local/bin/redis-cli -c -a 1234 -h redis-6371 -p 6371
# 写入数据
set name mrhelloworld
set aaa 111
set bbb 222
# 读取数据
get name
get aaa
get bbb
解释:
- 首先进入容器并连接至集群某个节点;
- 然后执行第一个 set 命令 set name mrhelloworld,name 键根据哈希函数运算以后得到的值为 [5798]。当前集群环境的槽分配情况为:[0-5460] 6371节点,[5461-10922] 6372节点,[10923-16383] 6373节点,所以该键的存储就被分配到了 6372 节点上;
- 再来看第二个 set 命令 set aaa,这里大家可能会有一些疑问,为什么看不到 aaa 键根据哈希函数运算以后得到的值?因为刚才重定向至 6372 节点插入了数据,此时如果还有数据插入,正好键根据哈希函数运算以后得到的值也还在该节点的范围内,那么直接插入数据即可;
- 接着是第三个 set 命令 set bbb,bbb 键根据哈希函数运算以后得到的值为 [5287],所以该键的存储就被分配到了 6371 节点上;
- 然后是读取操作,第四个命令 get name,name 键根据哈希函数运算以后得到的值为 [5798],被重定向至 6372 节点读取;
- 第五个命令 get aaa,aaa 键根据哈希函数运算以后得到的值也在 6372 节点,直接读取;
- 第六个命令 get bbb,bbb 键根据哈希函数运算以后得到的值为 [5287],被重定向至 6371 节点读取。
通过以上操作我们得知 name 键的存储被分配到了 6372 节点,如果直接连接 6372 节点并获取该值会怎么样?没错,不需要重定向节点,因为数据就在该节点,所以直接读取返回。 - 总结下来就是,在 Redis Cluster 集群模式中,无论连接哪个节点,每次我们执行写入或者读取操作的时候,所有的键会根据哈希函数运算并映射到 0 ~ 16383 整数槽内,如果恰好对应的槽就在你当前连接的节点中,则直接执行命令,否则重定向至对应节点执行命令。
引用