【MongoDb入門】別讓你的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”這個雙機熱備分叢集中。
這個命令可以參考下官網的介紹:https://docs.mongodb.com/manual/reference/command/replSetInitiate/ 好了,現在大致配置好了,接下
來我們用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 #endregion
104
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 try
114 {
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 #endregion
127
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 try
137 {
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 #endregion
152
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 try
160 {
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 else
170 {
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 #endregion
187
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 try
197 {
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 else
207 {
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 #endregion
223
224 /// <summary>
225 /// 查詢所有資料
226 /// </summary>
227 /// <returns></returns>
228 public List<T> SearchAll()
229 {
230 var list = new List<T>();
231
232 try
233 {
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 }
四:測試一下
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 = 1
13 });
14 }
15 }
16
17 public class MongodbCustomerModel
18 {
19 public ObjectId _id { get; set; }
20
21 public int ShopID { get; set; }
22
23 public DateTime SendLastTime { get; set; }
24 }
25 }
2. 然後我把【27000】 這個primary關閉掉,通過rs.Status看看“主備情況”。
3. 接下來,我們繼續用mongodbHelper執行一下search,看是否能撈取到資料,如果可以,說明一臺機器掛了沒關係,這個“主備叢集”還是活的。
是不是很牛逼的感覺,雖然掛了一臺,我的客戶端程式還是可以繼續從mognodb中獲取到剛才插入的資料,好了,大概就說這麼多,洗洗睡了,
歡迎關注公眾號: