MongoDB笔记3 - 分布式 & 副本集 & 主从复制

MongoDB的分布式部署

1、分片的概念

分片(sharding)是指根据片键,将数据进行拆分,使其落在不同的机器上的过程。如此一来,不需要功能,配置等强大的机器,也能储存大数据量,处理更高的负载。

2、分片的原理和思想

MongoDB分片的基本思想就是将集合切分成小块。这些块分散到若干片里面,每个片只负责总数据的一部分。
对于客户端来说,无需知道数据被拆分了,也无需知道服务端哪个分片对应哪些数据。数据在分片之前需要运行一个路由进程,进程名为mongos。这个路由器知道所有数据的存放位置,知道数据和片的对应关系。对客户端来说,它仅知道连接了一个普通的mongod,在请求数据的过程中,通过路由器上的数据和片的对应关系,路由到目标数据所在的片上,如果请求有了回应,路由器将其收集起来回送给客户端
MongoDB笔记3 - 分布式 & 副本集 & 主从复制

3、分片的简单实现

(1)片键的概念

设置分片时,需要从集合里面选一个键,用该键的值作为数据拆分的依据。这个键称为片键(shard key)。
{department:“IT”,name:“zhangsan”},{department:“HR”,name:“lisi”},{department:“SUPPORT”,name:“zhaowu”}
以该数据为例,表示的是职员名字以及所在的部门,假若我们设置部门(department)为片键,那么第一片可能存放名称以字母A-F开头的部门,第二片存放名称以GP开头的部门,第三片存QZ,如此类推。随着添加或者删除片,MongoDB会重新平衡数据,使每片的流量都比较均衡,数据量也在合理范围内。

(2)本地模拟实现

a、首先mongod开启服务端3个节点,端口分别为8080,8081,8082
b、开启config服务器。mongos要把mongod之间的配置放到config服务器里面,所以首先开启它,这里就使用8083端口。
命令为:
mongod --dbpath E:\sharding\config_node --port 8083
c、开启mongos服务器 。端口8084,同时指定下config服务器。
命令为:
mongos --port 8084 --configdb=127.0.0.1:8083
d、 路由指定服务端节点。客户端直接跟mongos打交道,也就说明我们要连接mongos服务器,然后将8080,8081,8082的mongod交给mongos,添加分片也就是addshard()。需要进到路由节点的admin数据库进行配置。allowLocal表示该服务端节点,可被客户端直接连接而无需经过路由。
db.runCommand({“addshard”:“127.0.0.1:8080”,allowLocal:true})
db.runCommand({“addshard”:“127.0.0.1:8081”,allowLocal:true})
db.runCommand({“addshard”:“127.0.0.1:8082”,allowLocal:true})
e、 开启数据库分片功能,命令为enablesharding(),并指定数据库名称,如下指定每个mongod都有的test数据库
db.runCommand({“enablesharding”:“test”})
f、 指定集合中分片的片键,这里就指定为company.department键.
db.runCommand({“shardcollection”:“company.department”,“key”:{“depatment”:1}})
g、 通过向mongos节点插入100万条数据,查看各节点保存的数据。
h、 通过向mongos插入一条数据,查看数据被分配到哪个片

MongoDB的分布式-副本集

1、副本集概念

    什么是副本?可能第一印象想到的是游戏副本,游戏副本就是为了让每个玩家都有一个独立的游戏环境,这种环境的复制就是副本的一种体现。MongoDB也提供了对副本的支持,副本集中有多个副本保证数据库的容错性,即使一个副本挂掉了还是会存在很多副本;并且支持副本间的自动选举,切换,解决了上一篇博文讲到的主从复制的故障恢复得人工进行的问题。其实主从复制就是一个单副本,缺少扩展性,容错性。

2、副本集原理及图解

    应用服务器,也就是客户端,连接到MongoDB的整个副本集,副本集中有一台主服务器负责整个副本集的读写,副本节点定期同步主节点的数据和oplog,以保证数据的一致性,一旦主节点宕机或挂掉,副本节点会通过心跳机制检测到,并根据事先副本集创建时设置的节点优先级进行主节点的重新选举,从而保证高可用。如此,客户端完全不必关心副本集的健康状况,MongoDB集群也可以长期保持高可用。
    副本集提供了MongoDB集群故障的自动回复机制,扩展性高,容错性强,是MongoDB官方强烈推荐使用的集群解决方案。

MongoDB笔记3 - 分布式 & 副本集 & 主从复制
MongoDB笔记3 - 分布式 & 副本集 & 主从复制

3、副本集使用说明

4个节点为例,ip,端口,日志以及数据存放路径如下      
        节点1
        地址:127.0.0.1:1001  # 在项目中,是实际的机器IP和端口,192.168.1.101:27017
        安装路径:D:\mongodb_cluster\MongoDB1
        日志存放路径:D:\mongodb_cluster\MongoDB1\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB1\data
        节点2
        地址:127.0.0.1:1002
        安装路径:D:\mongodb_cluster\MongoDB2
        日志存放路径:D:\mongodb_cluster\MongoDB2\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB2\data
        节点3
        地址:127.0.0.1:1003
        安装路径:D:\mongodb_cluster\MongoDB3
        日志存放路径:D:\mongodb_cluster\MongoDB3\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB3\data
        节点4
        地址:127.0.0.1:1004
        安装路径:D:\mongodb_cluster\MongoDB4
        日志存放路径:D:\mongodb_cluster\MongoDB4\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB4\data

        分别启动节点命令如下 
        启动节点1:
        mongod --dbpath D:\mongodb_cluster\MongoDB1\data  --logpath D:\mongodb_cluster\MongoDB1\log\mongodb.log --logappend --port 1001 --replSet guanghuan
        启动节点2:
        mongod --dbpath D:\mongodb_cluster\MongoDB2\data --logpath D:\mongodb_cluster\MongoDB2\log\mongodb.log --logappend --port 1002 --replSet guanghuan
        启动节点3:
    mongod --dbpath D:\mongodb_cluster\MongoDB3\data --logpath D:\mongodb_cluster\MongoDB3\log\mongodb.log --logappend --port 1003 --replSet guanghuan
        启动节点4:
    mongod --dbpath D:\mongodb_cluster\MongoDB4\data --logpath D:\mongodb_cluster\MongoDB4\log\mongodb.log --logappend --port 1004 --replSet guanghuan

        启动节点命令解释
        dbpath: 数据存放路径
        logpath:日志存放路径
        logappend : 日志拼接声明
        replSet:声明是副本集,后面格式为副本集名称/与之位于同一个副本集的节点地址(副本集要求至少要有两个节点,一个主,一个从)
        --fork:后台启动,这里为了效果没有添加此参数
        初始化节点(只能初始化一次,执行初始化之前,必须启动所有节点)
        mongo 127.0.0.1:1001
        use admin
       rs.initiate(
    {"_id" : "guanghuan",
     "members" : [
        {"_id" : 1, "host" : "127.0.0.1:1001", "priority":3},
        {"_id" : 2, "host" : "127.0.0.1:1002", "priority":2},
        {"_id" : 3, "host" : "127.0.0.1:1003", "priority":1},
        {"_id" : 4, "host" : "127.0.0.1:1004", "arbiterOnly" : true}
    ]
});        
初始化节点命令解释
        _id:副本集名称,与启动节点中的名称保持一致
        host:副本集成员地址
        priority:优先级,即选举成为新master的优先级,越大优先级越高
        arbiterOnly:仲裁节点

        
验证 :  rs.status()   # 查看副本集的状态


        登录主节点,即优先级最高的master节点,输入是否主节点的命令:rs.isMaster()
        相关指令:
        rs.remove(hostportstr) : 删除节点hostportstr:127.0.0.1:1003
        rs.add(hostportstr)  :增加节点

		登录所有副本集成员,设置:rs.slaveOk(),不然副本集不允许读取数据

	修改节点优先级:
		cfg = rs.conf()
		cfg.members[0].priority=10
		rs.reconfig(cfg)
		
        将该主节点关闭,登录优先级第二的从节点,输入是否主节点的命令: 发现在主节点宕机后,优先级较高的节点被选举为了master节点,继续负责读写的工作,从而持续地提供服务,保持集群高可用。
        
    四、仲裁者节点及其作用
        当集群中的节点数量为偶数个时,投票选举机制会根据数据最后操作,更新时间戳,优先级等来判定谁将成为master节点,如果出现以上条件都符合的情况,且票数相等,此投票环节需要等待若干分钟,这对于客户端来说是无法接受的。
        仲裁节点的出现打破了这个僵局,仲裁节点并不需要太多系统资源,也并不持有数据本身,而是参与投票并有效协调从节点争master的撕逼。
        集群中部署多仲裁节点时,需在初始化副本集时,添加属性arbiterOnly:true

备注:

备注:
1. 整个副本集中的数据库,用户名和密码要统一
2. 增、删、改 操作只能在master机器上进行
3. 读取 操作 根据操作程序的配置,可以从不同的机器上读取
# conn = MongoClient('mongodb://127.0.0.1:1001,127.0.0.1:1002/')
conn = MongoClient(['127.0.0.1:1001,127.0.0.1:1002'])


from pymongo import ReadPreference

test = conn.get_database('test', read_preference=ReadPreference.SECONDARY_PREFERRED)


'PRIMARY',  : 在主节点上读取
'PRIMARY_PREFERRED', : 主节点优先
'SECONDARY', : 只在 从节点 上读取
'SECONDARY_PREFERRED', :从节点 优先
'NEAREST', : 自动选择最空闲的节点读取

笔记

1、索引


1、索引
    提高检索速度
    降低增、删、改的速度

    索引不是越多越好!只在必要的字段上建立索引
    什么字段建立索引?
    根据你的业务需求,需要频繁作为条件进行查询的字段

    不建议建立索引的字段:
    需要频繁修改的字段

    索引是有顺序的,升序和降序

2、缩写

2、缩写
    ns  大概率是 namespace, 命名空间

    pasword:  pass、 pwd
    internationalization:  i18n

3、复合索引

3、复合索引
    建立复合索引:db.inventory.createIndex({'item':1, 'qty':-1})

    以下各种情况是否应用到了上面这个索引:
    db.inventory.find({'item': 'test'})  索引起效
    db.inventory.find({'qty': 5})     索引不起效
    db.inventory.find({'item': 'test', 'qty': 5})  起效
    db.inventory.find({'qty': 5, 'item': 'test'})  起效

    条件中:
    包含了符合索引的 字段的从第一个按顺序来的, 那么就会起效的
    如果中间有某个字段 中断 了的,那么就不会起效

    譬如: 索引字段的顺序是:col1、col2、col3、col4、col5
    索引起作用的 字段查询:
    col1
    col1、col2
    col1、col2、col3
    col1、col2、col3、col4
    col1、col2、col3、col4、col5
    索引不起作用的 查询:
    col2、col3、col4、col5
    col1、col2、col4、col5

4、斜杠

4、斜杠
/  :  斜杠
    \  :  反斜杠


5、条件操作符


5、条件操作符
    select * from table_name where age < 18
    db.table_name.find({'age'< 18})  不允许出现   <
    db.table_name.find({'age': {$lt: 18}})

6、 nor

6、 nor
    使用逻辑NOR连接查询子句将返回所有与两个子句不匹配的文档。
    db.inventory.find({$nor: [{item:'journal'}, {qty:25}]})
    等同于:
    db.inventory.find({$and: [{item: {$ne: 'journal'}}, {qty: {$ne: 25}}]})

7、 exsits

7、 exsits
    字段是否存在
    db.inventory.find({item:{$exists: true}})
    即使  item: null  也算存在!

8、 参数个数错误

8、 参数个数错误
    mongodb:  Expression $subtract takes exactly 2 arguments. 3 were passed in.
    python:   TypeError: test_func() takes 2 positional arguments but 3 were given

    只要2个参数,但是你提供了3

9、avg 取平均值

9、avg 取平均值
    mysql:
    select item as _id, avg(price*quantity) as avgAmount,
        avg(quantity) as avgAquantity from sales group by item

    mongodb:
        db.sales.aggregate(
           [
             {
               $group:
                 {
                   _id: "$item",
                   avgAmount: { $avg: { $multiply: [ "$price", "$quantity" ] } },
                   avgQuantity: { $avg: "$quantity" }
                 }
             }
           ]
        )

