前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探索云原生技术之基石——Docker容器

探索云原生技术之基石——Docker容器

作者头像
IT大咖说
发布2022-06-09 11:40:54
3670
发布2022-06-09 11:40:54
举报
文章被收录于专栏:IT大咖说IT大咖说

文章目录

什么是云原生

什么是Docker

MySQL主从复制(1主1从)

  •  Master节点配置
  • Slave节点配置
  • 测试主从同步
  • 主从同步失败问题(Slave_SQL_Running:No)
    • Slave_SQL_Running:No的解决办法

Redis集群(3主6从)

  • 10亿条数据怎么进行缓存
    • 哈希取余算法(小厂采用)
    • 一致性hash算法(中大厂采用)
    • hash槽算法(大厂采用、和Redis集群也是采用这种)
  • 快速搭建Redis Cluster(3主6从)
    • 快速生成9个容器实例
    • 查看容器实例是否全部启动
    • 配置主从
    • 以集群的方式进入Redis客户端
    • 操作set命令
    • 查看集群节点信息
    • 查看集群状态
  • 主从切换
  • 主从扩容
  • 主从缩容

什么是云原生

Pivotal公司的Matt Stine于2013年首次提出云原生(Cloud-Native)的概念;2015年,云原生刚推广时,Matt Stine在《迁移到云原生架构》一书中定义了符合云原生架构的几个特征:12因素、微服务、自敏捷架构、基于API协作、扛脆弱性;到了2017年,Matt Stine在接受InfoQ采访时又改了口风,将云原生架构归纳为模块化、可观察、可部署、可测试、可替换、可处理6特质;而Pivotal最新官网对云原生概括为4个要点:DevOps+持续交付+微服务+容器。

总而言之,符合云原生架构的应用程序应该是:采用开源堆栈(K8S+Docker)进行容器化,基于微服务架构提高灵活性和可维护性,借助敏捷方法、DevOps支持持续迭代和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。

什么是Docker

  • Docker 是一个开源的应用容器引擎,基于Go语言开发。
  • Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
  • 容器是完全使用沙箱机制(容器实例相互隔离),容器性能开销极低(高性能)。

总而言之:

Docker是一个高性能的容器引擎;

可以把本地源代码、配置文件、依赖、环境通通打包成一个容器即可以到处运行;

使用Docker安装软件十分方便,而且安装的软件十分精简,方便扩展。

MySQL主从复制(1主1从)

Master节点配置

  • 运行一个mysql容器实例。作为Master节点
  • 创建my.cnf文件(也就是mysql的配置文件)
  • 将内容粘贴进my.cnf文件
  • 重启该mysql容器实例
  • 进入容器内部,并登陆mysql
  • 在Master节点的MySQL中创建用户和分配权限

在主数据库创建的该帐号密码只是用来进行同步数据。

Slave节点配置

  • 运行一个MySQL容器实例,作为slave节点(从节点)
  • 创建my.cnf文件(也就是mysql的配置文件)
  • 将内容粘贴进my.cnf文件
  • 重启该mysql容器实例
  • 查看容器实例是否都是up
代码语言:javascript
复制
[root@aubin ~]# docker psCONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                                                  NAMES2c4136668536   mysql:5.7   "docker-entrypoint.s…"   3 minutes ago   Up 9 seconds   33060/tcp, 0.0.0.0:3308->3306/tcp, :::3308->3306/tcp   mysql-slave20fc7174d1a7   mysql:5.7   "docker-entrypoint.s…"   15 hours ago    Up 8 minutes   33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp   mysql-master
  • 进入Master节点查看主从同步状态
  • 进入从机MySQL
  • 在从数据库(slave)配置主从同步(重点)

在Master节点中找到ens33的ip地址并放到下面的master_host中(记住这个ip是Master数据库的服务器ip,不是从数据库的):

记住下面这个命令要在从(slave)数据库执行:

