你的位置:首页 > 数据库

[数据库]双十一来了,别让你的mongodb宕机了


 

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

我们项目中会有一个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。

 

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

 

好了,现在大致配置好了,接下来我们用rs.Status()来查看下当前“主,备,仲裁”的分布情况。

 

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

一个很爽的感觉呢???

 

三:使用驱动

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

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

 1     static MongoDBHelper() 2     { 3       var ips = connectionString.Split(';'); 4  5       var servicesList = new List<MongoServerAddress>(); 6  7       foreach (var ip in ips) 8       { 9         var host = ip.Split(':')[0];10         var port = Convert.ToInt32(ip.Split(':')[1]);11 12         servicesList.Add(new MongoServerAddress(host, port));13       }14 15       setting = new MongoClientSettings();16       setting.ReplicaSetName = "datamip";17 18       //集群中的服务器列表19       setting.Servers = servicesList;20     }

 

其中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。

 1 namespace DataMipCRM.Common 2 { 3   public class MongoDBHelper<T> 4   { 5     private static readonly string connectionString = ConfigurationManager.AppSettings["mongodbServerList"]; 6  7     static MongoClientSettings setting = null; 8     MongoServer server = null; 9  10     public string tableName = "person"; 11  12     public string databaseName = "test"; 13  14     static MongoDBHelper() 15     { 16       var ips = connectionString.Split(';'); 17  18       var servicesList = new List<MongoServerAddress>(); 19  20       foreach (var ip in ips) 21       { 22         var host = ip.Split(':')[0]; 23         var port = Convert.ToInt32(ip.Split(':')[1]); 24  25         servicesList.Add(new MongoServerAddress(host, port)); 26       } 27  28       setting = new MongoClientSettings(); 29       setting.ReplicaSetName = "datamip"; 30  31       //集群中的服务器列表 32       setting.Servers = servicesList; 33     } 34  35     public MongoDBHelper(string databaseName, string tableName) 36     { 37       this.databaseName = databaseName; 38       this.tableName = tableName; 39  40       server = new MongoClient(setting).GetServer(); 41     } 42  43     public bool Remove(Expression<Func<T, bool>> func) 44     { 45       try 46       { 47         var database = server.GetDatabase(databaseName); 48  49         var collection = database.GetCollection<T>(tableName); 50  51         var query = Query<T>.Where(func); 52  53         var result = collection.Remove(query); 54  55         return result.Response["ok"].AsInt32 > 0 ? true : false; 56       } 57       catch (Exception ex) 58       { 59         return false; 60       } 61     } 62  63     public bool RemoveAll() 64     { 65       try 66       { 67         var database = server.GetDatabase(databaseName);  //mongodb中的数据库 68  69         var collection = database.GetCollection<T>(tableName); 70  71         var result = collection.RemoveAll(); 72  73         return result.Response["ok"].AsInt32 > 0 ? true : false; 74       } 75       catch (Exception ex) 76       { 77         return false; 78       } 79     } 80  81     #region 单条插入 82     /// <summary> 83     /// 单条插入 84     /// </summary> 85     /// <typeparam name="T"></typeparam> 86     /// <param name="t"></param> 87     public bool Insert(T t) 88     { 89       try 90       { 91         var database = server.GetDatabase(databaseName);  //mongodb中的数据库 92  93         var collection = database.GetCollection<T>(tableName); 94  95         var result = collection.Insert(t); 96         return result.DocumentsAffected > 0; 97       } 98       catch (Exception ex) 99       {100         return false;101       }102     }103     #endregion104 105     #region 单条覆盖,如果不存在插入,如果存在覆盖106     /// <summary>107     /// 单条覆盖,如果不存在插入,如果存在覆盖108     /// </summary>109     /// <typeparam name="T"></typeparam>110     /// <param name="t"></param>111     public bool Save(T t)112     {113       try114       {115         var database = server.GetDatabase(databaseName);  //mongodb中的数据库116 117         var collection = database.GetCollection<T>(tableName);118         var result = collection.Save(t);119         return result.DocumentsAffected > 0;120       }121       catch (Exception ex)122       {123         return false;124       }125     }126     #endregion127 128     #region 批量插入129     /// <summary>130     /// 批量插入131     /// </summary>132     /// <typeparam name="T"></typeparam>133     /// <param name="t"></param>134     public bool Insert(IEnumerable<T> t)135     {136       try137       {138         var database = server.GetDatabase(databaseName);  //mongodb中的数据库139 140         var collection = database.GetCollection<T>(tableName);141 142         collection.InsertBatch(t);143 144         return true;145       }146       catch (Exception ex)147       {148         return false;149       }150     }151     #endregion152 153     #region 批量查询154 155     public List<T> Search(Expression<Func<T, bool>> func, bool forcemaster = false)156     {157       var list = new List<T>();158 159       try160       {161         //是否强制使用 “主服务器”162         if (forcemaster)163         {164           var database = server.GetDatabase(databaseName);  //mongodb中的数据库165 166           var collection = database.GetCollection<T>(tableName);167           list = collection.Find(Query<T>.Where(func)).ToList();168         }169         else170         {171           var database = server.GetDatabase(databaseName);  //mongodb中的数据库172 173           var collection = database.GetCollection<T>(tableName);174 175           list = collection.Find(Query<T>.Where(func)).ToList();176         }177       }178       catch (Exception ex)179       {180         throw;181       }182 183       return list;184     }185 186     #endregion187 188     #region 单条查询189     /// <summary>190     /// 单条查询191     /// </summary>192     public T SearchOne(Expression<Func<T, bool>> func, bool forcemaster = false)193     {194       T t = default(T);195 196       try197       {198         if (forcemaster)199         {200           var database = server.GetDatabase(databaseName);  //mongodb中的数据库201 202           var collection = database.GetCollection<T>(tableName);203 204           t = collection.FindOne(Query<T>.Where(func));205         }206         else207         {208           var database = server.GetDatabase(databaseName);  //mongodb中的数据库209 210           var collection = database.GetCollection<T>(tableName);211 212           t = collection.FindOne(Query<T>.Where(func));213         }214 215         return t;216       }217       catch (Exception ex)218       {219         return t;220       }221     }222     #endregion223 224     /// <summary>225     /// 查询所有数据226     /// </summary>227     /// <returns></returns>228     public List<T> SearchAll()229     {230       var list = new List<T>();231 232       try233       {234         var database = server.GetDatabase(databaseName);  //mongodb中的数据库235 236         var collection = database.GetCollection<T>(tableName);237 238         list = collection.FindAll().ToList();239 240         return list;241       }242       catch (Exception ex)243       {244         return list;245       }246     }247   }248 }

View Code

 

四:测试一下

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

 1 namespace ConsoleApplication2 2 { 3   class Program 4   { 5     static void Main(string[] args) 6     { 7       MongoDBHelper<MongodbCustomerModel> helper = new MongoDBHelper<MongodbCustomerModel>("mydb", "test"); 8  9       helper.Save(new MongodbCustomerModel()10       {11         SendLastTime = DateTime.Now,12         ShopID = 113       });14     }15   }16 17   public class MongodbCustomerModel18   {19     public ObjectId _id { get; set; }20 21     public int ShopID { get; set; }22 23     public DateTime SendLastTime { get; set; }24   }25 }

 

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

 

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

 

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

 

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

 

--文件下载--