通过docker-compose搭建mongo的replica set高可用

前言

搭建一个mongo的集群,同时原来单机mongo的数据需要迁移到集群中。

处理思路:单机mongo的数据通过mongodump备份,然后集群搭建起来了,在mongorestore导入到集群中,实现数据的迁移。

备份数据

备份(mongodump)与恢复(mongorestore)

备份数据到本地

mongodump -h 192.168.56.201:37018 -u handle -p jimeng2017 -o /home/liz/Desktop/mongo-bei

数据恢复

新的集群安装完成之后,恢复数据到Primary节点,集群会自动同步到副本集中

mongorestore -h 192.168.56.201:37017 -u handle -p jimeng2017  /home/liz/Desktop/mongo-bei

注意:更换自己服务器上面的ip和mongo对应的账号密码

集群搭建

生成keyFile

  • MongoDB使用keyfile认证,副本集中的每个mongod实例使用keyfile内容作为认证其他成员的共享密码。mongod实例只有拥有正确的keyfile才可以加入副本集。
  • keyFile的内容必须是6到1024个字符的长度,且副本集所有成员的keyFile内容必须相同。
  • 有一点要注意是的:在UNIX系统中,keyFile必须没有组权限或完全权限(也就是权限要设置成X00的形式)。Windows系统中,keyFile权限没有被检查。
  • 可以使用任意方法生成keyFile。例如,如下操作使用openssl生成复杂的随机的1024个字符串。然后使用chmod修改文件权限,只给文件拥有者提供读权限。
# 400权限是要保证安全性,否则mongod启动会报错
openssl rand -base64 756 > mongodb.key
chmod 400 mongodb.key

每一个副本集成员都要使用相同的keyFile文件

创建yml文件

配置文件:

version: '3.3'

services:
mongodb1:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo1:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb1
ports:
- 37017:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@ mongodb2:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo2:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb2
ports:
- 37018:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@ mongodb3:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo3:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb3
ports:
- 37019:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@

文件详解

chown 999:999 /data/mongodb.key 999用户是容器中的mongod用户,通过chown修改文件用户权限

mongod --replSet mongos --keyFile /data/mongodb.key 启动命令,--replSet mongos 以副本集形式启动并将副本集名字命名为 mongos ,--keyFile /data/mongodb.key 设置keyFile,用于副本集通信,文件通过 volumes 映射到容器内

然后启动

docker-compose -f  docker-compose-set.yml up -d

初始化副本集

然后进去到第一个容器里面,初始化副本集

docker exec -it mongodb1 /bin/bash

登录

mongo -u 账号 -p 密码

登录成功可以查看状态

> rs.status()
{
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94,
"codeName" : "NotYetInitialized"
}

配置副本集

> rs.initiate({
... ... _id: "mongos",
... ... members: [
... ... { _id : 0, host : "192.168.56.201:37017" },
... ... { _id : 1, host : "192.168.56.201:37018" },
... ... { _id : 2, host : "192.168.56.201:37019" }
... ... ]
... ... });
{ "ok" : 1 }

上面提示ok就是表示成功了,这时候会选举出Primary节点。重新通过rs.status()查看状态就能看到了。

rs.status()
{
"set" : "mongos",
"date" : ISODate("2020-07-04T13:02:44.676Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2020-07-04T13:02:40.809Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"readConcernMajorityWallTime" : ISODate("2020-07-04T13:02:40.809Z"),
"appliedOpTime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2020-07-04T13:02:40.809Z"),
"lastDurableWallTime" : ISODate("2020-07-04T13:02:40.809Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1593867720, 5),
"lastStableCheckpointTimestamp" : Timestamp(1593867720, 5),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2020-07-04T13:02:00.300Z"),
"termAtElection" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1593867709, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(-29631936),
"newTermStartDate" : ISODate("2020-07-04T13:02:00.787Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2020-07-04T13:02:01.528Z")
},
"members" : [
{
"_id" : 0,
"name" : "192.168.56.201:37017",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 155,
"optime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-07-04T13:02:40Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1593867720, 1),
"electionDate" : ISODate("2020-07-04T13:02:00Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "192.168.56.201:37018",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 54,
"optime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-07-04T13:02:40Z"),
"optimeDurableDate" : ISODate("2020-07-04T13:02:40Z"),
"lastHeartbeat" : ISODate("2020-07-04T13:02:44.402Z"),
"lastHeartbeatRecv" : ISODate("2020-07-04T13:02:43.511Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.56.201:37017",
"syncSourceHost" : "192.168.56.201:37017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.56.201:37019",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 54,
"optime" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1593867760, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-07-04T13:02:40Z"),
"optimeDurableDate" : ISODate("2020-07-04T13:02:40Z"),
"lastHeartbeat" : ISODate("2020-07-04T13:02:44.402Z"),
"lastHeartbeatRecv" : ISODate("2020-07-04T13:02:43.533Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.56.201:37017",
"syncSourceHost" : "192.168.56.201:37017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1593867760, 1),
"signature" : {
"hash" : BinData(0,"Zr91geLBqJM7xN3vVVMWnJYAexk="),
"keyId" : NumberLong("6845609731550085123")
}
},
"operationTime" : Timestamp(1593867760, 1)
}

通过rs.status()的输出我们就能分出那个是PRIMARY节点了。

增加副本集

之前已经初始化了三个mongo,我们在原来的基础上再增加一个副本集。

首先编写docker-compose-set.yml增加mongodb4

mongodb4:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo4:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb4
ports:
- 37020:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@

启动

docker-compose -f  docker-compose-set.yml up -d

然后进入到PRIMARY,执行

> rs.add("192.168.56.201:37020")
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1593868399, 1),
"signature" : {
"hash" : BinData(0,"BZJ2tCwFE1NvE22/LwGzFTWy+1M="),
"keyId" : NumberLong("6845609731550085123")
}
},
"operationTime" : Timestamp(1593868399, 1)
}