10、json

10、json,只关注4个方法:
    load : 从文件中反序列化为 字典对象
    dump : 将 字典对象 序列化到 文件当中
    loads: 将一个符合 json 格式的 字符串 反序列化 为 字典对象
    dumps: 将 字典对象 序列化为 一个 json字符串

备份与恢复

1、 备份

备份与恢复
1、	备份:
mongodump -h dbhost -d dbname -o dbdirectory
-h:
MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d:
需要备份的数据库实例,例如:test
-o:
备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

mongodump -h 127.0.0.1 -d test -o d:\
mongodump -h 127.0.0.1:27017 -d test -o d:\
mongodump -h 127.0.0.1:27017 -d test –-collection counters -o d:\

2、 恢复

2、	恢复
mongorestore -h <hostname><:port> -d dbname <path>
--host <:port>, -h <:port>:
MongoDB所在服务器地址,默认为: localhost:27017
--db , -d :
需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
--drop:
恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!
<path>:
mongorestore 最后的一个参数,设置备份数据所在位置,例如:c:\data\dump\test。

你不能同时指定 <path>--dir 选项,--dir也可以设置备份目录。

--dir:
指定备份的目录

你不能同时指定 <path>--dir 选项。

MongoDB主从复制+集群

1、读写分离的概念

1、读写分离的概念
    读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERTUPDATEDELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
    读写分离的目的是为了实现高并发场景下的请求分流,避免对数据库的访问过于集中,导致性能下降甚至是宕机。

MongoDB主从复制+集群

2、主从复制介绍

2、主从复制介绍
    在MongoDB的集群中,会有指定为master的主节点存在,该节点用于被客户端进行数据的增删改操作。同时集群中还会有被指定为slave的节点存在,即从节点,该节点主要接收来自于客户端的读,检索操作,并不具备增删改操作的功能。
    在master节点处理完增删改操作后,会实时同步数据到与其绑定的从节点上,实现主从复制至少要有两个数据库实例,并且每个从节点需要知道主节点的地址,如果是在linux中记得开通主从端口的防火墙。
    主从复制的优势在于比较灵活,适用于数据备份,故障后人工进行数据恢复,以及对读数据的扩展等。

MongoDB笔记3 - 分布式 & 副本集 & 主从复制

3、主从复制局限

3、主从复制局限
    (1)MongoDB目前建议使用副本集实现集群管理,不建议使用简单的主从复制
    (2)主从复制在master宕机后,没有自动选举master机制,导致主节点服务一挂,便不能对外提供增删改操作。
    (3)所有增删改操作都是针对主节点进行操作,可能导致主节点性能下降。
    (4)从节点对主节点的数据都是全量拷贝,对主从节点的压力都是不小的。

4、主从复制简单配置及实现

4、主从复制简单配置及实现
    设备有限,为方便简单的实现,可在一台机器上模拟主节点和从节点。在C盘创建master目录,在E盘创建slave目录,master目录作为主节点数据存放的目录,slave目录作为从节点数据存放的目录。
    注意:主节点和从节点要指定不同的端口。
    启动主节点:mongod --dbpath C:\master --port 666 --master
    启动从节点:mongod --dbpath E:\slave --port 888 --slave --source localhost:666
    启动成功后就可以连接主节点进行操作了,而对主节点的操作会同步到从节点,而对从节点进行插入操作时,会报not master的提示并拒绝写入数据。
    配置实现解释
    master:默认为false,若要设置当前节点为主节点,需要在服务端启动添加--master
    slave:默认为false,若要设置当前节点为从节点,需要在服务端启动添加--slave
    source:默认为空,用于从节点,指定从节点的复制来源,即主节点所在的地址,格式为:<host><:port>
    only:默认为空,用于从节点,主动复制默认复制主节点上所有的数据库,通过设置此项指定需要复制的数据库名称
    slavedelay:设置从节点同步主节点的延迟时间,用于从节点设置,默认为0,单位秒。
    autoresync:默认为false,用于从节点设置。是否自动重新同步。设置为true,如果落后主节点超过10秒,会强制从节点自动重新同步。如果oplogSize太小,此设置可能有问题。如果oplog大小不足以存储主节点的变化状态和从节点的状态变化之间的差异,这种情况下强制重新同步是不必要的。当设置autoresync选项设置为false10分钟内从节点不会进行大于1次的自动重新同步。
    什么是oplog?
    主节点的操作会被记录为oplog,存储在系统数据库local的集合oplog.$main中,这个集合中的每个文档都代表主节点的一个操作(不包括查询),从节点定期从主服务器获取oplog数据,并在本机进行执行,oplog使用的是固定集合,随着操作的逐渐增加,新的文档会逐渐覆盖旧的文档。

