好久没过来吹牛了,前段时间一直赶项目,没有时间来更新博客,项目也终于赶完了,接下来就要面临双十一这场惊心动魄的处女秀考验,

我们项目中会有一个wcf集群,而集群地址则放在mongodb中,所以mongodb的核心地位可想而知,如果mongodb挂掉,整个项目也就陷入

瘫痪,想让mongodb不宕机,最简单的方法就是要做双机热备,跟传统的关系型数据库的双机热备模式一样,一个主服务器,一个备份服务器,

一个仲裁服务器。如果热备集群中的主服务器宕掉,会有仲裁服务器参与投票来选出一台作为主服务器,我想这个大家都比较清楚,下面我们来

实战一下,最后会奉献源代码。

一:搭建mongodb热备集群

1. 准备工作

  为了做到最简化搭建,我就做一个主,一个备,一个仲裁就好了,然后最简化配置信息都放在mongodb.conf文件中,如下图:

从上图中可以看到,三个mongodb,我建立了对应的三个文件夹来存放对应的三个db,其中“主服务器”的端口为27000,“备服务器“的端口为

27001,”仲裁服务器“端口为27002。 具体mongodb.conf内容如下:

2. 开启 “主服务器” 【27000】

3.  开启 “备服务器” 【27001】

4.  开启 “仲裁服务器” 【27002】

现在三台服务器都开启起来了,细心的你会发现,三个控制台都有这么一段英文单词” replSet info you may need to run replSetInitiate“。。。

既然都这么说了,我现在就去run这个func。

db.runCommand({
"replSetInitiate":{
"_id":"datamip",
"members":[
{
"_id":,
"host":"127.0.0.1:27000"
},
{
"_id":,
"host":"127.0.0.1:27001"
}
]
}
}) 

配置完了之后,然后我们把“仲裁服务器【27002】”加入到“datamip”这个双机热备分集群中。

rs.addArb( { host: "127.0.0.1:27002"} )

这个命令可以参考下官网的介绍:https://docs.mongodb.com/manual/reference/command/replSetInitiate/   好了,现在大致配置好了,接下

来我们用rs.Status()来查看下当前“主,备,仲裁”的分布情况。

从图中你应该看到了【27000】成为了主服务器,【27001】成为了备服务器,【27002】成为了仲裁服务器,到目前为止,搭建完成,是不是有

一个很爽的感觉呢???

三:使用驱动

  既然mongodb的双机热备已经做好了,我们驱动也必须支持,这样我们才能够嗨,对伐???其实在配置中使用也很简单,里面有一个

MongoClientSettings,你需要配置一下”ReplicaSetName“和”Servers“列表即可,核心代码如下:

         static MongoDBHelper()
{
var ips = connectionString.Split(';'); var servicesList = new List<MongoServerAddress>(); foreach (var ip in ips)
{
var host = ip.Split(':')[];
var port = Convert.ToInt32(ip.Split(':')[]); servicesList.Add(new MongoServerAddress(host, port));
} setting = new MongoClientSettings();
setting.ReplicaSetName = "datamip"; //集群中的服务器列表
setting.Servers = servicesList;
}

其中ips的信息是配置在app.config中。

 <appSettings>
<add key="mongodbServerList" value="127.0.0.1:27000;127.0.0.1:27001;127.0.0.1:27002"/>
</appSettings>

然后我简单的封装了下mongodb。

 namespace DataMipCRM.Common
{
public class MongoDBHelper<T>
{
private static readonly string connectionString = ConfigurationManager.AppSettings["mongodbServerList"]; static MongoClientSettings setting = null;
MongoServer server = null; public string tableName = "person"; public string databaseName = "test"; static MongoDBHelper()
{
var ips = connectionString.Split(';'); var servicesList = new List<MongoServerAddress>(); foreach (var ip in ips)
{
var host = ip.Split(':')[];
var port = Convert.ToInt32(ip.Split(':')[]); servicesList.Add(new MongoServerAddress(host, port));
} setting = new MongoClientSettings();
setting.ReplicaSetName = "datamip"; //集群中的服务器列表
setting.Servers = servicesList;
} public MongoDBHelper(string databaseName, string tableName)
{
this.databaseName = databaseName;
this.tableName = tableName; server = new MongoClient(setting).GetServer();
} public bool Remove(Expression<Func<T, bool>> func)
{
try
{
var database = server.GetDatabase(databaseName); var collection = database.GetCollection<T>(tableName); var query = Query<T>.Where(func); var result = collection.Remove(query); return result.Response["ok"].AsInt32 > ? true : false;
}
catch (Exception ex)
{
return false;
}
} public bool RemoveAll()
{
try
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); var result = collection.RemoveAll(); return result.Response["ok"].AsInt32 > ? true : false;
}
catch (Exception ex)
{
return false;
}
} #region 单条插入
/// <summary>
/// 单条插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
public bool Insert(T t)
{
try
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); var result = collection.Insert(t);
return result.DocumentsAffected > ;
}
catch (Exception ex)
{
return false;
}
}
#endregion #region 单条覆盖,如果不存在插入,如果存在覆盖
/// <summary>
/// 单条覆盖,如果不存在插入,如果存在覆盖
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
public bool Save(T t)
{
try
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName);
var result = collection.Save(t);
return result.DocumentsAffected > ;
}
catch (Exception ex)
{
return false;
}
}
#endregion #region 批量插入
/// <summary>
/// 批量插入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
public bool Insert(IEnumerable<T> t)
{
try
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); collection.InsertBatch(t); return true;
}
catch (Exception ex)
{
return false;
}
}
#endregion #region 批量查询 public List<T> Search(Expression<Func<T, bool>> func, bool forcemaster = false)
{
var list = new List<T>(); try
{
//是否强制使用 “主服务器”
if (forcemaster)
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName);
list = collection.Find(Query<T>.Where(func)).ToList();
}
else
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); list = collection.Find(Query<T>.Where(func)).ToList();
}
}
catch (Exception ex)
{
throw;
} return list;
} #endregion #region 单条查询
/// <summary>
/// 单条查询
/// </summary>
public T SearchOne(Expression<Func<T, bool>> func, bool forcemaster = false)
{
T t = default(T); try
{
if (forcemaster)
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); t = collection.FindOne(Query<T>.Where(func));
}
else
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); t = collection.FindOne(Query<T>.Where(func));
} return t;
}
catch (Exception ex)
{
return t;
}
}
#endregion /// <summary>
/// 查询所有数据
/// </summary>
/// <returns></returns>
public List<T> SearchAll()
{
var list = new List<T>(); try
{
var database = server.GetDatabase(databaseName); //mongodb中的数据库 var collection = database.GetCollection<T>(tableName); list = collection.FindAll().ToList(); return list;
}
catch (Exception ex)
{
return list;
}
}
}
}

四:测试一下

1. 首先向mongodb中插入一条记录,dbname=mydb, tablename=test,插入后我们用mongodUVE看一下数据:

 namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
MongoDBHelper<MongodbCustomerModel> helper = new MongoDBHelper<MongodbCustomerModel>("mydb", "test"); helper.Save(new MongodbCustomerModel()
{
SendLastTime = DateTime.Now,
ShopID =
});
}
} public class MongodbCustomerModel
{
public ObjectId _id { get; set; } public int ShopID { get; set; } public DateTime SendLastTime { get; set; }
}
}

2. 然后我把【27000】 这个primary关闭掉,通过rs.Status看看“主备情况”。

3. 接下来,我们继续用mongodbHelper执行一下search,看是否能捞取到数据,如果可以,说明一台机器挂了没关系,这个“主备集群”还是活的。

是不是很牛逼的感觉,虽然挂了一台,我的客户端程序还是可以继续从mognodb中获取到刚才插入的数据,好了,大概就说这么多,洗洗睡了,

最后祝顶着双十一压力的兄弟们,一路平安。

--文件下载--

双十一来了,别让你的mongodb宕机了的更多相关文章

  1. mongodb副本集中其中一个节点宕机无法重启的问题

    2-8日我还在家中的时候,被告知mongodb副本集中其中一个从节点因未知原因宕机,然后暂时负责代管的同事无论如何就是启动不起来. 当时mongodb的日志信息是这样的: 实际上这里这么长一串最重要的 ...

  2. MongoDb 本机删除密码的方法

    Terminal Inflection LINUX ESOTERICA, FIXES AND RANTS About Errors Resolved Linux Recommended Books W ...

  3. MongoDB一次节点宕机引发的思考(源码剖析)

    目录 简介 日志分析 副本集 如何实现 Failover 心跳的实现 electionTimeout 定时器 业务影响评估 参考链接 声明:本文同步发表于 MongoDB 中文社区,传送门: http ...

  4. MongoDB一次节点宕机引发的思考(源码剖析)【华为云分享】

    目录 简介 日志分析 副本集 如何实现 Failover 心跳的实现 electionTimeout 定时器 业务影响评估 参考链接 声明:本文同步发表于 MongoDB 中文社区,传送门:http: ...

  5. 8天学通MongoDB

    随笔分类 - MongoDB 双十一来了,别让你的mongodb宕机了 摘要: 好久没过来吹牛了,前段时间一直赶项目,没有时间来更新博客,项目也终于赶完了,接下来就要面临双十一这场惊心动魄的处女秀考验 ...

  6. MongoDB 那些坑(转)

    MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒.但是薄荷 ...

  7. MongoDB中的一些坑( 2.4.10 版本)

    http://www.jb51.net/article/62654.htm 1.MongoDB 数据库级锁 MongoDB的锁机制和一般关系数据库如 MySQL(InnoDB), Oracle 有很大 ...

  8. MongoDB 那些坑

    MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒.但是薄荷 ...

  9. MongoDB中的一些坑(最好不要用)

    MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒.但是薄荷 ...

随机推荐

  1. 修复 XE8 Win 平台 Firemonkey Memo 卷动后会重叠的问题

    问题:XE8 Firemonkey 在 Windows 平台 Memo 卷动时,在第 1 , 2 行会产生重叠现象. 更新:XE8 update 1 已经修复这个问题,无需再使用下面方法. 修改前: ...

  2. 泛函编程(3)-认识Scala和泛函编程

    接着昨天的文章,再示范一个稍微复杂一点的尾递归tail recursion例子:计算第n个Fibonacci数.Fibonacci数第一.第二个数值分别是0,1,按顺序后面的数值是前面两个数的加合.例 ...

  3. [moka同学笔记]Yii2 数据操作Query Builder 2

    Query Builder $rows = (new \yii\db\Query()) ->select(['dyn_id', 'dyn_name']) ->from('zs_dynast ...

  4. get/post时中文乱码问题的解决办法

    1.文章1 最近遇到一个问题:用get方法传递中文有问题,用post没有问题. 问题简单的描述是这样的: <a href="userGroup.jsp?userGroupName=&l ...

  5. Android 手机卫士4--设置中心显示

    1,自定义属性 SettingActivity.java package com.itheima.mobilesafe74.activity; import com.itheima.mobilesaf ...

  6. Slideout.js – 触摸滑出式 Web App 导航菜单

    Slideout.js 是为您的移动 Web 应用开发的触摸滑出式的导航菜单.它没有依赖,自由搭配简单的标记,支持原生的滚动,您可以轻松地定制它.它支持不同的 CSS3 转换和过渡.最重要的是,它只是 ...

  7. ZedGraph饼图---傻瓜版

    GraphPane pGraphPane=this.zedGraphControl1.GraphPane;//调用饼图类 pGraphPane.Title.Text = "重金属含量分析图& ...

  8. sharepoint2010问卷调查(2)-实现问卷的图片调查(采用自定义字段类型)

    1. 首先建立个图片库上传图片 并建立文件夹1和2,1下有1.1文件夹,2下2.1文件夹,2.1下有文件夹2.1.1. 在1文件夹下放如下图片: 2.建立自定义字段类型,如下图: 3.部署后建立栏目的 ...

  9. 见见面、聊聊天 - 5月22日晚7点Meetup,三里屯绿树旁酒吧,畅谈云技术和应用

    总是邮件.QQ什么的线上聊,让我们见面吧,不怕见光死,呵呵.   我和同事会先抛砖引玉,给大家介绍一下Autodesk几款最新的云技术和解决方案,然后大家就可畅所欲言,自由交流.来自五湖四海的人,为了 ...

  10. 高性能JS笔记3——DOM编程

    一.访问与修改DOM DOM和JS 相当于两个岛屿,访问操作的次数越多,要交的过路费越多,对性能产生很大影响. 减少访问DOM的次数,把运算尽量留在JS端操作. 二.innerHTML 对比 DOM ...