代码语言:javascript
复制
change master to master_host='192.168.184.132',master_user='slave',master_password='123456',master_port=3307,master_log_file='order-mysql-bin.000001',master_log_pos=617,master_connect_retry=30;

配置参数解析

  1. master_host:主数据库(Master)的 ip 地址
  2. master_user:在Master数据库中创建的用来进行同步的帐号
  3. master_password:在Master数据库中创建的用来进行同步的帐号的密码
  4. master_port:Master数据库的 MySQL端口号,这里是3307
  5. master_log_file:MySQL的 binlog文件名
  6. master_log_pos:binlog读取位置
  • 在从数据库(slave)查看主从同步状态:

我们找到里面的Slave_IO_Running: No,Slave_SQL_Running: No属性,发现都是No的状态,证明主从同步还没有开始。。。

  • 在从数据库(slave)正式开启主从同步
  • 再次在从数据库中查看主从同步状态

我们可以看到已经都为yes了,说明主从同步已经开启。

测试主从同步

在Master数据库执行:

  • 创建数据库
  • 使用数据库
  • 创建表(表是我从之前写的项目中拿的)
  • 插入数据
  • 查询数据库表(在Master数据库执行)
  • 切换从数据库机器(在slave数据库执行)
  • 查询数据库表(在slave数据库执行)
  • Docker+MySQL主从同步搞定!

也可以用Navicat去连接这两个数据库。如果Navicat出现连接不了docker的mysql,则可以:

方法一:关闭防火墙(测试环境用,生产环境不可以用)

方法二:开放防火墙对应端口,比如master数据库的3307和slave数据库的3308(生产环境用这个)

主从同步失败问题(Slave_SQL_Running:No)

代码语言:javascript
复制
mysql> show slave status \G;*************************** 1. row ***************************               Slave_IO_State: Waiting for master to send event                  Master_Host: 192.168.184.132                  Master_User: slave                  Master_Port: 3307                Connect_Retry: 30              Master_Log_File: order-mysql-bin.000001          Read_Master_Log_Pos: 3752               Relay_Log_File: 2c4136668536-relay-bin.000002                Relay_Log_Pos: 326        Relay_Master_Log_File: order-mysql-bin.000001             Slave_IO_Running: Yes            Slave_SQL_Running: No              Replicate_Do_DB:           Replicate_Ignore_DB:            Replicate_Do_Table:        Replicate_Ignore_Table:       Replicate_Wild_Do_Table:   Replicate_Wild_Ignore_Table:                    Last_Errno: 1007                   Last_Error: Error 'Can't create database 'mall';                    database exists' on query. Default database:                     'mall'. Query: 'create database mall'
  • Slave_SQL_Running为No的状态,那么这是为什么呢?
  • 可以看到Last_Error: Error ‘Can’t create database ‘mall’; database exists’ on query. Default database: ‘mall’. Query: ‘create database mall’
  • 原因是主数据库(Master)和从数据库(slave)不一致造成的,我在从数据库执行了命令导致数据不一致,最终导致主从复制失败。

Slave_SQL_Running:No的解决办法

1:把主数据库和从数据库变成一模一样,也就是把多余的数据库和表删除掉,变成默认的mysql状态。(切记生产环境下要做好数据备份!!!)

2:结束同步:

3:再次开启同步:

4:搞定!

Redis集群(3主6从)

10亿条数据怎么进行缓存

  • 这么大量的数据放在一个Redis里面显然是不行的,所以我们必须进行搭建分布式的Redis集群进行存储。
  • 那么我们如何确定每一条数据存放在哪一个Redis中呢?我们有如下三种方法。

哈希取余算法(小厂采用)

过程

1:假设一共有5台Redis服务器,编号分别为:0 1 2 3 4,服务器台数为count=5

2:先把key(关键字)进行哈希后产生一个哈希值为val,假设这个val为22

3:再用哈希取余算法公式:val%count,也就是22%5=2

4:那么就定位到3号(0为1号机器),那么该数据就插入3号Redis机器中

缺点:

