doker部署服务

一、tomcat

docker pull billygoo/tomcat8-jdk8
docker images
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8:latest

二、mysql

1.单机配置

//下载镜像
docker pull mysql:5.7
//创建容器并挂载在容器卷
docker run -d -p 3306:3306 --privileged=true \
-v /lizjuse/mysql/log:/var/log/mysql \
-v /lizjuse/mysql/data:/var/lib/mysql \
-v /lizjuse/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql5.7_1 mysql:5.7
//配置mysql
cd /lizjuse/mysql/conf
vim my.cnf
[client]
default_character_set = utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8

2.主从复制配置

主服务器3307,从服务器3308

①创建主机
//创建3307
docker run -p 3307:3306 --name mysql-master \
-v/mydata/mysql-master/log:/var/log/mysql \
-v/mydata/mysql-master/data:/var/lib/mysql \
-v/mydata/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
//创建3308
docker run -p 3308:3306 --name mysql-slave \
-v/mydata/mysql-slave/log:/var/log/mysql \
-v/mydata/mysql-slave/data:/var/lib/mysql \
-v/mydata/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
②mysql配置文件my.cnf
##master
[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
##跳过主从复制中遇到的所有错误或指定类型的错误,避免slaves端复制中断。
##如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
##slave
[mysqld]
##设置server_id,同一局域网中需要唯一
server_id=102
#指定不需要同步的数据库名称
binlog-ignore-db=mysql
#开启二进制日志功能,以备Slave作为其它数据库实例的Masterl时使用
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
#slavei设置为只读(具有super权限的用户除外)
read_only=1
③配置

主数据库master数据库创建授权用户

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';

查看主从同步状态show master status;
从数据库slave配置主从复制

change master to master_host='172.21.55.100',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000001',master_log_pos=617,master_connect_retry=30;

查看主从同步状态show slave status \G;

从数据库slave开启主从同步start slave;

三、redis

1.单机配置

配置文件完成版(密码123456)

//下载镜像
docker pull redis:6.0.8
//创建容器并挂载在容器卷
docker run -d -p 6379:6379 --privileged=true \
-v /lizjuse/redis/redis.conf:/etc/redis/redis.conf \
-v /lizjuse/redis/data:/data \
--name redis6.0.8_1 \
-d redis:6.0.8  redis-server /etc/redis/redis.conf
//测试
redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>

2.集群配置

①创建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
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-cli --cluster create 172.21.55.100:6381 172.21.55.100:6382 172.21.55.100:6383 172.21.55.100:6384 172.21.55.100:6385 172.21.55.100:6386 --cluster-replicas 1

查看集群信息

//进入节点
root@lizj:/data# redis-cli -p 6381
//查看集群详情
127.0.0.1:6381> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:200
cluster_stats_messages_pong_sent:191
cluster_stats_messages_sent:391
cluster_stats_messages_ping_received:186
cluster_stats_messages_pong_received:200
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:391
//查看节点状态
127.0.0.1:6381> cluster nodes
8716061af89bd1ab05c7b61344fc1710ce42cc1c 172.21.55.100:6386@16386 slave 6e5c36d824e2838c7ef138d72ea81601ee6d28be 0 1697121966814 3 connected
6e5c36d824e2838c7ef138d72ea81601ee6d28be 172.21.55.100:6383@16383 master - 0 1697121966000 3 connected 10923-16383
21e5a7fecc3b664af5ee9355d4be81083fbfa5c1 172.21.55.100:6382@16382 master - 0 1697121967878 2 connected 5461-10922
d04aa04a5fdca742658ff2a65b8eb09c316a59c1 172.21.55.100:6381@16381 myself,master - 0 1697121965000 1 connected 0-5460
33a571d032e6f389473679de135724b1663e4a6c 172.21.55.100:6384@16384 slave d04aa04a5fdca742658ff2a65b8eb09c316a59c1 0 1697121965000 1 connected
54da511af35f7143881277f1bdc7c3df9709c948 172.21.55.100:6385@16385 slave 21e5a7fecc3b664af5ee9355d4be81083fbfa5c1 0 1697121966000 2 connected

可以看出主从分别为83:86,81:84,82:85

连接集群化redis要使用参数-c优化路由redis-cli -p 6381 -c

存储范围

实现自动跳转对应的节点

查看个节点hash存储情况redis-cli --cluster check 172.21.55.100:6381

②主从扩容(写入简历,问哈希槽的重新分配)

创建节点容器

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节点7进行配置

[root@lizj ~]# docker exec -it redis-node-7 bash
root@lizj:/data# redis-cli --cluster add-node 172.21.55.100:6387 172.21.55.100:6381
#检查添加情况可以发现6387添加成功但没有槽位
root@lizj:/data# redis-cli --cluster check 172.21.55.100:6381
172.21.55.100:6381 (d04aa04a...) -> 2 keys | 5461 slots | 1 slaves.
172.21.55.100:6382 (21e5a7fe...) -> 1 keys | 5462 slots | 1 slaves.
172.21.55.100:6387 (59bca87e...) -> 0 keys | 0 slots | 0 slaves.
172.21.55.100:6383 (6e5c36d8...) -> 1 keys | 5461 slots | 1 slaves.
[OK] 4 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 172.21.55.100:6381)
M: d04aa04a5fdca742658ff2a65b8eb09c316a59c1 172.21.55.100:6381
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 33a571d032e6f389473679de135724b1663e4a6c 172.21.55.100:6384
   slots: (0 slots) slave
   replicates d04aa04a5fdca742658ff2a65b8eb09c316a59c1
