C# MongoDB

  1. 云栖社区>
  2. 博客>
  3. 正文

C# MongoDB

yswenli 2017-08-24 11:07:00 浏览638

一、搭建Mongodb 副本集

副本集中有三个角色:

主节点:所有副节点的数据均来自于主节点,并且只能对主节点进行读写操作。
副节点:数据来自于主节点,可以进行读取操作,但是不能进行写操作。
仲裁者:不含数据也不与客户端交流,只在选举主节点的时候进行投票。

Mongodb最多支持50个副本集成员以及最多7个选举成员,启动副本集后将开始第一次选举,在选举过程中,所有副本集成员都只能读取,直到选举出主节点后主节点才能进行读写,但是在这个期间副本成员可以提供查询服务。

而主节点要保持主节点的位置需要每两秒发送一个ping请求,如果10秒内没有得到响应则标记为不可访问,当一半以上的副本集成员不可访问,那么主节点将降级为副节点。

其中设置成员的priority值可以优先成员主节点,这个值介于0-1000之间,默认为1,如果这个值为0,那么它的votes值也为0,只要votes为0的成员不能投选举票,但是可以投否决票。但是我们也可以手动设置成员priority值为大于1的成员是否有投票权利。

在进行选举的时候,其他成员会作以下几点判断来进行投票参与选举的成员是否能作为主节点,选举步骤:

自己是否能与主节点通讯。
参与选举的成员是否比其他参与选举的成员数据最新。
如果参与选举的成员数据相等则尝试使用具有最高priority的值的成员。

仲裁者

仲裁者的出现是为了避免只有两个成员的副本集,两个成员的副本集投票可能无法满足一半以上的投票情况。

仲裁者不负责数据和客户端交流,只有参与选举的功能,需要注意的是仲裁者一旦设置过后就再也无法变为非仲裁者了。

首先部署一个副本集很简单,下面的代码是部署了一个本地含有三个成员的副本集。

建立三个成员的副本集,首先你得建立三个数据库的存放目录:

mkdir -p ./replDb/s0 ./replDb/s1 ./replDb/s2
然后我们启动三个副本集成员,其中replSet参数后面跟的是副本集的名称,将需要有关联的成员的副本集名称要一致。

mongod --dbpath ./replDb/s0 --port 27017 --replSet s0

mongod --dbpath ./replDb/s0 --port 27018 --replSet s0

mongod --dbpath ./replDb/s0 --port 27019 --replSet s0
创建仲裁者也同样非常简单,建立一个空的数据目录,然后和其他副本集成员一样设置同样的副本集名称启动,最后通过rs.add方法的第二个参数设置为true:

mongod --dbpath ./replDb/s5 --port 27020 --replSet s0

mongod --port 27017 --host localhost

> rs.add('localhost:27020', true);

然后通过Mongo Shell进入到端口为27017的成员中,并配置副本集。

mongod --port 27017 --host localhost
进入到Mongo Shell后通过rs.initiate方法来配置副本集。

> var conf = {
_id: 'r0',
version: 1,
members: [
{
_id: 0,
host: 'localhost:27017'
},
{
_id: 1,
host: 'localhost:27018'
},
{
_id: 2,
host: 'localhost:27019'
},
{
_id: 3,
host: 'localhost:27020'
}
]
};

> rs.initiate(conf);
initiate接受一个对象,对象_id为副本集名称,必须和启动副本集设置的一致才能添加进来(本例为rs0)。version为版本号,每当我们修改副本集配置的时候这个版本号都会递加1,而members则为副本集成员,我们可以在这里一次性添加完,也可以只添加一个后面再通过add方法添加,比如下面这样:

> rs.add('localhost:27018');
> rs.add('localhost:27019');

删除副本集

删除副本集通过rs.remove方法来删除,它接受一个<localhost>:<port>这样的字符串。下面是删除一个副本集成员:

> rs.remove('localhost:27019');

查询副本集配置

查看副本集配置是通过rs.conf方法查询,返回包含所有副本集的配置内容.

> rs.conf();

查询主节点

每当使用rs.add方法添加成员的时候可能会影响选举来选择主节点是谁,查看主节点通过rs.isMaster()方法来查看。

> rs.isMaster();
返回的内容中有几个可以了解

{
"hosts" : [ //副本集成员
"localhost:27017",
"localhost:27018",
"localhost:27019"
],
"setName" : "rs0", //副本集名称
"setVersion" : 3, //副本集配置版本
"ismaster" : true, //是否是主节点
"primary" : "localhost:27017", //主节点成员的主机地址
"me" : "localhost:27017", //当前所在主机
}