1:Redis节点扩容十分麻烦,如果此时从5台机器变成10台,那么我们需要去修改哈希取余算法的公式,不利于扩展。

2:又或者是缩容也十分麻烦,如果有一台服务器宕机了,在线机器从5->4台,那么也需要去修改哈希取余算法公式。

一致性hash算法(中大厂采用)

图解:

先虚拟一个哈希环,记录我们机器的ip的hash对应到哈希环中:

将对象的关键字key进行hash,顺时针寻找我们的机器,如果机器还在线就插入:

过程

1:虚拟一个哈希环(类似于大小为2^32的数组arr),即0 ~ (2^32)-1的空间中。

2:对我们所有的Redis节点所在的服务器IP或者主机名进行hash,得到的这个hash值记录下来。

3:先把key(关键字)进行hash后产生一个hash值为val

4:把这个val当成数组的下标进行遍历(也就是从这个位置顺时针遍历哈希环)一旦遇到Redis节点的hash值则进行插入,如果该节点宕机了则插入失败,这个时候我们就会跳过这个Redis节点继续顺时针搜索合适的节点,直到插入成功或者遍历完整个哈希环(当然此时是最坏情况)。

5:如果有新增的节点就按照第2步操作即可

6:如果Redis节点被删除或者宕机了,就移除这个记录的节点即可。

优点:

方便扩容和缩容,不需要和哈希取余算法一样更改算法公式,扩展性很好。

是因为哈希环的大小是2^32,几乎涵盖了所有hash值的可能。

缺点:

  • 缺点也是十分明显的,当我们的Redis节点过少时,会造成数据倾斜问题。这种问题也是十分致命的。
  • 因此该算法小厂不适合用,中大厂在多节点的情况下采用效果会更好。

hash槽算法(大厂采用、和Redis集群也是采用这种)

1:由于一致性hash算法会导致数据倾斜问题,而hash槽可以避免这个问题。

2:Redis的hash槽大小固定为:16384个。

3:将hash槽均匀分配到各个Master节点上(注意:slave节点不会被分配)

4:假如有三个Redis节点,则会分配成5461:5462:5461

  • Redis的1号节点:负责0-5460号槽位
  • Redis的2号节点:负责5461-10922号槽位
  • Redis的3号节点:负责10923-16383号槽位

5:将关键字(key)进行hash取值,并且映射到对应的hash槽位上。

6:如果需要扩容或者缩容,只需要重新分配槽位即可。

快速搭建Redis Cluster(3主6从)

搭建的集群为:3主6从。

其中内部是1个Master主节点对应2个slave从节点

快速生成9个容器实例

  • 由于我们搭建3主6从,所以需要9个Redis容器实例。这里的Redis都是最新版,如果需要改变版本,只需要把下面的版本换成你需要指定的版本即可。

查看容器实例是否全部启动

配置主从

  • 随便进入一个Redis容器(我们这里选择redis-node-2,其实都行),执行下面命令
    • 下面的ip需要修改成Redis所在的服务器的ip。
    • 如果需要输入内容,则输入:yes
  • –cluster-replicas 2:意味着Master和slave是以1比2的形式生成。
    • Redis集群至少需要3个Master节点,意味着每个Master对应replicas为2个slave节点。
    • 如果–cluster-replicas 1,那么就是说1个Master节点对应1个slave节点。

以集群的方式进入Redis客户端

  • 只需要多加一个-c即表示集群方式进入客户端。
  • 别忘了指定端口号。因为Redis默认是6379端口!!!!!
  • 如果搭建了Redis集群,而不使用Redis集群的方式进入客户端会怎样?
  • 上面说过,Redis集群是通过hash槽进行存储kv键值对数据的,这种情况下,当我们进入1号Redis节点进行set值,如果刚好这个set的key的hash值刚好分配到我们当前所在的1号节点,那么就可以插入成功。
  • 如果这个key的hash值分配到其他节点比如2,3号这些节点,则会插入失败。因为这个连接没有用集群的方式进入客户端。
  • 只有我们使用集群的方式进入客户端才能随意插入数据,否则只能看缘分插入!!!!!!!!

