1.部署3节点mongodb复制集。
1、编辑mongodb节点rocky(10.0.0.160)、rocky1(10.0.0.170)、rocky2(10.0.0.180)的安装脚本。
bash
vim install_mongodb.sh
#!/bin/bash
# 正确定义版本变量
MONGODB_VERSION=rhel80-5.0.4
MONGODB_FILE=mongodb-linux-x86_64-${MONGODB_VERSION}.tgz
URL=https://fastdl.mongodb.org/linux/$MONGODB_FILE
MONGODB_DIR=/mongodb
INSTALL_DIR=/usr/local
PORT=27017
MY_IP=`hostname -I|awk '{print $1}'`
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
system_prepare () {
[ -e $MONGODB_DIR -o -e $INSTALL_DIR/mongodb ] && { color "MongoDB 数据库已安装!" 1;exit; }
# 安装依赖
if [ $ID = "centos" -o $ID = "rocky" ];then
rpm -q curl &> /dev/null || yum install -y -q curl
elif [ $ID = "ubuntu" ];then
dpkg -l curl &> /dev/null || apt -y install curl
else
color '不支持当前操作系统!' 1
# 透明大页配置
exit
fi
if [ -e /etc/rc.local ];then
echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.local
else
cat > /etc/rc.local <<EOF
#!/bin/bash
echo never > /sys/kernel/mm/transparent_hugepage/enabled
EOF
fi
chmod +x /etc/rc.local
}
mongodb_file_prepare () {
if [ ! -e $MONGODB_FILE ];then
curl -O $URL || { color "MongoDB 数据库文件下载失败" 1; exit; }
fi
}
install_mongodb () {
id mongod &> /dev/null || useradd -m -s /bin/bash mongod
tar xf $MONGODB_FILE -C $INSTALL_DIR
ln -s $INSTALL_DIR/mongodb-linux-x86_64-${MONGODB_VERSION} $INSTALL_DIR/mongodb
#mongod --dbpath $db_dir --bind_ip_all --port $PORT --logpath $db_dir/mongod.log --fork
}
config_mongodb(){
# 环境变量
echo PATH=$INSTALL_DIR/mongodb/bin/:'$PATH' > /etc/profile.d/mongodb.sh
. /etc/profile.d/mongodb.sh
# 创建目录
mkdir -p $MONGODB_DIR/{conf,data,log}
# 配置文件
cat > $MONGODB_DIR/conf/mongo.conf <<EOF
systemLog:
destination: file
path: "$MONGODB_DIR/log/mongodb.log"
logAppend: true
storage:
dbPath: "$MONGODB_DIR/data/"
journal:
enabled: true
processManagement:
fork: true
net:
port: 27017
bindIp: 0.0.0.0
EOF
chown -R mongod.mongod $MONGODB_DIR/
cat > /lib/systemd/system/mongod.service <<EOF
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
User=mongod
Group=mongod
ExecStart=$INSTALL_DIR/mongodb/bin/mongod --config $MONGODB_DIR/conf/mongo.conf
ExecReload=/bin/kill -s HUP \$MAINPID
ExecStop=$INSTALL_DIR/bin/mongod --config $MONGODB_DIR/conf/mongo.conf --shutdown
PrivateTmp=true
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now mongod &>/dev/null
}
start_mongodb() {
systemctl is-active mongod.service &>/dev/null
if [ $? -eq 0 ];then
echo
color "MongoDB 安装完成!" 0
else
color "MongoDB 安装失败!" 1
exit
fi
}
# 执行流程
system_prepare
mongodb_file_prepare
install_mongodb
config_mongodb
start_mongodb
2、配置rocky0(10.0.0.160)、rocky1(10.0.0.170)、rocky2(10.0.0.180)构成的3节点mongodb复制集。
bash
# 以 root 用户身份在 rocky 主机上执行 install_mongodb.sh 脚本进行 MongoDB 的安装
# 记得禁用防火墙
[root@rocky0 ~]setenforce 0
[root@rocky0 ~]sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@rocky0 ~] bash install_mongodb.sh
# 创建 mongo 命令的软链接,方便在任何位置使用 mongo 命令
[root@rocky0 ~]ln -s /usr/local/mongodb/bin/mongo /usr/bin/
# 使用 vim 编辑器打开 MongoDB 的配置文件进行编辑
[root@rocky0 ~]vim /mongodb/conf/mongo.conf
# 在配置文件中添加复制集的名称为 myrepl
replication:
replSetName: myrepl
# 重启 MongoDB 服务使配置生效
[root@rocky0 ~]systemctl restart mongod.service
# 以 root 用户身份在 rocky1 主机上执行 install_mongodb.sh 脚本进行 MongoDB 的安装
[root@rocky1 ~] bash install_mongodb.sh
# 创建 mongo 命令的软链接,方便在任何位置使用 mongo 命令
[root@rocky1 ~]ln -s /usr/local/mongodb/bin/mongo /usr/bin/
# 使用 vim 编辑器打开 MongoDB 的配置文件进行编辑
[root@rocky1 ~]vim /mongodb/conf/mongo.conf
# 在配置文件中添加复制集的名称为 myrepl
replication:
replSetName: myrepl
# 重启 MongoDB 服务使配置生效
[root@rocky1 ~]systemctl restart mongod.service
# 以 root 用户身份在 rocky2 主机上执行 install_mongodb.sh 脚本进行 MongoDB 的安装
[root@rocky2 ~] bash install_mongodb.sh
# 创建 mongo 命令的软链接,方便在任何位置使用 mongo 命令
[root@rocky2 ~]ln -s /usr/local/mongodb/bin/mongo /usr/bin/
# 使用 vim 编辑器打开 MongoDB 的配置文件进行编辑
[root@rocky2 ~]vim /mongodb/conf/mongo.conf
# 在配置文件中添加复制集的名称为 myrepl
replication:
replSetName: myrepl
# 重启 MongoDB 服务使配置生效
[root@rocky2 ~]systemctl restart mongod.service
# 以 root 用户身份在 rocky 主机上使用 mongo 命令进入 MongoDB 的 shell
[root@rocky0 ~] mongo
> config = { _id: 'myrepl', members: [
{_id: 0, host: '10.0.0.160:27017'},
{_id: 1, host: '10.0.0.170:27017'},
{_id: 2, host: '10.0.0.180:27017'}]
}
{
"_id" : "myrepl",
"members" : [
{
"_id" : 0,
"host" : "10.0.0.160:27017"
},
{
"_id" : 1,
"host" : "10.0.0.170:27017"
},
{
"_id" : 2,
"host" : "10.0.0.180:27017"
}
]
}
> rs.initiate(config)
{ "ok" : 1 }
myrepl:SECONDARY>
myrepl:PRIMARY>
myrepl:PRIMARY> rs.status();
{
"set" : "myrepl",
"date" : ISODate("2025-03-08T11:49:30.857Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"votingMembersCount" : 3,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2025-03-08T11:49:22.588Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2025-03-08T11:49:22.588Z"),
"lastDurableWallTime" : ISODate("2025-03-08T11:49:22.588Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1741434520, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2025-03-08T11:48:52.329Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(1741434520, 1),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1741434520, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2025-03-08T11:48:52.581Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2025-03-08T11:48:53.611Z")
},
"members" : [
{
"_id" : 0,
"name" : "10.0.0.160:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 7884,
"optime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2025-03-08T11:49:22Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1741434532, 1),
"electionDate" : ISODate("2025-03-08T11:48:52Z"),
"configVersion" : 1,
"configTerm" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "10.0.0.170:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 49,
"optime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2025-03-08T11:49:22Z"),
"optimeDurableDate" : ISODate("2025-03-08T11:49:22Z"),
"lastHeartbeat" : ISODate("2025-03-08T11:49:30.573Z"),
"lastHeartbeatRecv" : ISODate("2025-03-08T11:49:30.088Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "10.0.0.160:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
},
{
"_id" : 2,
"name" : "10.0.0.180:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 49,
"optime" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1741434562, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2025-03-08T11:49:22Z"),
"optimeDurableDate" : ISODate("2025-03-08T11:49:22Z"),
"lastHeartbeat" : ISODate("2025-03-08T11:49:30.573Z"),
"lastHeartbeatRecv" : ISODate("2025-03-08T11:49:30.086Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "10.0.0.160:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1741434562, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1741434562, 1)
}
2.部署3节点Kafka集群
1、编辑Kafka节点NODE1(10.0.0.100)、NODE2(10.0.0.110)、NODE3(10.0.0.120)的安装脚本。
bash
#!/bin/bash
NODE1=10.0.0.100
NODE2=10.0.0.110
NODE3=10.0.0.120
KAFKA_VERSION=3.9.0
SCALA_VERSION=2.13
KAFKA_URL="https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/${KAFKA_VERSION}/kafka_${SCALA_VERSION}-${KAFKA_VERSION}.tgz"
KAFKA_INSTALL_DIR=/usr/local/kafka
HOST=`hostname -I|awk '{print $1}'`
. /etc/os-release
# 定义color函数,用于输出彩色文本
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
# 定义env函数,用于设置环境变量和/etc/hosts文件
env () {
if hostname -I |grep -q $NODE1;then
ID=1
hostnamectl set-hostname node1
elif hostname -I |grep -q $NODE2;then
ID=2
hostnamectl set-hostname node2
elif hostname -I |grep -q $NODE3;then
ID=3
hostnamectl set-hostname node3
else
color 'IP地址错误' 1
exit
fi
cat >> /etc/hosts <<EOF
$NODE1 node1
$NODE2 node2
$NODE3 node3
EOF
}
# 定义install_jdk函数,用于安装JDK
install_jdk() {
java -version &>/dev/null && { color "JDK 已安装!" 1 ; return; }
if command -v yum &>/dev/null ; then
yum -y install java-1.8.0-openjdk-devel || { color "安装JDK失败!" 1; exit 1; }
elif command -v apt &>/dev/null ; then
apt update
#apt install openjdk-11-jdk -y || { color "安装JDK失败!" 1; exit 1; }
apt install openjdk-8-jdk -y || { color "安装JDK失败!" 1; exit 1; }
else
color "不支持当前操作系统!" 1
exit 1
fi
java -version && { color "安装 JDK 完成!" 0 ; } || { color "安装JDK失败!" 1; exit 1; }
}
# 定义install_zookeeper函数,用于安装和配置Zookeeper
install_zookeeper() {
mv ${KAFKA_INSTALL_DIR}/config/zookeeper.properties{,.bak}
cat > ${KAFKA_INSTALL_DIR}/config/zookeeper.properties <<EOF
tickTime=2000
initLimit=10
syncLimit=5
dataDir=${KAFKA_INSTALL_DIR}/data
clientPort=2181
maxClientCnxns=128
autopurge.snapRetainCount=3
autopurge.purgeInterval=24
server.1=${NODE1}:2888:3888
server.2=${NODE2}:2888:3888
server.3=${NODE3}:2888:3888
EOF
mkdir -p ${KAFKA_INSTALL_DIR}/data
echo $ID > ${KAFKA_INSTALL_DIR}/data/myid
cat > ${KAFKA_INSTALL_DIR}/bin/zookeeper-startup.sh <<EOF
#!/bin/bash
nohup ${KAFKA_INSTALL_DIR}/bin/zookeeper-server-start.sh ${KAFKA_INSTALL_DIR}/config/zookeeper.properties &
EOF
chmod +x ${KAFKA_INSTALL_DIR}/bin/zookeeper-startup.sh
cat > /lib/systemd/system/zookeeper.service <<EOF
[Unit]
Description=zookeeper.service
After=network.target
[Service]
Type=forking
ExecStart=${KAFKA_INSTALL_DIR}/bin/zookeeper-startup.sh
ExecStop=${KAFKA_INSTALL_DIR}/bin/zookeeper-server-stop.sh
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now zookeeper.service
systemctl is-active zookeeper.service
if [ $? -eq 0 ] ;then
color "zookeeper 安装成功!" 0
else
color "zookeeper 安装失败!" 1
exit 1
fi
}
install_kafka(){
# 检查是否已经下载了指定版本的Kafka安装包,如果没有则下载
if [ ! -f /usr/local/src/kafka_${SCALA_VERSION}-${KAFKA_VERSION}.tgz ];then
wget -P /usr/local/src/ --no-check-certificate $KAFKA_URL || { color "下载失败!" 1 ;exit ; }
fi
tar xf /usr/local/src/${KAFKA_URL##*/} -C /usr/local/
ln -s /usr/local/kafka_${SCALA_VERSION}-${KAFKA_VERSION} ${KAFKA_INSTALL_DIR}
install_zookeeper
echo PATH=${KAFKA_INSTALL_DIR}/bin:'$PATH' >> /etc/profile
# 备份原始的server.properties配置文件,创建新的server.properties配置文件,并写入配置内容
mv ${KAFKA_INSTALL_DIR}/config/server.properties{,.bak}
cat > ${KAFKA_INSTALL_DIR}/config/server.properties <<EOF
broker.id=$ID
listeners=PLAINTEXT://${HOST}:9092
log.dirs=${KAFKA_INSTALL_DIR}/data
num.partitions=1
log.retention.hours=168
zookeeper.connect=${NODE1}:2181,${NODE2}:2181,${NODE3}:2181
zookeeper.connection.timeout.ms=6000
delete.topic.enable=true
EOF
# 创建Kafka启动脚本
cat > ${KAFKA_INSTALL_DIR}/bin/kafka-startup.sh <<EOF
#!/bin/bash
nohup ${KAFKA_INSTALL_DIR}/bin/kafka-server-start.sh ${KAFKA_INSTALL_DIR}/config/server.properties &
EOF
chmod +x ${KAFKA_INSTALL_DIR}/bin/kafka-startup.sh
# 创建systemd服务文件,用于管理Kafka服务
cat > /lib/systemd/system/kafka.service <<EOF
[Unit]
Description=Apache kafka
After=network.target
[Service]
Type=forking
ExecStart=${KAFKA_INSTALL_DIR}/bin/kafka-startup.sh
ExecStop=/bin/kill -TERM \${MAINPID}
Restart=always
RestartSec=20
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kafka.service
#kafka-server-start.sh -daemon ${KAFKA_INSTALL_DIR}/config/server.properties # 注释代码,原意是直接启动Kafka服务,已被systemctl管理取代
systemctl is-active kafka.service
if [ $? -eq 0 ] ;then
color "kafka 安装成功!" 0
else
color "kafka 安装失败!" 1
exit 1
fi
}
# 打印当前环境变量(此处可能是为了调试或查看环境变量设置)
env
# 调用安装JDK的函数(假设已在脚本中定义)
install_jdk
# 调用安装Kafka的函数
install_kafka
2、配置node1(10.0.0.100)、node2(10.0.0.110)、node3(10.0.0.120)构成的3节点kafka集群,并测试。
bash
# 在node1上配置Kafka
[root@node1 ~]# vim /usr/local/kafka/config/server.properties
# 编辑Kafka的配置文件,设置broker.id为1,这是集群中每个Kafka节点的唯一标识符
broker.id=1
# 启动Kafka服务
[root@node1 ~]# /usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties
# 使用Kafka自带的启动脚本和配置文件启动Kafka服务
# 在node2上配置Kafka
[root@node2 ~]# vim /usr/local/kafka/config/server.properties
# 同样编辑Kafka的配置文件,但这次设置broker.id为2,以区分node1
broker.id=2
# 启动Kafka服务
[root@node2 ~]# /usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties
# 使用相同的启动脚本和配置文件在node2上启动Kafka服务
# 在node3上配置Kafka
[root@node3 ~] vim /usr/local/kafka/config/server.properties
# 设置broker.id为3,以区分node1和node2
broker.id=3
# 启动Kafka服务
[root@node3 ~]# /usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties
# 使用相同的启动脚本和配置文件在node3上启动Kafka服务
# 在node1上创建一个名为zhangyao的主题
[root@node1 ~]# /usr/local/kafka/bin/kafka-topics.sh --create --topic zhangyao --bootstrap-server 10.0.0.100:9092,10.0.0.110:9092,10.0.0.120:9092
# 使用Kafka的topics.sh脚本创建一个新的主题,指定了bootstrap-server列表,即Kafka集群的地址和端口
# 在node1上作为生产者向zhangyao主题发送消息
[root@node1 ~]# /usr/local/kafka/bin/kafka-console-producer.sh --broker-list 10.0.0.100:9092 --topic zhangyao
# 使用Kafka的console-producer.sh脚本作为生产者向指定的主题发送消息
> zhangyao
> node1
> node2
> node3
# 在node1上作为消费者从zhangyao主题接收消息
[root@node1 ~]# /usr/local/kafka/bin/kafka-console-consumer.sh --topic zhangyao --bootstrap-server 10.0.0.100:9092 --from-beginning
# 使用Kafka的console-consumer.sh脚本作为消费者从指定的主题接收消息
# --from-beginning选项表示从主题的起始位置开始消费消息
zhangyao
node1
node2
node3
# 在node2上作为消费者从zhangyao主题接收消息
[root@node2 ~]# /usr/local/kafka/bin/kafka-console-consumer.sh --topic zhangyao --bootstrap-server 10.0.0.100:9092 --from-beginning
# 与在node1上相同的操作,但在另一个节点上进行,以验证Kafka集群的分布式特性
zhangyao
node1
node2
node3
# 在node3上作为消费者从zhangyao主题接收消息
[root@node3 ~]# /usr/local/kafka/bin/kafka-console-consumer.sh --topic zhangyao --bootstrap-server 10.0.0.100:9092 --from-beginning
# 同样,在第三个节点上进行消费操作,验证Kafka集群的正常工作
zhangyao
node1
node2
node3