手把手教你用docker搭建数据库中间件DBLE+zookeeper集群

最近因为公司项目需要,所以搭建了一个DBLE+zookeeper集群的框架。在此记录一下。

 

DBLE

简单介绍一下DBLE:

业内称作Mycat Plus。是一款分布式数据库中间件,一般用于MySQL分片。在知名数据库中间Mycat的基础上进行了大量的优化和定制,修复了很多Mycat的bug,有专业的团队维护,可以提供商业服务。

官方特性一览:

官方网站:DBLE官网

 

zookeeper

zookeeper我想我不用过多介绍了,时下算是最火的一个分布式服务框架。很多中间件,比如Kafka、Hadoop、HBase,都用到了 Zookeeper。

(以下内容来自知乎柳树  https://zhuanlan.zhihu.com/p/69114539?utm_source=wechat_session

为什么需要 Zookeeper?

正经点来回答,就是我们需要一个用起来像单机但是又比单机更可靠的东西。

不正经的回答:

一个团队里面,需要一个leader,leader是干嘛用的?管理什么的咱不说,就说如果外面的人,想问关于这个团队的一切事情,首先就会去找这个leader,因为他知道的最多,而且他的回答最靠谱。

比如产品经理小饼过来要人,作为leader,老吕发现小耀最近没有项目安排,于是把小耀安排给了小饼的项目;

过了一会,另一个产品小西也过来要人,老吕发现刚刚把小耀安排走了,已经没人,于是就跟小西说,人都被你们产品要走了,你们产品自己去协调去。

如果老吕这时候忘了小耀已经被安排走了,把小耀也分配给小西,那到时两个产品就要打架了。

这就是leader在团队里的协调作用

同样的,在分布式系统中,也需要这样的协调者。

比如我们搭建了一个数据库集群,里面有一个Master,多个Slave,Master负责写,Slave只读,我们需要一个系统,来告诉客户端,哪个是Master。

有人说,很简单,我们把这个信息写到一个Java服务器的内存就好了,用一个map,key:master,value:master机器对应的ip

但是别忘了,这是个单机,一旦这个机器挂了,就完蛋了,客户端将无法知道到底哪个是Master。

于是开始进行拓展,拓展成三台服务器的集群。

这下问题来了,如果我在其中一台机器修改了Master的ip,数据还没同步到其他两台,这时候客户端过来查询,如果查询走的是另外两台还没有同步到的机器,就会拿到旧的数据,往已经不是master的机器写数据。

所以我们需要这个存储master信息的服务器集群,做到当信息还没同步完成时,不对外提供服务,阻塞住查询请求,等待信息同步完成,再给查询请求返回信息。

这样一来,请求就会变慢,变慢的时间取决于什么时候这个集群认为数据同步完成了。

假设这个数据同步时间无限短,比如是1微妙,可以忽略不计,那么其实这个分布式系统,就和我们之前单机的系统一样,既可以保证数据的一致,又让外界感知不到请求阻塞,同时,又不会有SPOF(Single Point of Failure)的风险,即不会因为一台机器的宕机,导致整个系统不可用。

这样的系统,就叫分布式协调系统。谁能把这个数据同步的时间压缩的更短,谁的请求响应就更快,谁就更出色,Zookeeper就是其中的佼佼者。

它用起来像单机一样,能够提供数据强一致性,但是其实背后是多台机器构成的集群,不会有SPOF。

其实就是CAP理论中,满足CP,不满足A的那类分布式系统。

(以上内容来自知乎柳树  https://zhuanlan.zhihu.com/p/69114539?utm_source=wechat_session

 

好了,概念说完,我们开始动手操作!说的这么牛逼,是骡子是马拉出来溜溜!

 

环境准备

一.4G内存的虚拟机(VirtualBox)

二.CentOS7系统

三.安装docker

四.拉取MySQL镜像:docker pull mysql:5.7(我用的mysql5.7版本)

五.制作DBLE镜像:

我是直接在DBLE的GitHub上面拉取的源码到本地进行制作的,这样以方便我们项目以后有需要可以进行DBLE源码的修改,然后再重新打包镜像。

DBLE源码地址:DBLE源码地址,我选的2.19.11.0版本

源码下下来后,等待下载依赖包。

依赖下载完成后,我们需要在pom.xml文件中增加:

<plugin>
   <groupId>com.spotify</groupId>
   <artifactId>docker-maven-plugin</artifactId>
   <version>1.0.0</version>
   <configuration>
       <!-- 镜像名称及版本 -->
       <imageName>${project.artifactId}:${project.version}</imageName>
       <!-- 指定Dockerfile所在的路径 -->
       <dockerDirectory>./docker-images</dockerDirectory>
       <!-- docker容器的地址 -->
       <!-- 需要打包的本地资源 -->
       <resources>
         <resource>
           <targetPath>/</targetPath>
           <directory>${project.build.directory}</directory>
           <include>${project.build.finalName}.jar</include>
         </resource>
       </resources>
   </configuration>
</plugin>

用于docker镜像打包。

然后我们先运行命令:

mvn clean package -DskipTests

将项目打包。

BUILD SUCCESS!

通过打包的信息我们可以看到生成的包在target下:

DBLE帮我们把项目打包成了几种格式,现在我们是要打包成镜像部署在服务器上运行的,所以我们选择xxx-linux.tar.gz这种压缩包的格式。我们把这个包拷贝到项目的docker-images目录下:

然后修改我们的Dockerfile文件:

FROM centos:centos7
RUN yum install -y wget java mysql

COPY dble-2.19.11.0-20200813140947-linux.tar.gz /opt
COPY quick-start/schema.xml /opt/dble/conf/
COPY quick-start/server.xml /opt/dble/conf/
COPY quick-start/rule.xml /opt/dble/conf/
COPY quick-start/wrapper.conf /opt/dble/conf/
COPY quick-start/docker_init_start.sh /opt/dble/bin/
COPY wait-for-it.sh /opt/dble/bin/

RUN tar zxvf /opt/dble-2.19.11.0-20200813140947-linux.tar.gz -C /opt && \
    chmod 777 /opt/dble/bin/* && \
    rm -f /opt/dble-2.19.11.0-20200813140947-linux.tar.gz

VOLUME /opt/dble

CMD ["/opt/dble/bin/docker_init_start.sh"]

启动我们本地的docker(切记!一定要启动docker,有时候会忘记,然后各种查找原因,很冤!),然后运行命令:

mvn clean package -DskipTests docker:build

(这里其实应该可以只运行mvn docker build -Dmaven.test.skip,但是会报找不到target目录的错,后面有时间再细研究这个问题)

感谢上帝,我们又看见了BUILD SUCCESS!图中红框的部分就是我们打包好的镜像ID。也可以通过命令docker images查看所以你打在本地的镜像。

接下来就是上传我们的镜像啦。

我一般是先把镜像传到我的阿里云镜像仓库:

sudo docker login --username=阿凯的帽子反戴 registry.cn-hangzhou.aliyuncs.com

输入密码,然后:

sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/age/agestore:[镜像版本号]

这里的镜像版本号是我们自己取的镜像名字,反正只要能标识你仓库里面的这个镜像就可以,一般都是以应用+版本名称来,类似dble1.0.1、dble1.0.2这样的。

然后上传:

sudo docker push registry.cn-hangzhou.aliyuncs.com/age/agestore:[镜像版本号]

上传完成后,我们到我的镜像仓库去看看:

可以看到我们的镜像已经上传成功了,很舒服。(原谅我的镜像名字起的比较随意,毕竟只是测试嘛)

 

部署

接下来终于进入正题啦!我们先来看一下我们的架构图:

现在我们要实现的是浅绿色虚线框中的部分架构。

开整!

首先,登陆我的虚拟机。

我们先来创建一个docker网络:

docker network create -o "com.docker.network.bridge.name"="my-net" --subnet 172.18.0.0/16 my-net

启动两个mysql容器:

docker run --name backend-mysql1 --ip 172.18.0.2 -e MYSQL_ROOT_PASSWORD=123456 -p 33061:3306 --network=my-net -d mysql:5.7 --server-id=1

docker run --name backend-mysql2 --ip 172.18.0.3 -e MYSQL_ROOT_PASSWORD=123456 -p 33062:3306 --network=my-net -d mysql:5.7 --server-id=2

然后从我的阿里云镜像仓库把我们上面创建的dble镜像拉取下来:

sudo docker login --username=阿凯的帽子反戴 registry.cn-hangzhou.aliyuncs.com
sudo docker pull registry.cn-hangzhou.aliyuncs.com/age/agestore:[镜像版本号]

拉取完成后

启动两个dble容器:

docker run -d -i -t --name dble-server01 --ip 172.18.0.4 -p 8066:8066 -p 9066:9066 --network=my-net eca6b28ad63b
docker run -d -i -t --name dble-server02 --ip 172.18.0.5 -p 8166:8066 -p 9166:9066 --network=my-net eca6b28ad63b

现在我们的虚拟机上,就跑了两个dble应用和两个mysql应用了。

然后我们先用dble连接mysql试试。

可以用命令

docker exec -it [镜像ID] /bin/bash

进入运行的容器中,在/opt/dble/conf目录下修改server.xml、schema.xml、rule.xml这三个文件(网上有一些测试的配置,这里我不再做赘述),两个dble服务使用相同配置即可。配置完成后,重启dble容器,然后用一个SQL工具测试一下:

配置成功如图所示。

这样,我们的单体dble服务就配置完成了。那么现在我们要把这两个单体dble服务统一管理起来,我们的zookeeper就登场啦!

 

先下载zookeeper镜像:

docker pull zookeeper:3.4.14

我这里用的3.4.14版本,使用3.5以上版本的小伙伴,可能到时候的配置不太一样哦,要注意。

查看一下zookeeper的镜像ID:

这里我们启动三个zookeeper容器:

docker run -d --name zookeeper01 --ip 172.18.0.6 -p 22181:2181 --network=my-net  5273b3db83ff
docker run -d --name zookeeper02 --ip 172.18.0.7 -p 22182:2181 --network=my-net  5273b3db83ff
docker run -d --name zookeeper03 --ip 172.18.0.8 -p 22183:2181 --network=my-net  5273b3db83ff

为什么是三个呢?这就和zookeeper集群的特性有关啦。

zookeeper集群中,只有当半数以上的节点都挂掉,整个集群才会挂掉。

什么是半数以上?

假如我是三个节点,挂掉一个,还有两个节点存活,半数以上,集群还能工作。再挂掉一个,那么只有一个节点存活,少于半数以上了,整个集群就挂掉了。

假如我是四个节点,挂掉一个,还有三个节点存活,半数以上,集群还能工作。再挂掉一个,只有两个节点存活,只有半数节点存活,少于半数以上了,整个集群挂掉。

小伙伴们发现什么问题?三个节点的集群,和四个节点的集群,容错率是一样的!

也就是说,我们的2n-1和2n个节点的集群拥有一样的容错率。但是可以少部署一台机器。所以zookeeper的集群,通常都是奇数个节点。

 

书归正传,三台zookeeper容器启动后,我们要配置一下,才能使它们三成为一个集群。

运行命令把容器中的zoo.cfg文件拷贝出来:

docker cp zookeeper01容器id:conf/zoo.cfg zoo.cfg

vim命令修改一下,在文件末尾增加集群配置:

server.1=zookeeper01:2881:3881
server.2=zookeeper02:2881:3881
server.3=zookeeper03:2881:3881

这里因为三个容器都注册到同一个bridge,所以可以通过容器名称进行访问。

然后将zoo.cfg文件分别复制到三个容器中:

docker cp zoo.cfg zookeeper01容器id:conf/zoo.cfg
docker cp zoo.cfg zookeeper02容器id:conf/zoo.cfg
docker cp zoo.cfg zookeeper03容器id:conf/zoo.cfg

修改完zoo.cfg后我们还要修改容器data/myid,myid这个文件中就写一个数字,分别对应上面的集群id:

将myid修改并复制到容器的data/myid:

docker cp myid(内容:1) zookeeper01容器id:data/myid
docker cp myid(内容:2) zookeeper02容器id:data/myid
docker cp myid(内容:3) zookeeper03容器id:data/myid

最后,重启我们这三台zookeeper容器。

分别进入三台容器内部验证一下集群配置生效没:

可以看到,两台follower,一台leader,集群搭建成功,舒服!

 

接下来,我们就把dble服务注册到我们的zookeeper集群上。

随便进入一个dble容器,修改/opt/dble/conf/myid.properties文件:

#
# Copyright (C) 2016-2020 ActionTech.
# License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
#

#set false if not use cluster ucore/zk
cluster=zk
#clinet info
ipAddress=172.18.0.6:2181,172.18.0.7:2181,172.18.0.8:2181
#cluster namespace, please use the same one in one cluster
clusterId=cluster-1
#it must be different for every node in cluster
myid=server_01

这里要注意,myid这个配置,两个dble服务一定要不一样。我这里一个设为server_01,一个设为server_02,其他的配置一样的即可。

配置完成后,重启两个dble容器。

启动完成后可以进入容器中/opt/dble/logs/wrapper.log中查看启动日志,看是否有报错,如下则表示成功启动:

然后我们再到zookeeper容器中看下服务有没有成功注册上去。

随便进入一个zookeeper容器:

在/bin路径下,执行zkCli.sh:

可以看到,我们的dble服务已经注册上去啦!

我们再用我们的SQL工具连接dble试试:

可以连接,舒服!

现在我们来把zookeeper集群里面的zookeeper01这个节点挂了,会怎么样?

我们来试试:

暴脾气!说停就停!

我们再来看看zookeeper02和zookeeper03中的服务注册,是否要有dble的两个容器:

可以看到我们的zookeeper02和zookeeper03节点上依然注册着dble的两个服务。

然后我们在通过SQL工具测试一下:

两个dble服务依然能正常提供服务。说明我们的zookeeper集群依然能正常提供服务,舒服!

由于我这里只启动了两个dble服务(虚拟机内存所限,一个字:穷),所以没有办法演示当dble集群中有节点挂掉时,另外的节点依然能作为一个集群对外暴露服务。什么意思呢?

假如我的dble集群有三个节点A、B、C,我们的节点A停掉,然后在节点B中上对数据库中的任意一张表的结构进行修改,然后通过节点C查看这张表结构,发现查看到的是修改后的表结构。

所以,DBLE 集群中,当其他节点掉线或故障时,不影响其他节点提供服务。有兴趣的同学可以自己尝试一下~

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Docker Swarm和Docker Compose来创建Zookeeper集群。以下是一个简单的步骤: 1. 创建一个Docker Compose文件,用于定义Zookeeper集群中的服务和配置。例如,可以创建一个名为docker-compose.yml的文件,其中包含以下内容: ``` version: '3' services: zoo1: image: zookeeper restart: always hostname: zoo1 environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 ports: - "2181:2181" - "2888:2888" - "3888:3888" volumes: - ./data/zoo1:/data - ./logs/zoo1:/datalog zoo2: image: zookeeper restart: always hostname: zoo2 environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 ports: - "2182:2181" - "2889:2888" - "3889:3888" volumes: - ./data/zoo2:/data - ./logs/zoo2:/datalog zoo3: image: zookeeper restart: always hostname: zoo3 environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 ports: - "2183:2181" - "2890:2888" - "3890:3888" volumes: - ./data/zoo3:/data - ./logs/zoo3:/datalog ``` 该文件定义了三个Zookeeper实例(zoo1、zoo2和zoo3),每个实例都有自己的ID和端口映射。 2. 使用Docker Swarm启动Zookeeper集群。首先,需要初始化Swarm: ``` docker swarm init ``` 然后,使用以下命令在Swarm中部署Zookeeper集群: ``` docker stack deploy -c docker-compose.yml zookeeper ``` 这将在Swarm中启动三个Zookeeper实例,并配置它们以形成一个集群。 3. 验证集群是否正常工作。可以使用以下命令查看Zookeeper集群的状态: ``` docker exec -it $(docker ps -q -f name=zookeeper_zoo1) /bin/bash zkServer.sh status ``` 该命令将连接到Zookeeper集群中的一个实例(这里是zoo1),并显示集群的状态信息。 这样就可以使用Docker Swarm和Docker Compose创建一个Zookeeper集群。需要注意的是,这仅是一个简单的示例,实际部署可能需要进行更多的配置和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值