副本集

1、副本集概念

1、副本集概念
        什么是副本?可能第一印象想到的是游戏副本,游戏副本就是为了让每个玩家都有一个独立的游戏环境,这种环境的复制就是副本的一种体现。MongoDB也提供了对副本的支持,副本集中有多个副本保证数据库的容错性,即使一个副本挂掉了还是会存在很多副本;并且支持副本间的自动选举,切换,解决了上一篇博文讲到的主从复制的故障恢复得人工进行的问题。其实主从复制就是一个单副本,缺少扩展性,容错性。

2、副本集原理及图解

2、副本集原理及图解
        应用服务器,也就是客户端,连接到MongoDB的整个副本集,副本集中有一台主服务器负责整个副本集的读写,副本节点定期同步主节点的数据和oplog,以保证数据的一致性,一旦主节点宕机或挂掉,副本节点会通过心跳机制检测到,并根据事先副本集创建时设置的节点优先级进行主节点的重新选举,从而保证高可用。如此,客户端完全不必关心副本集的健康状况,MongoDB集群也可以长期保持高可用。
        副本集提供了MongoDB集群故障的自动回复机制,扩展性高,容错性强,是MongoDB官方强烈推荐使用的集群解决方案。

MongoDB笔记3 - 分布式 & 副本集 & 主从复制
MongoDB笔记3 - 分布式 & 副本集 & 主从复制

3、副本集使用说明

3、副本集使用说明
        以4个节点为例,ip,端口,日志以及数据存放路径如下      
        节点1
        地址:127.0.0.1:1001  # 在项目中,是实际的机器IP和端口,192.168.1.101:27017
        安装路径:D:\mongodb_cluster\MongoDB1
        日志存放路径:D:\mongodb_cluster\MongoDB1\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB1\data
        节点2
        地址:127.0.0.1:1002
        安装路径:D:\mongodb_cluster\MongoDB2
        日志存放路径:D:\mongodb_cluster\MongoDB2\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB2\data
        节点3
        地址:127.0.0.1:1003
        安装路径:D:\mongodb_cluster\MongoDB3
        日志存放路径:D:\mongodb_cluster\MongoDB3\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB3\data
        节点4
        地址:127.0.0.1:1004
        安装路径:D:\mongodb_cluster\MongoDB4
        日志存放路径:D:\mongodb_cluster\MongoDB4\log\mongodb.log
        数据存放路径:D:\mongodb_cluster\MongoDB4\data

        分别启动节点命令如下 
        启动节点1:
        mongod --dbpath D:\mongodb_cluster\MongoDB1\data  --logpath D:\mongodb_cluster\MongoDB1\log\mongodb.log --logappend --port 1001 --replSet guanghuan
        启动节点2:
        mongod --dbpath D:\mongodb_cluster\MongoDB2\data --logpath D:\mongodb_cluster\MongoDB2\log\mongodb.log --logappend --port 1002 --replSet guanghuan
        启动节点3:
    mongod --dbpath D:\mongodb_cluster\MongoDB3\data --logpath D:\mongodb_cluster\MongoDB3\log\mongodb.log --logappend --port 1003 --replSet guanghuan
        启动节点4:
    mongod --dbpath D:\mongodb_cluster\MongoDB4\data --logpath D:\mongodb_cluster\MongoDB4\log\mongodb.log --logappend --port 1004 --replSet guanghuan

        启动节点命令解释
        dbpath: 数据存放路径
        logpath:日志存放路径
        logappend : 日志拼接声明
        replSet:声明是副本集,后面格式为副本集名称/与之位于同一个副本集的节点地址(副本集要求至少要有两个节点,一个主,一个从)
        --fork:后台启动,这里为了效果没有添加此参数
        初始化节点(只能初始化一次,执行初始化之前,必须启动所有节点)
        mongo 127.0.0.1:1001
        use admin
       rs.initiate(
    {"_id" : "guanghuan",
     "members" : [
        {"_id" : 1, "host" : "127.0.0.1:1001", "priority":3},
        {"_id" : 2, "host" : "127.0.0.1:1002", "priority":2},
        {"_id" : 3, "host" : "127.0.0.1:1003", "priority":1},
        {"_id" : 4, "host" : "127.0.0.1:1004", "arbiterOnly" : true}
    ]
});        
初始化节点命令解释
        _id:副本集名称,与启动节点中的名称保持一致
        host:副本集成员地址
        priority:优先级,即选举成为新master的优先级,越大优先级越高
        arbiterOnly:仲裁节点

        