再次查看

> rs.status()
{
"set" : "mongos",
"date" : ISODate("2020-07-04T13:13:27.944Z"),
"myState" : 1,
"term" : NumberLong(3),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 3,
"writeMajorityCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"lastCommittedWallTime" : ISODate("2020-07-04T13:13:19.243Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"readConcernMajorityWallTime" : ISODate("2020-07-04T13:13:19.243Z"),
"appliedOpTime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"durableOpTime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"lastAppliedWallTime" : ISODate("2020-07-04T13:13:19.243Z"),
"lastDurableWallTime" : ISODate("2020-07-04T13:13:19.243Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1593868366, 1),
"lastStableCheckpointTimestamp" : Timestamp(1593868366, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2020-07-04T13:06:06.408Z"),
"termAtElection" : NumberLong(3),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1593867860, 1),
"t" : NumberLong(1)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(37018),
"newTermStartDate" : ISODate("2020-07-04T13:06:06.753Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2020-07-04T13:06:07.255Z")
},
"members" : [
{
"_id" : 0,
"name" : "192.168.56.201:37017",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 452,
"optime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-07-04T13:13:19Z"),
"optimeDurableDate" : ISODate("2020-07-04T13:13:19Z"),
"lastHeartbeat" : ISODate("2020-07-04T13:13:27.642Z"),
"lastHeartbeatRecv" : ISODate("2020-07-04T13:13:27.493Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 2
},
{
"_id" : 1,
"name" : "192.168.56.201:37018",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 452,
"optime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-07-04T13:13:19Z"),
"optimeDurableDate" : ISODate("2020-07-04T13:13:19Z"),
"lastHeartbeat" : ISODate("2020-07-04T13:13:27.622Z"),
"lastHeartbeatRecv" : ISODate("2020-07-04T13:13:27.493Z"),
"pingMs" : NumberLong(13),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 2
},
{
"_id" : 2,
"name" : "192.168.56.201:37019",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 454,
"optime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-07-04T13:13:19Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1593867966, 1),
"electionDate" : ISODate("2020-07-04T13:06:06Z"),
"configVersion" : 2,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 3,
"name" : "192.168.56.201:37020",
"ip" : "192.168.56.201",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 8,
"optime" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1593868399, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-07-04T13:13:19Z"),
"optimeDurableDate" : ISODate("2020-07-04T13:13:19Z"),
"lastHeartbeat" : ISODate("2020-07-04T13:13:27.418Z"),
"lastHeartbeatRecv" : ISODate("2020-07-04T13:13:27.823Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 2
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1593868399, 1),
"signature" : {
"hash" : BinData(0,"BZJ2tCwFE1NvE22/LwGzFTWy+1M="),
"keyId" : NumberLong("6845609731550085123")
}
},
"operationTime" : Timestamp(1593868399, 1)
}

可以看到最新的节点已经加进去了

将节点初始化也放到yml中

如果熟练了,我们可以将副本集的初始化也放到yml中完成

version: '3.3'

