MongoDB 4.0.10 复制(副本集)和分片

  • MongoDB 复制(副本集)
    • 多台机器共同维护相同的数据副本,提高服务器的可用性,并可以保证数据的安全性
    • mongodb的复制至少需要两个节点:其中一个是主节点Primary,负责处理客户端请求;其余的都是从节点Secondary,负责复制主节点的数据
    • 副本集:有N个节点的集群,任何节点都可以作为主节点,所有的写入操作都在主节点上,可以自动故障转移和自动恢复
    • 当主节点服务断开时,某一个从节点会自动成为主节点
 1 # 1.建立多个MongoDB实例,使用--replSet声明复制集的名称,--smallfiles表示一个小文件
 2 mongod --port 27018 --dbpath C:MongoDBdata1 --replSet rsa --smallfiles
 3 mongod --port 27019 --dbpath C:MongoDBdata2 --replSet rsa --smallfiles
 4 # 2.声明配置文件,_id为复制集名称,members为复制集的成员,默认一个成员为主节点
 5 var rsconf={ _id:"rsa", members:[{_id:0, host:"localhost:27018"}, {_id:1, host:"localhost:27019"} ]}
 6 # 3.启动端口号为27018的实例
 7 mongo --port 27018
 8 rs.initiate(rsconf) # 根据配置初始化,此时,端口27018为主节点
 9 # 4.初始化之后进入 rsa:PRIMARY> 模式
10 # rsa:PRIMARY> 模式命令 
11 rs.add("localhost:27020")        # 增加一个节点集
12 rs.remove("localhost:27020")    # 删除一个节点集
13 rs.status()                     # 查看状态
14 rs.conf()                        # 查看配置
15 rs.isMaster()                     # 判断当前服务是否为主节点
16 rs.help()                        # 查看帮助
17 rs.reconfig(cfg)                # 重载配置
18 rs.slaveOk()                    # 从节点访问数据库,执行该函数,否则从节点无法访问
19 # 5.只有主节点才能进行数据库数据的CDU操作,在主节点插入数据,在从节点可以查到相同数据,实现数据的同步
  • MongoDB 分片
    • 当MongoDB存储海量的数据时,一台机器可以不足以存储数据,这时,可以通过在多台机器上分割数据,使得数据库系统能够存储和处理更多的数据
    • 使用分片的原因:单个副本集限制在12个节点;当请求量巨大时会出现内存不足;本地磁盘不足,垂直扩展价格昂贵
    • mongos:前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用
    • Config Server:mongod实例,不存储真正的数据信息,存储的是meta信息(某条数据在哪个片上);mongos查询某条数据时,要先找到config sever,询问该数据在哪个shard上
    • 分片要素:要有N(N>=2)个mongod服务做片节点(shard1,shard2....);要有config server维护meta信息;要舍得号数据的分片规则;要启动mongos做路由
 1 # 1.建立用作 分片shard 的mongod实例
 2 mongod --port 27018 --dbpath C:MongoDBdata1 --smallfiles --shardsvr
 3 mongod --port 27019 --dbpath C:MongoDBdata2 --smallfiles --shardsvr
 4 # 2.建立用作 Config Server 的mongod实例
 5 mongod --configsvr --dbpath C:MongoDBdata0 --port 27020 --replSet rsa --smallfiles
 6 # 3.对端口27020的服务配置复制集模式
 7 mongo --port 27020
 8 var rsconf={ _id:"rsa", members:[{_id:0, host:"localhost:27020"}]}
 9 rs.initiate(rsconf) # 初始化