M: 21e5a7fecc3b664af5ee9355d4be81083fbfa5c1 172.21.55.100:6382
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 54da511af35f7143881277f1bdc7c3df9709c948 172.21.55.100:6385
   slots: (0 slots) slave
   replicates 21e5a7fecc3b664af5ee9355d4be81083fbfa5c1
S: 8716061af89bd1ab05c7b61344fc1710ce42cc1c 172.21.55.100:6386
   slots: (0 slots) slave
   replicates 6e5c36d824e2838c7ef138d72ea81601ee6d28be
M: 59bca87efa0732360c7c2079750636b695147266 172.21.55.100:6387
   slots: (0 slots) master
M: 6e5c36d824e2838c7ef138d72ea81601ee6d28be 172.21.55.100:6383
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

重新分配槽号

root@lizj:/data# redis-cli --cluster reshard 172.21.55.100:6381
>>> Performing Cluster Check (using node 172.21.55.100:6381)
M: d04aa04a5fdca742658ff2a65b8eb09c316a59c1 172.21.55.100:6381
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 33a571d032e6f389473679de135724b1663e4a6c 172.21.55.100:6384
   slots: (0 slots) slave
   replicates d04aa04a5fdca742658ff2a65b8eb09c316a59c1
M: 21e5a7fecc3b664af5ee9355d4be81083fbfa5c1 172.21.55.100:6382
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 54da511af35f7143881277f1bdc7c3df9709c948 172.21.55.100:6385
   slots: (0 slots) slave
   replicates 21e5a7fecc3b664af5ee9355d4be81083fbfa5c1
S: 8716061af89bd1ab05c7b61344fc1710ce42cc1c 172.21.55.100:6386
   slots: (0 slots) slave
   replicates 6e5c36d824e2838c7ef138d72ea81601ee6d28be
M: 59bca87efa0732360c7c2079750636b695147266 172.21.55.100:6387
   slots: (0 slots) master
M: 6e5c36d824e2838c7ef138d72ea81601ee6d28be 172.21.55.100:6383
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID? 59bca87efa0732360c7c2079750636b695147266
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: all

4096为16384/4=4096,id为新增节点的id

重新检查状态,可观察到已有槽位,每个节点匀了一点凑到4096

添加从节点

root@lizj:/data# redis-cli --cluster add-node 172.21.55.100:6388 172.21.55.100:6387 --cluster-slave --cluster-master-id 59bca87efa0732360c7c2079750636b695147266
③主从缩容(写入简历,问哈希槽的重新分配)

步骤
1.先清除从节点6388
2.清出来的槽号重新分配
3.再删除6387
4.恢复成3主3从

删除从节点6388
redis-cli --cluster del-node [主机IP]:[要删除的节点端口号] 要删除的节点id

root@lizj:/data# redis-cli --cluster del-node 172.21.55.100:6388 07e82323cc3eda6517863a7438b2b2f89152fd56
>>> Removing node 07e82323cc3eda6517863a7438b2b2f89152fd56 from cluster 172.21.55.100:6388
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.

将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
redis-cli --cluster reshard 172.21.55.100:6381

以6381为入口操作整个集群的槽号


删除节点6387
redis-cli --cluster del-node [主机IP]:[要删除的节点端口号] 要删除的节点id

root@lizj:/data# redis-cli --cluster del-node 172.21.55.100:6387 59bca87efa0732360c7c2079750636b695147266
>>> Removing node 59bca87efa0732360c7c2079750636b695147266 from cluster 172.21.55.100:6387
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.

3.面试题

1~2亿条数据需要缓存。请问如何设计这个存储案例?
回答:单机单台100%不可能,肯定是分布式存储,用redis如何落地?
上述问题阿里P6~P7工程案例和场景设计类必考题目,一般业界有3种解决方案
①哈希取余分区(小厂)


2亿条记录就是2亿个k,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

优点:简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。
缺点:原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

②一致性哈希算法分区(中厂)

三步骤:算法构建一致性哈希环、服务器IP节点映射、key落到服务器的落键规则

算法构建一致性哈希环
一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,232-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0=232),这样让它逻辑上形成了一个环形空间。

它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Hash算法是对232取模,简单来说,致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-232-1(即哈希值是一个32位无符号整形),整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、……直到232-1,也就是说0点左侧的第一个点代表232-1,0和232-1在零点中方向重合,我们把这个由232个点组成的圆环称为Hash环。


服务器IP节点映射
将集群中各个P节点映射到环上的某一个位置。

将各个服务器使用Hash进行一个哈希,具体可以选择服务器的P或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:


key落到服务器的落键规则
当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。


优点:一致性哈希算法的容错性、一致性哈希算法的扩展性
缺点:致性哈希算法的数据倾斜问题,一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,例如系统中只有两台服务器:

总结:
为了在节点数目发生改变时尽可能少的迁移数据
将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。
而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。
优点
加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。
缺点
数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

③哈希槽分区(大厂)

哈希槽实质就是一个数组,数组[0,214 -1]形成hash slot空间。

解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽 (slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。


槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。
哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。
多少个hash槽
一个集排只能有16384个槽(不超过1000个节点),归号0-16383(0-241)。这些会。给集集群的所有于节点,分配策没有要求,可以超定哪些编号的题分配经哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是儿key就落入欢应的槽里。slot= CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
哈希槽计算
Redis集群中内置了16384个哈希槽,redis会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在Redis集群中放置一个key-vaue时,redis先对key使用crc16算法算出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16383之间的哈希槽,也就是映射到某个节点上。如下代码,key之A、B在Node2,key之C落在Node3上。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容