services:
mongodb1:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo1:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb1
ports:
- 37017:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@ mongodb2:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo2:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb2
ports:
- 37018:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@ mongodb3:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo3:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb3
ports:
- 37019:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@ mongodb4:
image: mongo:4.2.1
volumes:
- /data/mongo/data/mongo4:/data/db
- ./mongodb.key:/data/mongodb.key
user: root
environment:
- MONGO_INITDB_ROOT_USERNAME=handle
- MONGO_INITDB_ROOT_PASSWORD=jimeng2017
- MONGO_INITDB_DATABASE=handle
container_name: mongodb4
ports:
- 37020:27017
command: mongod --replSet mongos --keyFile /data/mongodb.key
restart: always
entrypoint:
- bash
- -c
- |
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@ mongodb-init:
image: mongo:4.2.1
depends_on:
- mongodb1
- mongodb2
- mongodb3
- mongodb4
restart: on-failure:5
command:
- mongo
- mongodb://handle:jimeng2017@192.168.56.201:37017/admin
- --eval
- 'rs.initiate({ _id: "mongos", members: [{_id:1,host:"192.168.56.201:37017"},{_id:2,host:"192.168.56.201:37018"},{_id:3,host:"192.168.56.201:37019"},{_id:4,host:"192.168.56.201:37020"}]})'

这样通过docker-compose up -d就能完成镜像的构建和副本集的初始化

了解下Replica set

Replica set,由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,通过这样的方式来保持复制集内所有成员存储相同的数据集,提供数据的高可用。

优点:

  • 确保数据安全
  • 高(24 * 7)数据可用性
  • 灾难恢复
  • 无需停机维护(例如备份,索引重建,压缩)
  • 读取缩放(要读取的额外副本)
  • 副本集对应用程序是透明的

复制在MongoDB中的工作方式

  • MongoDB通过使用副本集来实现复制。 副本集是一组托管相同数据集的mongod实例。 在副本中,一个节点是接收所有写操作的主节点。 所有其他实例,例如第二实例,都将应用来自第一实例的操作,以便它们具有相同的数据集。 副本集只能有一个主节点。
  • 副本集是一组两个或更多节点(通常至少需要3个节点)。
  • 在副本集中,一个节点是主要节点,其余节点是次要节点。
  • 所有数据从主节点复制到辅助节点。
  • 在自动故障转移或维护时,将为主节点建立选举,并选举一个新的主节点。
  • 恢复失败的节点后,它再次加入副本集并用作辅助节点。

下面就是工作的流程图

测试连接

使用go测试下是否能正常连接和读写数据。

show dbs;:查看数据库

> show dbs
admin 0.000GB
bs-cx 0.000GB
config 0.000GB
handle 0.001GB
handle-core4 0.019GB
local 0.020GB
stud 0.000GB

use stud;:切换到指定数据库,如果不存在该数据库就创建。

> use stud
switched to db stud

db;:显示当前所在数据库。

> db
stud

db.dropDatabase():删除当前数据库

> db.dropDatabase();
{ "ok" : 1 }

测试写入数据,使用的包https://github.com/mongodb/mongo-go-driver

package main

import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
) type Student struct {
Name string
Age int
} func main() {
uri := "mongodb://handle:jimeng2017@192.168.56.201:37017,192.168.56.201:37018,192.168.56.201:37019,192.168.56.201:37020/admin?replicaSet=mongos"
// 设置客户端连接配置
clientOptions := options.Client().ApplyURI(uri) // 连接到MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
} // 检查连接
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB!")
collection := client.Database("stud").Collection("student") s1 := Student{"小红", 12}
insertResult, err := collection.InsertOne(context.TODO(), s1)
if err != nil {
log.Fatal(err)
}
fmt.Println("Inserted a single document: ", insertResult.InsertedID) var result Student
filter := bson.D{{"name", "小红"}} err = collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found a single document: %+v\n", result) // 断开连接
err = client.Disconnect(context.TODO())
if err != nil {
log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")
}

打印下输出

Connected to MongoDB!
Inserted a single document: ObjectID("5f00b6092aef651857151754")
Found a single document: {Name:小红 Age:12}
Connection to MongoDB closed.

成功连接上了

