Hướng dẫn mongodb cluster docker - docker cụm mongodb

Như bài lần trước mình đã trình bày về MongoDb cluster (https://viblo.asia/tanphan/posts/oOVlYEmVl8W) Hôm nay mình sẽ cùng nhau tạo 1 cụm mongo với docker, để xem thực hư nó như nào nhé.

Đầu tiên là file docker-compose.yml Các bạn tạo 1 thư mục đặt tên là sharding-by-docker-compose, bên trong tạo 1 file docker-compose.yml với nội dung như sau:

version: '2'
services:
  shard00:
    image: mongo
    command: mongod --replSet rs0 --shardsvr --dbpath /data/db --port 27017
    volumes:
      - ./data/shard00:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/replicaset_0:/scripts/replicaset_0
    ports:
      - 27022:27017
    links:
      - shard01
      - shard02
  shard01:
    image: mongo
    command: mongod --replSet rs0 --shardsvr --dbpath /data/db --port 27017
    volumes:
      - ./data/shard01:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27023:27017
  shard02:
    image: mongo
    command: mongod --replSet rs0 --shardsvr --dbpath /data/db --port 27017
    volumes:
      - ./data/shard02:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27024:27017

Với file docker-compose như trên, mình mới chỉ khởi tạo 3 node cho 1 replica set (replica set là gì các bạn đọc bài trước nhé), mình có map data ra bên ngoài (để sau này khi up lại thì data vẫn còn nguyên) đồng thời cũng map 1 file script ra bên ngoài để build replica set và add sharding. Nội dung file script ở bên đưới. Để build lên 9 node, các bạn cứ lặp lại đoạn code trên (trong khối services thôi nhé) với các chỉ số là shard10, shard11, shard12, shard20,.... lưu ý, nếu có port cổng ra ngoài cũng phải đổi đi nhé, ko nó conflic đấy =)) OK, nhưng chỉ 9 node mongod ko thể tạo thành 1 cụm được, ta phải cố 3 node làm vai trò config server, sau khi điền đủ 30 shard, ta thêm đoạn sau vào khối services :

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1

Ok, mình đã có 3 node làm vai trò config, cũng mount data và 1 file script ra bên ngoài, nội dung file script sẽ bên dưới nhé. Cuối cùng chúng ta cần 2 node mongos đóng vai trò interface, giao tiếp với người dùng, thêm đoạn mã sau:

router0:
    image: mongo
    command: mongos --configdb configRs/configsvr0:27017,configsvr1:27017,configsvr2:27017 --port 27017
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/sharding_replicaset:/scripts/sharding_replicaset
    ports:
      - 27017:27017
    links:
      - configsvr2
router1:
    image: mongo
    command: mongos --configdb configRs/configsvr0:27017,configsvr1:27017,configsvr2:27017 --port 27017
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/sharding_replicaset:/scripts/sharding_replicaset
    ports:
      - 27018:27017
    links:
      - router0

Được rồi, để chạy thử coi nhé, các bạn chạy lệnh sau (nhớ là vẫn thao tác trong thư mục sharding-by-docker-compose)

docker-compose up

Kết qủa là :

                Name                              Command               State            Ports
--------------------------------------------------------------------------------------------------------
shardingbydockercompose_configsvr0_1   /entrypoint.sh mongod --co ...   Up      0.0.0.0:27019->27017/tcp
shardingbydockercompose_configsvr1_1   /entrypoint.sh mongod --co ...   Up      0.0.0.0:27020->27017/tcp
shardingbydockercompose_configsvr2_1   /entrypoint.sh mongod --co ...   Up      0.0.0.0:27021->27017/tcp
shardingbydockercompose_router0_1      /entrypoint.sh mongos --co ...   Up      0.0.0.0:27017->27017/tcp
shardingbydockercompose_router1_1      /entrypoint.sh mongos --co ...   Up      0.0.0.0:27018->27017/tcp
shardingbydockercompose_shard00_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27022->27017/tcp
shardingbydockercompose_shard01_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27023->27017/tcp
shardingbydockercompose_shard02_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27024->27017/tcp
shardingbydockercompose_shard10_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27025->27017/tcp
shardingbydockercompose_shard11_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27026->27017/tcp
shardingbydockercompose_shard12_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27027->27017/tcp
shardingbydockercompose_shard20_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27028->27017/tcp
shardingbydockercompose_shard21_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27029->27017/tcp
shardingbydockercompose_shard22_1      /entrypoint.sh mongod --re ...   Up      0.0.0.0:27030->27017/tcp

Nhưng như vậy vẫn chỉ là các server mongo độc lập, bây h là lúc setup để chúng thành các replica set và sharding. Trong mỗi node mongod ở trên mình có mount 1 thư mục script ra bên ngoài như thế này:

volumes:
      - ./data/shard00:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/replicaset_0:/scripts/replicaset_0