10 # 4.配置mongos
11 mongos --help # 查看帮助
12 mongos --port 30000 --configdb rsa/localhost:27020
13 # 5.连接路由mongos
14 mongo --port 30000 # 进入 mongos> 模式
15 # 6.添加分片的服务
16 sh.addShard("localhost:27018")
17 sh.addShard("localhost:27019")
18 # 7.对shop数据库启用分片功能
19 sh.enableSharding("shop")
20 # 8.添加待分片的表,第二个参数设置用于分片的属性,可以设置多个;系统会利用该属性的值,来计算应该分到哪一片上
21 sh.shardCollection("shop.goods", {goodsid:1}) # 设置goodsid为用于分片的属性
22 # 9.修改chunk大小,chunk默认64m(取值范围是在1MB到1024MB之间)
23 use config
24 db.settings.save({_id:"chunksize", value:1})
25 # 10.测试分片效果,插入数据
26 for(var i=1;i<=100000;i++){
27     db.goods.insert({goodsid:i,name:"numbers"+i,date:new Date()})
28 }
29 # 11.查看分片情况
30 sh.status() # 可以看出在两个分片上分别有不同数量的chunk
31 # 可以进入端口27018和27019进行查看shop数据库的goods集合的数据量
32 
33 # 进入 mongos> 模式
34 sh.help()                     # 查看帮助
35 sh.status()                    # 查看状态
36 sh.addShard(<host>)            # 添加一个分片,host:为servr:port或者setname/server:post格式的,setname为复制集名称
37 sh.enableSharding(<DBName>)    # 启用某个数据库的分片功能,DBName为数据库名称
38 # fullname:为 shop.goods 形式数据代表shop数据库下的goods集合,field:为用于分片的属性
39 sh.shardCollection(<fullname>, {field:1})        # 启用一个集合的分片功能
40 sh.splitAt(<fullname>, {field:1000})            # 用于手动预先分片,设置在field=1000处有个分片界限
41 sh.addShardTag("shard00","NYC")                    # 即片键为NYC的数据集中分布到片shard00上
42 sh.addShardTag(<shard_server>,<tag_name>)        # 指定分片标记,shard_server:片名称,tag_name:片键标记
43 sh.removeShardTag(<shard_server>,<tag_name>)    # 移除分片标记
44 sh.addTagRange("records.users",{key:"100"},{key:"500"},"NYC")            # 对分片标记指定范围,片键在"100"-"500"
45 sh.addTagRange(<collection_path>,<startValue>,<endValue>,<tag_name>)    # 设置片键范围
  • 手动预先分片
    • 数据在shard上的分布原因:mongodb不是从单篇文档的级别,绝对平均的散落在各个片上,而是N篇文档形成一个块chunk,放置到某一个片上;当某一片上的chunk数量比另外一片的chunk数量较多时(>=3),就会把本片上的chunk转移到另外一片上,是以chunk为单位来维护片之间的数据均衡
    • 使用手动预先分片的原因:如果随着数据的不断增多,shard实例之间,经常有chunk来回移动,这样会照成服务器之间的IO流的增加,所以可以预先定义一个规则,即某N条数据形成一个chunk,预先分配M个chunk,M个chunk预先分配到不同片上,这样以后的数据会直接插入到各自预分配好的chunk上,不会再来回移动
 1 # 设置待分片的集合
 2 sh.shardCollection("shop.users", {userid:1})
 3 # 预先在1k,2k,3k....这样的界限上划分好chunk,这些chunk会均匀的分布到各个片上
 4 for(var i=1;i<=40;i++){
 5     sh.splitAt("shop.users", {userid:i*1000})
 6 }
 7 # 查看状态,多次查看之后,两个片的chunk数量稳定在20,21
 8 sh.status()
 9 # 插入测试数据
10 for(var i=1;i<=40000;i++){
11     db.users.insert({userid:i,name:"numbers"+i,date:new Date()})
12 }
13 # 连接端口27018和27019,查看数据,发现两个实例上的数据一个为19999,20001,很均匀
  • 使用分片的常见错误
    • mongos --port 30000 --configdb rsa/localhost:27020 报错:MongoDB BadValue configdb supports only replica set connection String
    • 原因:是在MongoDB 3.4版本之后,要求configs服务器是副本集模式
    • 解决方法:configs服务器配置成副本集模式或者是把MongoDB换成3.4以下版本
 1 # configs服务器配置成副本集模式
 2 # 2.建立用作 Config Server 的mongod实例
 3 mongod --configsvr --dbpath C:MongoDBdata0 --port 27020 --replSet rsa --smallfiles
 4 # 3.对端口27020的服务配置复制集模式
 5 var rsconf={ _id:"rsa", members:[{_id:0, host:"localhost:27020"}]}
 6 mongo --port 27020
 7 rs.initiate(rsconf) # 初始化
 8 # 4.配置mongos
 9 mongos --help # 查看帮助
10 mongos --port 30000 --configdb rsa/localhost:27020
11 
12 # 版本3.4以下的写法
13 mongod --configsvr --dbpath C:MongoDBdata0 --port 27020
14 mongos --port 30000 --configdb localhost:27020
    • 在设置待分片数据库或者集合时报错:Cannot accept sharding commands if not started with --shardsvr
    • 解决方法:配置可复制集作为分片节点与配置单独使用的可复制集基本一样。但启动参数中需指定—shardsvr参数
1 # 1.建立用作 分片shard 的mongod实例
2 mongod --port 27018 --dbpath C:MongoDBdata1 --smallfiles --shardsvr
3 mongod --port 27019 --dbpath C:MongoDBdata2 --smallfiles --shardsvr
4 
5 # 版本3.4以下的写法
6 mongod --port 27018 --dbpath C:MongoDBdata1 --smallfiles
7 mongod --port 27019 --dbpath C:MongoDBdata2 --smallfiles
原文地址:https://www.cnblogs.com/My-Sun-Shine/p/13510697.html