通过docker-compose搭建mongo的replica set高可用的更多相关文章

  1. Docker Compose 搭建 Redis Cluster 集群环境

    在前文<Docker 搭建 Redis Cluster 集群环境>中我已经教过大家如何搭建了,本文使用 Docker Compose 再带大家搭建一遍,其目的主要是为了让大家感受 Dock ...

  2. Istio入门实战与架构原理——使用Docker Compose搭建Service Mesh

    本文将介绍如何使用Docker Compose搭建Istio.Istio号称支持多种平台(不仅仅Kubernetes).然而,官网上非基于Kubernetes的教程仿佛不是亲儿子,写得非常随便,不仅缺 ...

  3. 利用 Docker Compose 搭建 SpringBoot 运行环境(超详细步骤和分析)

    0.前言 相信点进来看这篇文章的同学们已经对 Docker Dompose 有一定的了解了,下面,我们拿最简单的例子来介绍如何使用 Docker Compose 来管理项目. 本文例子: 一个应用服务 ...

  4. 使用Docker Compose搭建Service Mesh

    使用Docker Compose搭建Service Mesh 本文将介绍如何使用Docker Compose搭建Istio.Istio号称支持多种平台(不仅仅Kubernetes).然而,官网上非基于 ...

  5. 搭建 Keepalived + Nginx + Tomcat 的高可用负载均衡架构

    1 概述 初期的互联网企业由于业务量较小,所以一般单机部署,实现单点访问即可满足业务的需求,这也是最简单的部署方式,但是随着业务的不断扩大,系统的访问量逐渐的上升,单机部署的模式已无法承载现有的业务量 ...

  6. 搭建Keepalived + Nginx + Tomcat的高可用负载均衡架构

    1 概述 初期的互联网企业由于业务量较小,所以一般单机部署,实现单点访问即可满足业务的需求,这也是最简单的部署方式,但是随着业务的不断扩大,系统的访问量逐渐的上升,单机部署的模式已无法承载现有的业务量 ...

  7. (七) Docker 部署 MySql8.0 一主一从 高可用集群

    参考并感谢 官方文档 https://hub.docker.com/_/mysql y0ngb1n https://www.jianshu.com/p/0439206e1f28 vito0319 ht ...

  8. Docker Compose搭建Redis一主二从三哨兵高可用集群

    一.Docker Compose介绍 https://docs.docker.com/compose/ Docker官方的网站是这样介绍Docker Compose的: Compose是用于定义和运行 ...

  9. docker compose搭建redis7.0.4高可用一主二从三哨兵集群并整合SpringBoot【图文完整版】

    一.前言 redis在我们企业级开发中是很常见的,但是单个redis不能保证我们的稳定使用,所以我们要建立一个集群. redis有两种高可用的方案: High availability with Re ...

  10. Docker Compose搭建ELK

    Elasticsearch默认使用mmapfs目录来存储索引.操作系统默认的mmap计数太低可能导致内存不足,我们可以使用下面这条命令来增加内存: sysctl -w vm.max_map_count ...

随机推荐

  1. Axure 鼠标和键盘交互

  2. SpringBoot Admin OFFLINE

    java.util.concurrent.TimeoutException message Did not observe any item or terminal signal within 100 ...

  3. Mac下Homebrew替换镜像

    替换git和homebrew镜像源 一.git加速 查找域名对应的地址 nslookup github.com nslookup github.global.ssl.fastly.Net 修改host ...

  4. ORM之Sequelize

    一.环境: Vue.Quasar.Electron.Postgres.Sequelize.sequelize-auto 二.安装 (1)添加Sequelize(全局安装) $npm install - ...

  5. 原创内容屡屡被盗?从源头对资源盗用说NO

    在这个信息化的时代,资源被盗用是一件很让人厌恶,但又很常见的事.比如,之前郭敬明的小说<梦里花落知多少>剽窃庄羽小说<圈里圈外>一事,虽然郭敬明通过个人微博向庄羽道歉,并表示& ...

  6. AliAGC 自动增益控制算法:解决复杂场景下的音量问题

    音视频会议,直播连麦以及短视频已经成为人们工作.教学以及娱乐的一部分,其背后都离不开音视频实时通信等关键技术的广泛应用.音频方面,可预见的是客户业务形式的多样性,环境的复杂性,以及接入设备的差异性会带 ...

  7. Codeforece : 1360C. Similar Pairs(水题)

    https://codeforces.com/contest/1360/problem/C We call two numbers xx and yy similar if they have the ...

  8. 自主创新国产化科技:智能制造之 SMT 产线监控管理可视化

    SMT(Surface Mounted Technology,表面贴片技术)指的是在印刷电路板 (Printed Circuit Board,PCB)基础上进行加工的系列工艺流程的简称,是电子组装行业 ...

  9. python之单线程、多线程、多进程

    一.基本概念 进程(Process) 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 在当代面向线程设计的计算机结构中,进程是线程的容器.程 ...

  10. 小白学标准库之 log

    日常开发中,日志 log 几乎是必不可少.本文旨在介绍 log 的使用和内部实现等. 1. log 使用及实现 package main import ( "fmt" " ...