docker实践(提供几个安装案例)
- 安装Tomcat
# 拉取镜像,可以指定标签不指定默认为最新
docker pull tomcat
docker run -itd -p 8080:8080 --name tomcat tomcat:latest
#这样内部默认80端口,主机的映射端口会随机分配一个
docker run -itd -P tomcat
#可以用这个命令查看端口8080是否已经监听
netstat -ntlp
这里需要注意的是可能访问8080的时候会出现404(往往出现在新版中),是因为新版webapp目录下没有任何呢内容。
docker exec -it tomcat /bin/bash
#官方把欢迎页面放到了另一个位置
mv webapps.dist/ webapps
- 安装mysql
我们以经典的mysql5.7为例
docker pull mysql:5.7
docker run -d -p 13306:3306 --privileged=true -v /data/mysql/logs:/var/log/mysql -v /data/mysql/data:/var/lib/mysql -v /opt/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=654321 --name mysql mysql:5.7
注意我们需要解决乱码的问题
修改配置文件,设置编码
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
bind-address = 0.0.0.0 #允许所有IP连接,生产环境中不允许这么配置
character_set_server = utf8
配置修改后可以,用下面的命令查看字符集,可以在容器内部用客户端连接也可以用连接工具。
show variables like '%char%'
- 安装redis
docker pull redis
docker run -p 16379:6379 --name redis --privileged=true -v /opt/conf/redis/redis.conf:/etc/redis/redis.conf -v /data/redis/data:/data -d redis:latest redis-server /etc/redis/redis.conf
配置文件,注意生成环境中别这样配置,除了daemonize no这个,这样配置不安全。
bind 127.0.0.1
daemonize no
protected-mode no
进阶篇
安装进阶
- mysql主从复制搭建
安装master
docker run -p 13307:3306 --name mysql-master \
-v /data/mysql-master/log:/var/log/mysql \
-v /data/mysql-master/data:/var/lib/mysql \
-v /data/mysql-master/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=654321 \
-d mysql:5.7
修改配置文件并重启容器
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062```
master容器实例内创建数据同步用户,这是为了安全控制权限
CREATE USER 'slave' @'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave' @'%';
安装从节点
docker run -p 13308:3306 --name mysql-slave \
-v /data/mysql-slave/log:/var/log/mysql \
-v /data/mysql-slave/data:/var/lib/mysql \
-v /data/mysql-slave/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=654321 \
-d mysql:5.7
修改配置文件
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
在主数据库中查看同步状态,需要进入容器然后 mysql -uroot -p 客户端连接后输入此命令
show master status; 注意啦一定要有分号否则你只会看到输出一个箭头
在从数据库中配置主从复制,注意也是进入容器内部mysql客户端连接后执行
#这里的参数值都是之前配置的
change master to master_host='宿主机ip', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
#参数说明
master_host:主数据库的IP地址;
master_port:主数据库的运行端口;
master_user:在主数据库创建的用于同步数据的用户账号;
master_password:在主数据库创建的用于同步数据的用户密码;
master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
master_connect_retry:连接失败重试的时间间隔,单位为秒。
查看从数据库的同步状态
show slave status \G; \G只是换一种方式展示结果
在从数据库开启主从同步
start slave; #需要看到这两个参数是yes
这里踩坑了,怎么弄第一个都显示connecting, 后面看了下文,是端口不通的问题。
https://dba.stackexchange.com/questions/140929/slave-io-running-connecting-in-master-slave-replication
下面就是在master建表,看看从机有没有就OK。
- redis 如何存储1-2亿条数据(非常重要,学的是这个设计思想)
下面先介绍哈希存储的算法
- 普通哈希分区(对节点数量进行取余)
- 一致性哈希算法分区
就是有一个hash环,这样在迁移的时候不会重新洗牌,迁移少量机器即可。但是这样在数据节点太少的情况下,又会出现数据倾斜的问题。
- 哈希槽算法
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。
集群搭建实战(三主三从)
开启6台redis
#这里注意网络模式都是主机,生成环境中推荐用bridge模式,创建一个自定义网络,将它们部署到统一网络下,这样可以通过服务名访问到服务
docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
随便进入一台redis的内部搭建集群关系
redis-cli --cluster create ip:6381 ip:6382 ip:6383 ip:6384 ip:6385 ip:6386 --cluster-replicas 1
然后连接客户端查看相关信息,需要注意我们要指定端口因为我们启动的时候已经指定了端口 redis-cli -p 6381
cluster info
cluster nodes
下面注意了我们存储key的时候就需要连接集群了,如果单机只有一部分槽位那能存,如果集群就会自动跳过去。
redis-cli -p 6381 -c #下图展示了如果不是当前机器的槽位会自动跳
redis-cli --cluster check 127.0.0.1:6381
下面可以测试一下(比较简单这里不再演示),停掉一个实例,slave就会上位变成master,保证集群照样可用,后面恢复后也不会复原master的地位变成了slave。
集群扩容
新增节点
docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
添加节点
redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
我们看到虽然加入了集群但是没有分配槽位
分配槽位(每一台机器各出一些槽位分配给新机器):
redis-cli --cluster reshard 127.0.0.1:6381 #执行会提示填入分区的大小,一般采用均分,然后还需要填入新节点的ID
为主节点分配从节点:
redis-cli --cluster add-node 127.0.0.1:6388 127.0.0.1:6387 --cluster-slave --cluster-master-id 8b242a216d91366916054fca6b5c1ee4129d05b9
集群缩容
#删除88节点
redis-cli --cluster del-node 127.0.0.1:6388 5d149074b7e57b802287d1797a874ed7a1a284a8
#重新分配槽位,注意将槽位全部删除才能继续删除87节点
redis-cli --cluster reshard 192.168.111.147:6381