操作set命令

  • 可以看到Redis集群底层都是通过hash槽算法分区。

查看集群节点信息

查看集群状态

主从切换

  • 我们可以看到6381、6382、6383是Master节点。
  • 可以看出6381的从节点是:6389、6386
  • 把6381的容器实例给stop掉。
  • 先过一会,再次查看集群节点
代码语言:javascript
复制
192.168.184.132:6383> CLUSTER NODESc9d7f4ed642fa2fde013f2b060476b542b9af76e 192.168.184.132:6385@16385 slave af28288480e3398b18402e4475c9ae52c39ea776 0 1651767445299 3 connected9ef7a5bb156de64a969688eade8535399983dd00 192.168.184.132:6389@16389 slave 29a79c9f9a007bf80fdfc2ffaaf1cf27d29396c2 0 1651767443000 10 connected888158ad30d9a173175b115974b9d1cc5b39736e 192.168.184.132:6381@16381 master,fail - 1651767320800 1651767314000 1 disconnected1ff5a2a15526e3d7984b231cf7e47f8f442e4a9e 192.168.184.132:6382@16382 master - 0 1651767444000 2 connected 5461-1092229a79c9f9a007bf80fdfc2ffaaf1cf27d29396c2 192.168.184.132:6386@16386 master - 0 1651767444000 10 connected 0-546092d06bfb428a1358149c209c336152cae3304c66 192.168.184.132:6388@16388 slave af28288480e3398b18402e4475c9ae52c39ea776 0 1651767443000 3 connectedaf28288480e3398b18402e4475c9ae52c39ea776 192.168.184.132:6383@16383 myself,master - 0 1651767443000 3 connected 10923-163835b20d04646f7f38eb57266b81749e565825ab6e5 192.168.184.132:6387@16387 slave 1ff5a2a15526e3d7984b231cf7e47f8f442e4a9e 0 1651767444284 2 connecteda11993ddc7a726e3ad476858fb53bdc97d4834b8 192.168.184.132:6384@16384 slave 1ff5a2a15526e3d7984b231cf7e47f8f442e4a9e 0 1651767446319 2 connected

我们可以看到以前6381的从节点6386变成了Master节点。说明已经进行主从切换了。

  • 如果此时重新启动6381的容器
代码语言:javascript
复制
docker start redis-node-1
代码语言:javascript
复制
192.168.184.132:6383> CLUSTER NODES
c9d7f4ed642fa2fde013f2b060476b542b9af76e 192.168.184.132:6385@16385 slave af28288480e3398b18402e4475c9ae52c39ea776 0 1651767586000 3 connected9ef7a5bb156de64a969688eade8535399983dd00 192.168.184.132:6389@16389 slave 29a79c9f9a007bf80fdfc2ffaaf1cf27d29396c2 0 1651767586183 10 connected888158ad30d9a173175b115974b9d1cc5b39736e 192.168.184.132:6381@16381 slave 29a79c9f9a007bf80fdfc2ffaaf1cf27d29396c2 0 1651767582247 10 connected1ff5a2a15526e3d7984b231cf7e47f8f442e4a9e 192.168.184.132:6382@16382 master - 0 1651767586000 2 connected 5461-1092229a79c9f9a007bf80fdfc2ffaaf1cf27d29396c2 192.168.184.132:6386@16386 master - 0 1651767588204 10 connected 0-546092d06bfb428a1358149c209c336152cae3304c66 192.168.184.132:6388@16388 slave af28288480e3398b18402e4475c9ae52c39ea776 0 1651767586000 3 connectedaf28288480e3398b18402e4475c9ae52c39ea776 192.168.184.132:6383@16383 myself,master - 0 1651767587000 3 connected 10923-163835b20d04646f7f38eb57266b81749e565825ab6e5 192.168.184.132:6387@16387 slave 1ff5a2a15526e3d7984b231cf7e47f8f442e4a9e 0 1651767585000 2 connecteda11993ddc7a726e3ad476858fb53bdc97d4834b8 192.168.184.132:6384@16384 slave 1ff5a2a15526e3d7984b231cf7e47f8f442e4a9e 0 1651767587192 2 connected

