一.单机版
1.tomcat
1.查找镜像:docker search tomcat
2.拉取镜像:docker pull tomcat
3.运行容器:docker run -d -p 8080:8080 --name mytomcat tomcat ;参数: i:交互 t:终端 d:后台 name:指定名字
拓展,新版Tomcat移除首页
进入容器:`docker exec -it ID /bin/bash` 发现webapps里面已经移除了。
删除webapps:rm -r webapps
改动:mv webapps.dist webapps
2.mysql
1.查找镜像:docker search mysql:5.7
2.拉取镜像:docker pull mysql:5.7
3.启动容器:docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
4.进入容器:docker exec -it 1240e2657e23 /bin/bash
5.登录mysql:mysql -uroot -p123456
待解决的问题:
docker下的mysql会出现中文乱码`SHOW VARIABLES LIKE 'character%';`。
mysql数据备份。
重新安装 正式版本:
1.重新启动一个容器 挂载宿主机容器卷
docker run -d -p 3306:3306 --privileged=true -v /yzt/mysql/log:/var/log/mysql -v /yzt/mysql/data:/var/lib/mysql -v /yzt/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
2.新建文件,通过容器卷同步给mysql容器实例
4.进入刚才挂载的配置目录:cd /yzt/mysql/conf 新建并打开:vim my.cnf 加入如下内容:
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
5.重新启动mysql:docker restart ID 进入容器 docker exec -it ID /bin/bash 进入mysql:mysql -uroot -p123456
3.测试
3.redis
1.查找镜像:docker search redis:6.0.8
2.拉取镜像:docker pull redis:6.0.8
3.新建redis需要挂载的目录:mkdir -p /yzt/redis 拷贝一个redis.conf配置文件(修改一下)到这个目录下
4.redis启动命令:docker run -p 6379:6379 --name myr3 --privileged=true -v /yzt/redis/redis.conf:/etc/redis/redis.conf -v /yzt/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
3.进入启动的容器:docker exec -it ID /bin/bash;连接redisCli:redis-cli
二、集群版
1.安装mysql集群-主从
1.安装运行mysql5.7 先启动主机:mysql-master 将目录挂载到宿主机yzt目录下
docker run -p 3307:3306 --name mysql-master \
-v /yzt/mysql-master/log:/var/log/mysql \
-v /yzt/mysql-master/data:/var/lib/mysql \
-v /yzt/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
2.进入/yzt/mysql-master/conf目录下新建:vim my.cnf
[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
## 免密登录
##skip-grant-tables
安装小坑:如果安装过程遇到密码死活不正确,可以先免密登录上去,修改密码为空,之后再改密码。
use mysql;
select user,authentication_string,host from user;
update user set authentication_string='' where user='root';
flush privileges;
退出mysql,把第一步的skip-grant-tables注释。再重启mysql;
alter user 'root'@'localhost' IDENTIFIED BY '123456';
alter user 'root'@'%' IDENTIFIED BY '123456';
flush privileges;
修改root密码完成。
3.master容器实例内创建数据同步用户。授予从机权限
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
4.启动从服务器 mysql-slave
docker run -p 3308:3306 --name mysql-slave \
-v /yzt/mysql-slave/log:/var/log/mysql \
-v /yzt/mysql-slave/data:/var/lib/mysql \
-v /yzt/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
5.进入/yzt/mysql-slave/conf目录下新建:vim my.cnf
[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
6.修改配置文件都要重启:docker restart ID
7.在主数据库中查询主从同步状态:show master status; 里面的信息配置从机有用mall-mysql-bin和 master_log_pos。
8.进入从机sleave里面:docker exec -it ID /bin/bash mysql -uroot -p123456;在从数据库中配置主 从复制,在mysql里面执行:
change master to master_host='宿主机ip', master_user='slave',
master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000007',
master_log_pos=1249, master_connect_retry=30;
9.从数据库中查看主从同步状态:show slave status \G;
10.在从数据库中开启主从同步:start slave;
11.继续查看状态:show slave status \G;;如果变成两个Yes说明配置成功!
2.安装redis集群
1.当数据量大的时候,一台redis无法满足这么庞大的数据存储,这时候一般进行集群数据分摊在每一台机子上,一般使用哈希取余分区hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。这样做有坏处就是假如之后机器增加了或者某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。
2.一致性哈希算法分区:目的是当服务器个数发生变动时, 尽量减少影响客户端到服务器的映射关系。
一致性哈希环:一致性哈希算法必然有个hash函数并按照算法产生hash值,
这个算法的所有可能哈希值会构成一个全量集这个集合可以成为一个hash空间[0,2^32-1],
这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0 = 2^32),
这样让它逻辑上形成了一个环形空间。
节点映射:将集群中各个IP节点映射到环上的某一个位置。
落键规则:当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),
将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,
从此位置沿环顺时针行走,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。
3.一致性哈希算法的优点
容错性 假设Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。
扩展性 数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。
4.一致性哈希算法的缺点:一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题。如图落在ab间的概率明显小于ba间,所以在ba间的数据就会一直落在a节点。
5.哈希槽分区:哈希槽实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。 解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。
哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。
多少个hash槽
一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有求。
可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。
解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。
slot = CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
哈希槽计算
Redis 集群中内置了 16384 个哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,
然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,
也就是映射到某个节点上。如下代码,key之A 、B在Node2, key之C落在Node3上
2.安装mysql集群-主从(三主三从)
1.新建6个docker容器redis实例: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 开启集群:--cluster-enabled yes 开启6台,分别redis-node-16 端口63816386 存放目录也是。
2.进入docker实例 docker exec -it redis-node-1 /bin/bash
执行:redis-cli --cluster create 192.168.146.100:6381 192.168.146.100:6382 192.168.146.100:6383 192.168.146.100:6384 192.168.146.100:6385 192.168.146.100:6386 --cluster-replicas 1 --cluster-replicas 1 表示为每个master创建一个slave节点。如图显示分配的hash槽。
3.进入一台机子:redis-cli -p 6381 查看集群状态:cluster info 查看节点状态:cluster nodes
由图可以看出master和sleave挂载关系。
存储数据也会根据你存的key进行计算,计算出你具体存在那个槽位上面。单机连接就会出现有些值存不进去。
使用
redis-cli -p 6381 -c加入参数-c,优化路由:路由跳转到计算出来槽位的机器上。
查看集群信息:redis-cli --cluster check 192.168.146.100:6381
3.假如一台主机宕机,后面的从机上位做主机master,假如从机回来了,继续当从机。
4.主从扩容: 继续启动节点:7和8
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。
5.将6387节点(空槽号)作为master节点加入原集群。命令模式 redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381 6387 就是将要作为master新增节点 6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群。
6.进入7号机:docker exec -it redis-node-7 /bin/bash 加入集群
redis-cli --cluster add-node 192.168.146.100:6387 192.168.146.100:6381
如图查看集群情况。
查看新集群命令:
redis-cli --cluster check 192.168.146.100:6381,新加入的节点没有槽位
7.因为新加入的兄弟没有槽位,所以需要从新分配槽位。重新分派槽号命令: redis-cli --cluster reshard 192.168.146.100:6381
平均分配:4096,ID为我们要为哪台机子分配,我们写7号机。
继续查看集群情况:redis-cli --cluster check 192.168.146.100:6381,此时7号机就重新获得了槽位。查看槽位大小可得,前面3台机子都给了他一点共同凑成4096。他的槽位大小由3个构成。
8.为8号机分配主节点,因为7号机已经获得了槽位,
redis-cli --cluster add-node 192.168.146.100:6388 192.168.146.100:6387 --cluster-slave --cluster-master-id fc412e110a42426d793dfcf948cda1f2dd37a6e7
查看集群:redis-cli --cluster check 192.168.146.100:6382,此时集群中出现了8台机子。
9.主从缩容: 先从集群中把后加的8号机(从机)删除:
redis-cli --cluster del-node 192.168.146.100:6388 8e6d7563f3d7a7644930b9133b0724102a9f7458
检查发现只剩下7台机子。
将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
redis-cli --cluster reshard 192.168.146.100:6381
此时6387节点存在,但是里面的槽位全部没了。
redis-cli --cluster check 192.168.146.100:6381
删除7号机器 redis-cli --cluster del-node 192.168.146.100:6387 fc412e110a42426d793dfcf948cda1f2dd37a6e7
重新查看集群又变成了3主3从