读取副节点

副节点默认是无法读取的,我们可以通过rs.setSlaveOk()方法来设置Slave属性为true。下面是设置端口为27018的副节点可以进行读取

mongod --port 27018 --host localhost

> rs.setSlaveOk();

隐藏成员

隐藏成员通过设置成员的hidden属性为true并且优先值priority为0则可以隐藏此成员,隐藏成员不能当主节点也不能当其他成员的复制源

> rs.add({
> _id: 1,
> _host: 'localhost:27017',
> hidden: true,
> priority: 0
> })

延迟复制

通过设置成员的slaveDelay的值并且优先值priority为0,来让当前成员滞后多少秒后才开始复制数据。

> rs.add({
> _id: 1,
> _host: 'localhost:27017',
> slaveDelay: 120,
> priority: 0
> })

索引管理

通过成员的buildIndexes的值并且优先值priority为0,来设置是否在备份机器上建立相同的索引,一般这个选项只用于纯粹备份的服务器。

下面的代码设置添加的副本集成员不创建索引。

> rs.add({
> _id: 1,
> _host: 'localhost:27017',
> buildIndexes: false
> priority: 0
> })

二、搭建配置服务器

首先搭建配置服务器,配置服务器如同分片的大脑,保存着集群和数据的描述信息。

因为Mongodb3.4版本后需要配置服务器必须配置为副本集,所以需要给配置服务器配置副本集

首先建立三个空的数据库目录,用于搭建配置服务器的副本集,并分别启动它们,在启动的时候需要加上我们副本集的名称和--configsvr来表示这是一个配置服务器,并分别指定不同的端口。

$ mkdir config0 config1 config2

$ mongod --dbpath config0 --replSet conServer --configsvr --port 27020

$ mongod --dbpath config1 --replSet conServer --configsvr --port 27021

$ mongod --dbpath config2 --replSet conServer --configsvr --port 27020

然后通过mongo随意进入一个副本集成员,并为配置服务器的副本集进行配置:

$ mongo --port 27020 --host localhost

> var conf = {
    _id: 'conServer',
    version: 1,
    members: [
        {
            _id: 0,
            host: 'localhost:27020'
        },
        {
            _id: 1,
            host: 'localhost:27021'
        },
        {
            _id: 2,
            host: 'localhost:27022'
        }
    ]
};

> rs.initiate(conf);

至此配置服务器配置完成。

三、搭建分片服务器

官方建议我们的分片服务区至少在3个或以上才能发挥出更好的性能,我们这里也创建三个分片服务器。

因为分片服务器没有强制要求必须是副本集,所以下面就创建了三个单机分片服务器,但是Mongodb接受分片服务器为副本集。

下面创建三个空数据库目录,然后启动它们,在启动的时候需要加上--shardsvr以表示这是一个分片服务器:

$ mkdir sh0 sh1 sh2

$ mongod --dbpath sh0 --shardsvr --port 27030

$ mongod --dbpath sh1 --shardsvr --port 27031

$ mongod --dbpath sh2 --shardsvr --port 27032

至此分片服务器也搭建完成。

四、搭建路由服务器

mongodb提供了一个路由工具,它会随着我们下载包一起下载,名字为mongosmongos.exe,通过它配置路由功能。

启动路由我们需要加上参数--configdb,它的语法为:

--configdb 配置服务器副本集名称/配置服务器1地址端口,配置服务器1地址端口...

启动路由,并为路由指定一个端口,用于开放给客户端链接:

$ mongos --configdb conServer/localhost:27020,localhost:27021,localhost:27022 --port 27040

至此路由已经搭建完成。

五、配置分片

配置分片服务器

通过mongodb提供的mongo进入到路由服务器中进行配置,把我们开始创建的三个分片服务器通过sh.addShard()方法添加进行,这个方法接受一个字符串里面的格式为host:port

$ mongo --port 27040 --host localhost

> sh.addShard('localhost:27030');
> sh.addShard('localhost:27031');
> sh.addShard('localhost:27032');

可以通过rs.status()方法中返回的shards字段看是否添加成功。

配置片键

到目前为止,分片服务器已经搭建完成,但是目前分片服务器无法正常工作,我们所有的操作都将在随机的一个主分片上操作,这是因为分片服务器不知道怎么进行分片,所以我们还需要配置片键来告诉分片服务器按照什么来分片。

