使用pymongo创建和维护MongoDB副本集

时间:2014-10-17 11:57:19

标签: mongodb pymongo

我正在尝试使用 pymongo 复制(用于教学活动)IPython笔记本中的Docker and MongoDB Sharded Cluster食谱以设置多个mongo副本集。

该配方建议通过连接到建议副本集的一个成员,从mongo提示创建副本集,如下所示:

mongo --port <port>

rs.initiate()
rs.add("<IP_of_rs1_srv2>:27017")
rs.add("<IP_of_rs1_srv3>:27017")
rs.status()

pymongo documentation建议采用以下初始化路线:

$ hostname
morton.local
$ mongod --replSet foo/morton.local:27018,morton.local:27019 --rest
$ mongod --port 27018 --dbpath /data/db1 --replSet foo/morton.local:27017 --rest
$ mongod --port 27019 --dbpath /data/db2 --replSet foo/morton.local:27017 --rest

from pymongo import MongoClient, ReadPreference
c = MongoClient("morton.local:27017", read_preference=ReadPreference.SECONDARY)

c.admin.command("replSetInitiate")

这需要知道端口ID并通过--replSet标志在数据库服务器的初始化中使用它们,而不是仅为副本集声明一个简单的单个标签,然后将其应用于每个成员。如何在 pymongo 中编写初始化脚本以遵循原始配方?

原始版本还通过更改主机名以包含容器IP地址来修改配置:

cfg = rs.conf()
cfg.members[0].host = "<IP_of_rs1_srv1>:27017"
rs.reconfig(cfg)
rs.status()

同样, pymongo 不支持rs助手,那么如何更新副本集配置呢?

1 个答案:

答案 0 :(得分:0)

一个解决方案是根据mongodb容器的属性为副本集创建配置,然后使用它来启动集群集。

例如,配置可能采用以下形式:

rsc = {'_id': 'rs4',
 'members': [{'_id': 0, 'host': '172.17.0.2:27017'},
  {'_id': 1, 'host': '172.17.0.3:27017'},
  {'_id': 2, 'host': '172.17.0.4:27017'}]}

然后使用replSetInitiate admin命令调用。

import docker

#Connect to docker
c = docker.Client(base_url='unix://var/run/docker.sock',
                  version='1.10',
                  timeout=10)

创建一组数据库节点作为副本集运行:

def createReplicaSetNode(c,stub,num=0):
    ''' Create and run a specified number of mongo database servers as a replica set '''
    name='{stub}_srv{num}'.format(stub=stub,num=num)
    command='--replSet {stub}  --noprealloc --smallfiles'.format(stub=stub)
    c.create_container('dev24/mongodb',name=name,command=command)
    c.start(name,publish_all_ports=True)
    return name

def createReplicaSetNodes(c,stub,numNodes):
    ''' Create and run a specified number of mongo database servers as a replica set '''
    names=[]
    for i in range(0,numNodes):
        name=createReplicaSetNode(c,stub,i)
        names.append(name)
    return names


def getContainIPaddress(c,container):
    ''' Get the IP address of the container '''
    cConfig = c.inspect_container(container)
    return cConfig['NetworkSettings']['IPAddress']

def rs_config(c,rsid,num=3):
    ''' Create a replica set of nodes and then define a configuration file for that replica set '''
    createReplicaSetNodes(c,rsid,num)
    _rs_config={"_id" : rsid, 'members':[] }
    #This is scrappy - should really return something better from the creation
    for i in range(0,num):
        name='{stub}_srv{num}'.format(stub=rsid,num=i)
        #c.inspect_container(name)
        #get IP and port
        _rs_config['members'].append({"_id":i,"host":'{0}:{1}'.format(getContainIPaddress(c,name),27017)})
    return _rs_config

然后我们可以启动节点并为副本集创建配置文件:

rsc=rs_config(c,'rs4')
rsc

'''
{'_id': 'rs4',
 'members': [{'_id': 0, 'host': '172.17.0.2:27017'},
  {'_id': 1, 'host': '172.17.0.3:27017'},
  {'_id': 2, 'host': '172.17.0.4:27017'}]}
'''

此配置数据用于初始化副本集:

from pymongo import MongoClient

#Find the local port bound for 27017/tcp for each server in the replica set
def get27017tcp_port(c,container):
    cConfig = c.inspect_container(container)
    return int(cConfig['NetworkSettings']['Ports']['27017/tcp'][0]['HostPort'])

#We'll use the 0th server in the set as a the node
mc = MongoClient('localhost', get27017tcp_port(c,'rs4_srv0'))


#In mongo console, we'd typically use command rs.config() to initialise replica set
#Here, use replSetInitiate admin command, applying it with desired configuration
mc.admin.command( "replSetInitiate",rsc);