mongodb replica 是 mongo 的一个集群部署模式,replica 模式下,mongodb 本身的 读写实现了分离,性能更加优秀。

使用 docker compose 来部署 mongodb replica 的时候需要解决的问题是,网络和集群的搭建, docker 网络本身就挺复杂的,加上如果不知道 mongodb replica 的工作方式,那么将更加难以 完成集群的搭建。

replica

从图上面我们需要知道两个事情:

  • mongo replica 同步的时候从节点都需要和主节点通信
  • 当需要读模式的时候,客户端可能需要和各个节点通信,那么对于各个语言的客户端也一样的

所以需要解决节点之间的内网通信,也需要解决各个语言 SDK 和各个节点的通信关系。

直接使用最后的 docker-compose file 来说吧:

version: "3"

services:
  mongo1:
    image: mvertes/alpine-mongo
    restart: always
    ports:
      - "27017:27017"
    entrypoint: [ "/usr/bin/mongod", "--port", "27017", "--bind_ip_all", "--replSet", "rs"]
  
  mongo2:
    image: mvertes/alpine-mongo
    restart: always
    ports:
      - "27018:27018"
    entrypoint: [ "/usr/bin/mongod", "--port", "27018", "--bind_ip_all", "--replSet", "rs"]

  mongo3:
    image: mvertes/alpine-mongo
    restart: always
    ports:
      - "27019:27019"
    entrypoint: [ "/usr/bin/mongod", "--port", "27019", "--bind_ip_all", "--replSet", "rs"]

这个地方使用一个第三方的 docker image 主要是为了调试方便,里面的系统工具比较全,主要是 可能需要用到 nc / ping / netstat 等工具;另外注意参数--bind_ip_all参数,虽然 docker compose 所有的容器默认都在同一个网络下,但是也是有一个 IP 的,如果使用默认参数,所有容器的 端口只在容器里面监听回环网络 127.0.0.1 ,不同容器之间 IP 可以 ping 通,但是通过 nc 工具, 端口是不通的,所以这个选项需要加上。

运行完后,这个时候三个容器的复制集还没建立起来,需要使用命令行来完成:


#!/bin/sh

sudo docker-compose -f docker-compose.yaml up -d
sudo docker-compose -f docker-compose.yaml exec mongo1 mongo --port 27017 --eval 'var cfg = { "_id": "rs", "version": 1, "members": [{ "_id": 0, "host": "mongo1:27017", "priority": 2 }, { "_id": 1, "host": "mongo2:27018", "priority": 0 }, { "_id": 2, "host": "mongo3:27019", "priority": 0 } ] }; rs.initiate(cfg); rs.status();'

以上将容器 mongo1 设置为 primary 节点,之后集群就已经搭建起来了,可以在外面通过 mongo 命令连接 并查看状态。

对于需要使用 SDK 来访问的客户端来说,还需要配置 hosts 来实现客户端到各个节点的通信,修改 /etc/hosts:

external_ip mongo1
external_ip mongo2
external_ip mongo3

本节完,如果有疑问,欢迎留言。