分片是基于数据库集合中的文档的一个键进行分片的,比如选择username键,那么会根据这个键的顺序就行分片,而mongodb会自动平衡分片的数据。

Mongodb要求作为片键的键必须是索引过的,所以我们在建立片键之前需要对键进行索引,建立后片键就是集合中的最重要的索引。

在生产环境中建议先想好数据建构建立索引和片键后开始操作数据,这样会减轻分片服务器的负载。

首先我们在需要进行分片的数据库上开启分片功能,通过sh.enableSharding方法开启。

$ mongo --port 27040 --host localhost

> sh.enableSharding('test');

然后在开启分片的数据库中的test集合插入测试数据,注意此时我们还没有进行配置片键,所以所有的数据操作都在分片服务器随机分配的一个主分片上面进行的。

> for(var i = 0; i < 100; i++){
    db.test.insert({
        username: 'user' + i,
        idNum: i
    })
}

这时候以username为片键,通过sh.shardCollection方法进行建立,它的语法为:

sh.shardCollection(namespace, key, unique, options)

首先给我们要建立的片键建立索引:

> db.test.ensureIndex({'username': 1});

然后建立片键:

> sh.shardCollection('test.test', {username:1});

等待几分钟后,可以通过sh.status方法查看数据分片的情况了,可以从中很清楚的看见哪些数据在哪个分片服务器上面,并且通过explain方法来查看我们查询的过程中哪些分片服务器参与了查询。

六使用MongoDB

下载驱动

打开vs,使用nuget下载驱动

 

下载驱动封装库

打开https://github.com/yswenli/MongoDBOperator/releases下载二次驱动封装库

 

连接配置

 打开app.config或web.config填写mongo连接配置

1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3   <connectionStrings>
4     <add name="MongoServerSettings" connectionString="mongodb://admin:admin@localhost:27017/MongoTests?authSource=admin" />
5   </connectionStrings>
6 </configuration>

测试CS代码

 以下是测试代码: 

 1 /*****************************************************************************************************
 2 * 本代码版权归@wenli所有,All Rights Reserved (C) 2015-2017
 3 *****************************************************************************************************
 4 * CLR版本:4.0.30319.42000
 5 * 唯一标识:63fcdf18-8930-4a86-93ca-f99f5a020844
 6 * 机器名称:WENLI-PC
 7 * 联系人邮箱:wenguoli_520@qq.com
 8 *****************************************************************************************************
 9 * 项目名称:$projectname$
10 * 命名空间:MongoDBOperator.Test
11 * 类名称:Program
12 * 创建时间:2017/7/13 16:00:44
13 * 创建人:wenli
14 * 创建说明:
15 *****************************************************************************************************/
16 
17 using System;
18 using System.Linq;
19 using System.Threading.Tasks;
20 using MongoDBOperator.Interface;
21 using MongoDBOperator.Test.Model;
22 
23 namespace MongoDBOperator.Test
24 {
25     class Program
26     {
27         static void Main(string[] args)
28         {
29             Console.Title = "MongoDBOperator.Test";
30 
31             IOperator<Account> customerOperator = new MongoOperator<Account>();
32 
33 
34             var account = new Account();
35             account.FirstName = "li";
36             account.LastName = "wen";
37             account.Phone = "13800138000";
38             account.Email = "wenguoli_520@qq.com";
39             account.HomeAddress = new Address
40             {
41                 Address1 = "上海",
42                 Address2 = "徐汇",
43                 PostCode = "210001",
44                 City = "上海",
45                 Country = "中国"
46             };
47 
48             Console.WriteLine("Create");
49 
50             customerOperator.Add(account);            
53 
54             Console.WriteLine("Read");
55 
56             var c = customerOperator.Where(b => b.FirstName == "li").FirstOrDefault();
57 
58             Console.WriteLine("Update");
59 
60             c.FirstName = "guo li";
61 
62             customerOperator.Update(c);
63 
64             Console.WriteLine("Delete");
65 
66             customerOperator.Delete(c);
67 
68             customerOperator.DeleteAll();
69 
70             Console.ReadLine();
71 
72         }
73     }
74 }

 

vs调试效果如下:

 

 

 


转载请标明本文来源:http://www.cnblogs.com/yswenli/p/7421909.html 
更多内容欢迎star作者的github:https://github.com/yswenli/MongoDBOperator
如果发现本文有什么问题和任何建议,也随时欢迎交流~