我们可以看到6381变成了从节点(slave),主节点(Master)是6386。

主从扩容

  • 启动三个Redis容器实例,分别为6390、6391、6392
  • 目的是配置6390为Master节点加入集群,6391和6392为6390的Slave节点
  • 查看docker实例是否全部启动
  • 首先将主节点6390(Master)添加进集群中。
  • 192.168.184.132:6390:是你想要加入的Redis节点ip+端口号
  • 192.168.184.132:6383:随便一个集群中的Master节点的ip+端口(这个Master代表着整个集群,必须得是Master节点)
  • 检查一下集群

发现6390已经成功加入到集群,并且是Master节点,但是没有被分配槽位,slots为0。需要分配槽位才有用

  • 重新分配槽位,下面的6386也是Master节点,哪个Master节点都行
  • 因为我们是4个Master节点,所以是16384/4=4096,所以输入:4096
  • 再输入新加入的6390Master节点的容器id,输入:a25da2e5be0487b3109b23e807b2d4c9c23e5a1a
  • 再输入:all ,回车
  • 输入:yes
  • 检查一下集群:
  • 搞定,扩容成功。
  • 添加6390的从节点(6391和6392)
  • xxxxx1和xxxxx2替换成:6390(也就是想加入的Master节点)的id
  • 再次检查集群

主从缩容

  • 目的是移除6390(Master)和6391、6392(Slave)。
  • 删除从节点6391。xxx1替换成:6391的容器id
  • 删除从节点6392。xxx2替换成:6392的容器id
  • 删除Master节点6390之前,必须先把槽位给其他Master节点。
    • xxxxxx1:随便一个Master节点,我们这里指定6386
  • 输入删除的槽位数:因为6390的槽位是4096个,所以输入:4096
  • 再输入谁来接收这些残留下来的槽位的容器id,我们这里把4096个都给6383,所以输入6383的容器id:af28288480e3398b18402e4475c9ae52c39ea776(哪个Master节点都行)
  • 再输入删除的这个Master节点的id,也就是6390的容器id:a25da2e5be0487b3109b23e807b2d4c9c23e5a1a
  • 再输入:done
  • 再输入:yes

此时6390的槽位已经全部给了6383,这个时候可以删除6390节点了。xxx1为6390的容器id

  • 再次检查一下集群
  • 主从缩容搞定了。

来源:

https://blog.csdn.net/weixin_50071998/article/details/124751540

“IT大咖说”欢迎广大技术人员投稿,投稿邮箱:aliang@itdks.com

来都来了,走啥走,留个言呗~

 IT大咖说  |  关于版权

由“IT大咖说(ID:itdakashuo)”原创的文章,转载时请注明作者、出处及微信公众号。投稿、约稿、转载请加微信:ITDKS10(备注:投稿),茉莉小姐姐会及时与您联系!

感谢您对IT大咖说的热心支持!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT大咖说 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ◆ 什么是云原生
  • ◆ 什么是Docker
  • ◆ MySQL主从复制(1主1从)
  • ◆ Slave节点配置
  • ◆ 配置参数解析
  • ◆ Redis集群(3主6从)
  • ◆ 哈希取余算法(小厂采用)
  • ◆ 一致性hash算法(中大厂采用)
  • ◆ 快速搭建Redis Cluster(3主6从)
  • ◆ 快速生成9个容器实例
  • ◆ 查看容器实例是否全部启动
  • ◆ 配置主从
  • ◆ 以集群的方式进入Redis客户端
  • ◆ 操作set命令
  • ◆ 查看集群节点信息
  • ◆ 查看集群状态
  • ◆ 主从切换
  • ◆ 主从扩容
  • ◆ 主从缩容
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档