我正在尝试使用 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
助手,那么如何更新副本集配置呢?
答案 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);