bây giờ, trong thư mục sharding-by-docker-compose, các bạn tạo thư mục scrips, trong scripts tạo các thư mục replicaset_0, replicaset_1 tương ứng, trong mỗi thư mục replicaset_x đấy, tạo 1 file init_mongodb_replicaset.js với nội dung như sau:

var cfg = {
  "_id": "rs1",
  "members": [
    {
      "_id": 0,
      "host": "shard10:27017"
    },
    {
      "_id": 1,
      "host": "shard11:27017"
    },
    {
      "_id": 2,
      "host": "shard12:27017"
    }
  ] 
};

var status = rs.initiate(cfg);

printjson(status);

OK, file trên sẽ chạy với 3 node shard10, 11 và 12, sau khi chạy đoạn mã trên, 3 node shard10,11,12 sẽ được chỉ định vào 1 replicaset có id là rs1, Làm tương tự với các node shard00,01,02 cứ thế, cứ 3 node sẽ có 1 file script để setup chúng thành 1 replicaset. À, với những node đóng vai trò là config server, các bạn làm tương tự nhé, vì từ mongo 3.0 trở đi, config server cũng là 1 replicaset rồi. Với router (mongos) thì sẽ hơi khác một chút, như trong file docker-compose, khởi tạo router0 mình có mount 1 thư mục script như sau:

volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/sharding_replicaset:/scripts/sharding_replicaset

Bây giờ các bạn chỉ cần tạo 1 thư mục sharding_replicaset rồi tạo file init_mongodb_sharding_replicaset.js với nội dung như sau:

var addShard0 = sh.addShard("rs0/shard00:27017,shard01:27017,shard02:27017");
var addShard1 = sh.addShard("rs1/shard10:27017,shard11:27017,shard12:27017");
var addShard2 = sh.addShard("rs2/shard20:27017,shard21:27017,shard22:27017");

printjson(addShard0);
printjson(addShard1);
printjson(addShard2);

Đoạn mã trên sau khi được chạy sẽ đưa tất cả các replicaset vào sharding, nghĩa là dữ liệu có thể được phân mảnh trải đều trên các replicaset này (sharding là gì các bạn cũng đọc bài trước nhé) OK, bây giờ sau khi có các đoạn script, các bạn dùng docker exec để access vào các container của shard00, 10, 20 đây là các shard mà mình có mount các file script ra bên ngoài, lưu ý là cứ 3 shard thì mình có 1 file script để setup replicaset, với router và config server tương tự. sau khi access vào với lệnh

docker exec -it docker exec -it shardingbydockercompose_shard00_1 bash

shardingbydockercompose_shard00_1 là tên của container chạy shard00

các bạn chạy lệnh

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
0

Đoạn lệnh trên để chạy đoạn script trong file config mình viết bên trên thôi mà :v Chạy xong kết quả sẽ như thế này :

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
1

Như vậy là 3 node shard00, 01,02 đã thành 1 replicaset rồi, các bạn chạy tương tự với các replicaset còn lại, kể cả config server và router. Riêng với setup router, các bạn sẽ nhận được kết quả như sau:

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
2

OK, như vậy là đã sharding trên 3 replicaset rs0,1,2 Kiểm tra phát nhé, các bạn access vào 1 shard bất kì với lệnh

docker exec -it docker exec -it shardingbydockercompose_shard00_1 bash

trong container bạn vừa access vào, chạy thử lệnh

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
4

sau đó chạy lệnh:

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
5

thông tin của replicaset sẽ hiện ra:

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
6

Vậy là replicaset rs0 có 3 members, cái nào là primary, cái nào là secondary cũng hiện rõ rồi. Kiểm tra vấn đề sharding phát nhẻ, access vào router 0

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
7

Lần lượt chạy lệnh sau

configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
4
configsvr0:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr0:/data/db
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/config_replicaset:/scripts/config_replicaset
    ports:
      - 27019:27017
    links:
      - shard00
      - shard10
      - shard20
configsvr1:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr1:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27020:27017
    links:
      - configsvr0
configsvr2:
    image: mongo
    command: mongod --configsvr --replSet configRs --dbpath /data/db --port 27017
    volumes:
      - ./data/configsvr2:/data/db
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 27021:27017
    links:
      - configsvr1
9

Thông tin về sharding sẽ hiện ra

router0:
    image: mongo
    command: mongos --configdb configRs/configsvr0:27017,configsvr1:27017,configsvr2:27017 --port 27017
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/sharding_replicaset:/scripts/sharding_replicaset
    ports:
      - 27017:27017
    links:
      - configsvr2
router1:
    image: mongo
    command: mongos --configdb configRs/configsvr0:27017,configsvr1:27017,configsvr2:27017 --port 27017
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./scripts/sharding_replicaset:/scripts/sharding_replicaset
    ports:
      - 27018:27017
    links:
      - router0
0

tèn ten, vậy là đã xong, các bạn thử insert 100000 bản ghi vào mà coi, 100000 bản ghi đấy sẽ được phân bố rất đều, thôi bài sau mình sẽ hướng dẫn cách chạy test với ycsb nhé.