验证 :  rs.status()   # 查看副本集的状态


        登录主节点,即优先级最高的master节点,输入是否主节点的命令:rs.isMaster()
        相关指令:
        rs.remove(hostportstr) : 删除节点hostportstr:127.0.0.1:1003
        rs.add(hostportstr)  :增加节点

		登录所有副本集成员,设置:rs.slaveOk(),不然副本集不允许读取数据

	修改节点优先级:
		cfg = rs.conf()
		cfg.members[0].priority=10
		rs.reconfig(cfg)
		
        将该主节点关闭,登录优先级第二的从节点,输入是否主节点的命令: 发现在主节点宕机后,优先级较高的节点被选举为了master节点,继续负责读写的工作,从而持续地提供服务,保持集群高可用。

4、仲裁者节点及其作用

4、仲裁者节点及其作用
        当集群中的节点数量为偶数个时,投票选举机制会根据数据最后操作,更新时间戳,优先级等来判定谁将成为master节点,如果出现以上条件都符合的情况,且票数相等,此投票环节需要等待若干分钟,这对于客户端来说是无法接受的。
        仲裁节点的出现打破了这个僵局,仲裁节点并不需要太多系统资源,也并不持有数据本身,而是参与投票并有效协调从节点争master的撕逼。
        集群中部署多仲裁节点时,需在初始化副本集时,添加属性arbiterOnly:true

笔记

1、mongodb中 嵌套文档的访问


1、mongodb中 嵌套文档的访问
    {size:{w:18}}
    是通过 "size.w"  来进行访问

2、$field_name

2、mongodb中, 只要字段出现在 : 符号的右边,必须通过  '$field_name' 来进行访问

3、心跳包


3、心跳包
    机器A 向 机器B 发送心跳包
    其实就是机器A 定时向 机器B 发送一个特定的数据包, 告诉机器B, 我机器A还在正常工作
    这个 特定的数据包 就叫做心跳包,因为他是 定时发送的, 就类似人的心跳

4、搭建 副本集 命令

4、搭建 副本集  命令
    mongod --dbpath D:\mongodb_cluster\MongoDB\data --logpath D:\mongodb_cluster\MongoDB\log\mongodb.log --logappend --bind_ip 192.168.8.254 --port 1809 --replSet guanghuan

    rs.initiate(
        {"_id" : "guanghuan",
         "members" : [
            {"_id" : 1, "host" : "192.168.8.254:1809", "priority":30},
            {"_id" : 3, "host" : "192.168.8.226:1809", "priority":30},
            {"_id" : 4, "host" : "192.168.8.98:1809", "priority":30},
            {"_id" : 5, "host" : "192.168.8.227:1809", "priority":30},
            {"_id" : 6, "host" : "192.168.8.106:1809", "priority":30},
            {"_id" : 7, "host" : "192.168.8.144:1809", "priority":30},
            {"_id" : 24, "host" : "192.168.8.254:1004", "arbiterOnly" : true}
        ]
    })

5、 pip 不是内部或外部变量

5、 pip 不是内部或外部变量
    解决:将 python 安装目录下的 Scripts 目录 添加到 环境变量中即可解决

6、再次强调去 阅读 PEP8

6、再次强调去 阅读 PEP8
    注意 命名冲突!
不能以数字、中文 作为 模块名