• MongoDB 副本集和C#交互,简单测试


    MongoDB 副本集和C#交互,简单测试

    primary节点宕机:

     模拟primary节点宕机的情况,这时查看监控:

    可以看到37018已经成了primary节点。主界面宕机导致了整个集群发生一次election,实现了failover。等37017恢复了会自动成为secondary节点:

    所有secondary节点宕机

    当所有secondary宕机,或者副本集中只剩下一台机器的时候,那么剩下的机器只能成为secondary节点,也就意味着整个集群智能进行读操作而不能进行写操作

    当集群从故障中恢复过来后,仍然的primary节点仍然是primary节点。

    注意:当某个节点宕机后重新启动该节点会有一段的时间(时间长短视集群的数据量和宕机时间而定)导致整个集群中所有节点都成为secondary而无法进行写操作(如果应用程序没有设置相应的ReadReference也可能不能进行读取操作)。

    因此官方推荐的最小的副本集也应该具备一个primary节点和两个secondary节点。两个节点的副本集不具备真正的故障转移能力。

    应用程序访问副本集

    副本集搭建好了,基本的故障转移能力也验证过了,那么应用程序如何访问呢?下面分别介绍下C#和Java驱动如何访问mongodb副本集。

    C#:

    C#驱动下载地址http://driver-downloads.mongodb.org/dotnet/index.html,我使用的最新版本1.8.2。

    下面是访问副本集基本的代码:

    复制代码
     
    引用命名空间: MongoDB.Driver.dll
                  MongoDB.Bson.dll
    MongoClientSettings set = new MongoClientSettings();
    List<MongoServerAddress> servers = new List<MongoServerAddress>();
    servers.Add(new MongoServerAddress("192.168.129.129", 37017));
    servers.Add(new MongoServerAddress("192.168.129.129", 37018));
    servers.Add(new MongoServerAddress("192.168.129.129", 37019));
    set.Servers = servers;
    
    //设置副本集名称
    set.ReplicaSetName = "rs0";
    //设置超时时间为3秒
    set.ConnectTimeout = new TimeSpan(0, 0, 0, 3, 0);
    
    
    MongoClient client = new MongoClient(set);
    MongoServer server = client.GetServer();
    MongoDatabase db = server.GetDatabase("test");
    MongoCollection coll = db.GetCollection("test");
    
    //插入
    BsonDocument bd = new BsonDocument();
    bd.Add("name", "zhanjindong");
    bd.Add("age", 23);
    bd.Add("sex", "男D");
    
    coll.Insert(bd);
    
    //读取
    QueryDocument qd = new QueryDocument();
    qd.Add("name", "zhanjindong");
    qd.Add("age", 23);
    qd.Add("sex", "男D");
    
    BsonDocument rd = coll.FindOneAs<BsonDocument>(qd);
    
    Console.WriteLine(rd.ToString());
    复制代码

    当kill掉一个节点(secondary或primary)的时候,读取和写入的操作都是正常的,说明副本集的failover起作用了。但kill模拟两个节点宕机的时候,发现上面的代码在读取的时候会报下面的错误:

    这是因为默认的C#驱动的ReadPreference是Primary,也就是说读写操作都是在主节点上的,那么当集群中只剩下一个节点的时候,按照前面所说该节点一定是secondary节点,这样读取操作也是没法进行的(通过mongo shell当然是可以的)。解决方法就是设置驱动的ReadPreferenceMode:

    set.ReadPreference = new ReadPreference(ReadPreferenceMode.PrimaryPreferred);

    将ReadPreferenceMode设置成Secondary或SecondaryPreferred。后面读写分离一节对ReadPreference会有详细的说明。

    ReadPreferenceMode参数:

    primary:默认,只从主节点上进行读取操作;

    primaryPreferred:在绝大部分的情形都是从主节点上读取数据的,只有当主节点不可用的时候,比如在进行failover的10秒或更长的时间内会从secondary节点读取数据。

    警告:2.2版本之前的MongoDB对Read Preference支持的还不完全,如果客户端驱动采用primaryPreferred实际上读取操作都会被路由到secondary节点。

    secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。

    secondaryPreferred:优先从secondary节点进行读取操作;

    nearest:既有可能从primary,也有可能从secondary节点读取,这个决策是通过一个叫member selection过程处理的。

    Java:

    Java驱动下载地址:http://central.maven.org/maven2/org/mongodb/mongo-java-driver/

    我用的是最新版本mongo-java-driver-2.11.2.jar。

    下面是Java访问MongoDB副本集的基本代码:

    复制代码
    List<ServerAddress> addresses = new ArrayList<ServerAddress>();
    ServerAddress address1 = new ServerAddress("192.168.129.129", 37017);
    ServerAddress address2 = new ServerAddress("192.168.129.129", 37018);
    ServerAddress address3 = new ServerAddress("192.168.129.129", 37018);
    addresses.add(address1);
    addresses.add(address2);
    addresses.add(address3);
    
    MongoClient client = new MongoClient(addresses);
    DB db = client.getDB("test");
    DBCollection coll = db.getCollection("test");
    
    // 插入
    BasicDBObject object = new BasicDBObject();
    object.append("name", "zhanjindong");
    object.append("age", 23);
    object.append("sex", "男");
    
    coll.insert(object);
    
    BasicDBObject qobj = new BasicDBObject();
    qobj.append("name", "zhanjindong");
    qobj.append("age", 23);
    qobj.append("sex", "男");
    
    DBObject robj = coll.findOne(qobj);
    
    System.out.println(robj.toString());
    复制代码

    和C#一样如果想从secondary节点进行读取操作也是需要设置ReadPreference:

    ReadPreference preference = ReadPreference.secondary();
    DBObject robj = coll.findOne(qobj, qobj, preference);

    不同的是Java驱动发现副本集中某个成员连接不了会发出警告信息:

    而且发现如果读取不到的话Java驱动会进行不停的重试。

    :设置驱动的ReadReference也可以通过MongoDB连接字符串配置:mongodb://example1.com,example2.com,example3.com/?readPreference=secondary。通过连接字符串指定的read preference是针对整个连接。

  • 相关阅读:
    第5章 css与背景相关的样式background
    第4章 css文字text与字体font-face
    第3章 css属性color的RGBA值
    第2章 css边框属性
    第1章 初识CSS3
    CSS单行、多行文本溢出显示省略号(……)解决方案
    Access-Control-Allow-Origin实现跨域访问 跨域
    Mysql主数据库+备份数据库部署教程
    PHP 数据安全问题总结
    PHP redis 批量操作
  • 原文地址:https://www.cnblogs.com/wang726zq/p/6797745.html
Copyright © 2020-2023  润新知