<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 主從復制 1.這種架構有如下的好處: - 數據備份 - 數據恢復 - 讀寫分離 <!--more--> 2.下面我們就一一實踐 實際應用中我們肯定是多服務器部署,限于自己懶的裝虛擬機,就在一臺機器上實踐了。 第一步:我們把mongodb文件夾放在D盤和E盤,模擬放在多服務器上。 第二步:啟動D盤上的mongodb,把該數據庫指定為主數據庫,其實命令很簡單: ``` >mongodb --dbpath='XXX' --master ``` 端口還是默認的27017. 開啟主服務器: ``` D:\Projects\mongodb\bin>mongod --dbpath=D:\Projects\mongodb\db --master 2015-07-02T22:53:13.738+0800 I CONTROL [initandlisten] options: { master: true, storage: { dbPath: "D:\Projects\mongodb\db" } } 2015-07-02T22:53:13.814+0800 I REPL [initandlisten] ****** 2015-07-02T22:53:13.814+0800 I REPL [initandlisten] creating replication oplog of size: 50MB... 2015-07-02T22:53:13.921+0800 I REPL [initandlisten] ****** 2015-07-02T22:53:13.924+0800 I NETWORK [initandlisten] waiting for connections on port 27017 ``` 第三步:同樣的方式啟動E盤上的mongodb,指定該數據庫為從屬數據庫,命令也很簡單,當然我們要換一個端口,比如:8888。 source 表示主數據庫的地址。 ``` >mongod --dbpath=xxxx --port=8888 --slave --source=127.0.0.1:27017 ``` 開啟從服務器: ``` D:\Projects\mongodb2\bin>mongod --dbpath=D:\Projects\mongodb2\db --slave --port 8888 --source=17.0.0.1:27017 ``` 報錯了: ``` 2015-07-02T23:07:44.152+0800 I REPL [replslave] repl: --source 127.0.0.1:2222 != 17.0.0.1:27017 from local.sources collection ``` 這是由于之前誤操作,127.0.0.1:2222 != 17.0.0.1:27017,IP地址錯了。可以刪掉D:\Projects\mongodb2\db的db文件夾新建。嘗試修改主服務器的端口。 一般還可能有下面兩個錯誤: (1)D:\Projects\mongodb2\db的db文件夾不存在導致的錯誤;創建該文件夾即可。 (2)D:\Projects\mongodb2\db下存在mongod.lock文件。刪掉即可。 重新來: 開主服務器: ``` D:\Projects\mongodb\bin>mongod --dbpath=D:\Projects\mongodb\db --master --port 2222 ``` 提示: ``` 2015-07-02T23:10:04.004+0800 I CONTROL [initandlisten] options: { master: true, net: { port: 2222 }, storage: { dbPath: "D:\Proje cts\mongodb\db" } } 2015-07-02T23:10:04.063+0800 I NETWORK [initandlisten] waiting for connections on port 2222 ``` 成功。 開啟從服務器: ``` D:\Projects\mongodb2\bin>mongod --dbpath=D:\Projects\mongodb2\db --slave --port 3333 --source=127.0.0.1:2222 ``` 提示: ``` 2015-07-02T23:26:44.602+0800 I CONTROL [initandlisten] allocator: tcmalloc 2015-07-02T23:26:44.603+0800 I CONTROL [initandlisten] options: { net: { port: 3333 }, slave: true, source: "127.0.0.1:2222", sto rage: { dbPath: "D:\Projects\mongodb2\db" } } 2015-07-02T23:26:44.621+0800 I NETWORK [initandlisten] waiting for connections on port 3333 2015-07-02T23:26:53.106+0800 I REPL [replslave] repl: sleep 1 sec before next pass 2015-07-02T23:26:54.109+0800 I REPL [replslave] repl: syncing from host:127.0.0.1:2222 2015-07-02T23:27:03.104+0800 I REPL [replslave] repl: applied 1 operations 2015-07-02T23:27:03.106+0800 I REPL [replslave] repl: end sync_pullOpLog syncedTo: Jul 02 23:26:58 55955842:1 ``` 成功。從中我們發現了一條:“applied 1 operations"這樣的語句,并且發生的時間相隔10s,也就說明從屬數據庫每10s就向主數據庫同步數據,同步依據也就是尋找主數據庫的”OpLog“日志,可以在圖中紅色區域內發現”sync_pullOpLog“字樣。 接下來,我們可以打開客戶端,連接從服務器進行測試了。再打開一個命令行窗口: ``` D:\Projects\mongodb2\bin>mongo 127.0.0.1:3333 connecting to: 127.0.0.1:3333/test > db.user.find() { "_id" : ObjectId("55935f703cb05382291e9132"), "name" : "yjc", "age" : 22 } { "_id" : ObjectId("559360ae3cb05382291e9134"), "name" : "hxc", "birthday" : "1989-2-2" } { "_id" : ObjectId("559360bd3cb05382291e9135"), "name" : "jack", "birthday" : "1989-3-2" } { "_id" : ObjectId("559360d13cb05382291e9136"), "name" : "joe", "birthday" : "1989-2-22" } { "_id" : ObjectId("559360df3cb05382291e9137"), "name" : "mary", "birthday" : "1989-3-12" } { "_id" : ObjectId("559360e93cb05382291e9138"), "name" : "jr", "birthday" : "1989-3-2" } > db.person.find() { "_id" : ObjectId("558fd39d02d9b5bcf004aaf5"), "name" : "yjc", "age" : 5, "address" : { "city" : "beijing" } } { "_id" : ObjectId("5590ac85c8e4762462ebbab2"), "name" : "liyi", "age" : 20, "address" : { "province" : "hubei", "city" : "wuhan" }, "favourite" : [ "music", "movie" ] } { "_id" : ObjectId("5590adecc8e4762462ebbab3"), "name" : "lier", "age" : 10, "adress" : { "province" : "hubei", "city" : "yichang" } } { "_id" : ObjectId("5590b92aeb60c2633d9cfa24"), "name" : "yjc2", "age" : 25 } { "_id" : ObjectId("55926102f431047603d95187"), "name" : "yjc", "age" : 22 } ``` 好家伙,數據全都有了!數據已經同步更新成功! 3.如果我還想增加一臺從屬數據庫,但是我不想在啟動時就指定,而是后期指定,那么mongodb可否做的到呢?答案肯定是可以的。我們的主或者從屬數據庫中都有一個叫做local的集合,主要是用于存放內部復制信息。 主服務器不用關,我們可以再新增一臺或者關掉從服務器,重新開啟從服務器: ``` D:\Projects\mongodb2\bin>mongod --dbpath=D:\Projects\mongodb2\db --slave --port 3333 2015-07-03T09:50:18.777+0800 I CONTROL [initandlisten] allocator: tcmalloc 2015-07-03T09:50:18.777+0800 I CONTROL [initandlisten] options: { net: { port: 3333 }, slave: true, storage: { dbPath: "D:\Projec ts\mongodb2\db" } } 2015-07-03T09:50:18.780+0800 I INDEX [initandlisten] allocating new ns file D:\Projects\mongodb2\db\local.ns, filling with zero es... 2015-07-03T09:50:19.129+0800 I STORAGE [FileAllocator] allocating new datafile D:\Projects\mongodb2\db\local.0, filling with zero es... 2015-07-03T09:50:19.130+0800 I STORAGE [FileAllocator] creating directory D:\Projects\mongodb2\db\_tmp 2015-07-03T09:50:19.542+0800 I STORAGE [FileAllocator] done allocating datafile D:\Projects\mongodb2\db\local.0, size: 64MB, too k 0.406 secs 2015-07-03T09:50:19.695+0800 I NETWORK [initandlisten] waiting for connections on port 3333 2015-07-03T09:50:20.692+0800 I REPL [replslave] no source given, add a master to local.sources to start replication 2015-07-03T09:50:20.692+0800 I REPL [replslave] repl: sleep 20 sec before next pass ``` 看上面的log,提示沒有主數據庫,沒關系,某一天我們良心發現,給他后期補貼一下,哈哈,再開一個cmd窗口,打開客戶端,語句也就是在sources中add一個host地址: ``` D:\Projects\mongodb2\bin>mongo 127.0.0.1:3333 connecting to: 127.0.0.1:3333/test ``` 使用local集合 ``` > use local switched to db local ``` 從主服務器127.0.0.1:2222復制數據 ``` > db.sources.insert({"host":"127.0.0.1:2222"}) WriteResult({ "nInserted" : 1 }) > db.sources.find() { "_id" : ObjectId("5595ecd1143aa60c5492e195"), "host" : "127.0.0.1:2222", "source" : "main", "syncedTo" : Timestamp(1435888931, 1) } ``` 使用test集合 ``` > use test; switched to db test > db.user.find() { "_id" : ObjectId("55935f703cb05382291e9132"), "name" : "yjc", "age" : 22 } { "_id" : ObjectId("559360ae3cb05382291e9134"), "name" : "hxc", "birthday" : "1989-2-2" } { "_id" : ObjectId("559360bd3cb05382291e9135"), "name" : "jack", "birthday" : "1989-3-2" } { "_id" : ObjectId("559360d13cb05382291e9136"), "name" : "joe", "birthday" : "1989-2-22" } { "_id" : ObjectId("559360df3cb05382291e9137"), "name" : "mary", "birthday" : "1989-3-12" } { "_id" : ObjectId("559360e93cb05382291e9138"), "name" : "jr", "birthday" : "1989-3-2" } ``` 最后發現數據也同步到127.0.0.1:3333這臺后期同步的從屬數據庫中.... 客戶端插入一條數據試試: ``` > db.user.insert({"name":"mary", "age": 23}) WriteResult({ "writeError" : { "code" : undefined, "errmsg" : "not master" } }) ``` 切換連接到主服務器就可以新增了: ``` D:\Projects\mongodb2\bin>mongo 127.0.0.1:2222 > db.user.insert({"name":"mary", "age": 23}) WriteResult({ "nInserted" : 1 }) ``` 再連接到從服務器發現數據也同步了,即不用重新去追加數據。 4.讀寫分離 這種手段在大一點的架構中都有實現,在mongodb中其實很簡單,在默認的情況下,從屬數據庫不支持數據的讀取,但是沒關系,在驅動中給我們提供了一個叫做“slaveOkay"(?)來讓我們可以顯示的讀取從屬數據庫來減輕主數據庫的性能壓力。 主從復制的選項: ``` --only 在從節點上指定只復制特定的某個數據庫(默認是復制所有數據庫) --slavedelay 用在從節點上,當應用主節點的操作時,從節點增加延時復制(單位秒).這樣就能輕松設置延時從節點,這種節點對用戶 無意中刪除重要文檔或者插入垃圾數據等有防護作用,這些不良操作都會被復制到所有的從節點上,通過延時執行操作, 可以有個恢復的時間差. --fastsync 以主節點的數據快照為基礎啟動從節點.如果數據目錄一開始是主節點的數據快照,從節點用這個選項啟動要比 做完整的同步快的多. --autoresync 如果從節點與主節點不同步了,則自動重新同步 --oplogsize 主節點oplog的大小(單位MB) ``` ## 副本集 這個也是很牛X的主從集群,不過跟上面的集群還是有兩點區別的。 1 該集群沒有特定的主數據庫。 2 如果哪個主數據庫宕機了,集群中就會推選出一個從屬數據庫作為主數據庫頂上,這就具備了自動故障恢復功能。 好,我們現在就來試一下,首先把所有的cmd窗口關掉重新來,清掉db下的所有文件(不清除后續操作可能會報錯)。 第一步: 既然我們要建立集群,就得取個集群名字,這里就取名shopex, --replSet表示讓服務器知道shopex下還有其他數據庫, 這里就把D盤里面的mongodb程序打開,端口為2222。指定端口為3333是shopex集群下的另一個數據庫服務器。 ``` D:\Projects\mongodb\bin>mongod --dbpath=D:\Projects\mongodb\db --port 2222 --replSet shopex/127.0.0.1:3333 2015-07-04T09:05:37.568+0800 I CONTROL [initandlisten] allocator: tcmalloc 2015-07-04T09:05:37.568+0800 I CONTROL [initandlisten] options: { net: { port: 2222 }, replication: { replSet: "shopex/127.0.0.1: 3333" }, storage: { dbPath: "D:\Projects\mongodb\db" } } 2015-07-04T09:05:37.601+0800 I NETWORK [initandlisten] waiting for connections on port 2222 ``` 第二步: 既然上面說3333是另一個數據庫服務器,不要急,現在就來開,這里把另外一個目錄mongodb2的mongodb程序打開。 ``` mongod --dbpath=D:\Projects\mongodb2\db --port 3333 --replSet shopex/127.0.0.1:2222 2015-07-04T09:08:11.815+0800 I CONTROL [initandlisten] allocator: tcmalloc 2015-07-04T09:08:11.815+0800 I CONTROL [initandlisten] options: { net: { port: 3333 }, replication: { replSet: "shopex/127.0.0.1: 2222" }, storage: { dbPath: "D:\Projects\mongodb2\db" } } ingDocument Did not find replica set configuration document in local.system.replset 2015-07-04T09:08:12.905+0800 I NETWORK [initandlisten] waiting for connections on port 3333 ``` 第三步: ok,看看上面的日志,似乎我們還沒有做完,是的,log信息告訴我們要初始化一下“副本集“,既然日志這么說,那我也就這么做,隨便連接一下哪個服務器都行,不過一定要進入admin集合。 ``` D:\Projects\mongodb2\bin>mongo 127.0.0.1:2222/admin db.runCommand({"replSetInitiate":{ "_id":"shopex", "members" :[ { "_id" :1 , "host":"127.0.0.1:2222", }, { "_id" :2 , "host":"127.0.0.1:3333", }, ] }}) ``` 第一次設置報告了一個錯誤: ``` "errmsg" : "'127.0.0.1:3333' has data already, cannot initiate set." ``` 原因是我沒有清除`D:\Projects\mongodb2\`下的db。關閉`D:\Projects\mongodb2\`服務器并刪除db下的文件后重新打開mongodb2服務器,并再次設置初始化:顯示ok。 第四步: 開啟成功后,我們要看看誰才能成為主數據庫服務器,可以看到端口為2222的已經成為主數據庫服務器。 ``` mongodb1---cmd: 2015-07-04T09:16:02.925+0800 I REPL [ReplicationExecutor] replSet election succeeded, assuming primary role 2015-07-04T09:16:02.928+0800 I REPL [ReplicationExecutor] transition to PRIMARY mongodb2---cmd: 2015-07-04T09:16:07.059+0800 I REPL [ReplicationExecutor] transition to RECOVERING 2015-07-04T09:16:07.062+0800 I REPL [ReplicationExecutor] transition to SECONDARY ``` 第五步:我們知道sql server里面有一個叫做仲裁服務器,那么mongodb中也是有的,跟sql server一樣,仲裁只參與投票選舉,這里我們把mongodb3的mongodb作為仲裁服務器,然后指定shopex集群中的任一個服務器端口,這里就指定2222。 ``` mongod --dbpath=D:\Projects\mongodb3\db --port 4444 --replSet shopex/127.0.0.1:2222 ``` 然后我們在admin集合中使用rs.addArb()追加即可。 ``` > rs.addArb("127.0.0.1:4444") { "ok" : 1 } ``` 追加好了之后,我們使用rs.status()來查看下集群中的服務器狀態,圖中我們可以清楚的看到誰是主,還是從,還是仲裁。 ``` shopex:PRIMARY> rs.status() { "set" : "shopex", "date" : ISODate("2015-07-04T01:30:29.593Z"), "myState" : 1, "members" : [ { "_id" : 1, "name" : "127.0.0.1:2222", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1492, "optime" : Timestamp(1435973390, 1), "optimeDate" : ISODate("2015-07-04T01:29:50Z"), "electionTime" : Timestamp(1435972562, 2), "electionDate" : ISODate("2015-07-04T01:16:02Z"), "configVersion" : 2, "self" : true }, { "_id" : 2, "name" : "127.0.0.1:3333", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 870, "optime" : Timestamp(1435973390, 1), "optimeDate" : ISODate("2015-07-04T01:29:50Z"), "lastHeartbeat" : ISODate("2015-07-04T01:30:28.854Z"), "lastHeartbeatRecv" : ISODate("2015-07-04T01:30:29.147Z"), "pingMs" : 0, "syncingTo" : "127.0.0.1:2222", "configVersion" : 2 }, { "_id" : 3, "name" : "127.0.0.1:4444", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 38, "lastHeartbeat" : ISODate("2015-07-04T01:30:28.855Z"), "lastHeartbeatRecv" : ISODate("2015-07-04T01:30:29.175Z"), "pingMs" : 0, "configVersion" : 2 } ], "ok" : 1 } ``` 上面的結果顯示很清楚。 不是說該集群有自動故障恢復嗎?那么我們就可以來試一下,在2222端口的cmd服務器按Ctrl+C來KO掉該服務器,立馬我們發現在3333端口的從屬服務器即可頂上,最后大家也可以再次使用rs.status()來看下集群中服務器的狀態。 其它: 在從服務器是無法查看數據: ``` > use test; switched to db test > db.user.find() Error: error: { "$err" : "not master and slaveOk=false", "code" : 13435 } ``` 切換到主服務器就可以了 ``` shopex:PRIMARY> db.user.find() { "_id" : ObjectId("55935f703cb05382291e9132"), "name" : "yjc", "age" : 22 } { "_id" : ObjectId("559360ae3cb05382291e9134"), "name" : "hxc", "birthday" : "1989-2-2" } { "_id" : ObjectId("559360bd3cb05382291e9135"), "name" : "jack", "birthday" : "1989-3-2" } { "_id" : ObjectId("559360d13cb05382291e9136"), "name" : "joe", "birthday" : "1989-2-22" } { "_id" : ObjectId("559360df3cb05382291e9137"), "name" : "mary", "birthday" : "1989-3-12" } { "_id" : ObjectId("559360e93cb05382291e9138"), "name" : "jr", "birthday" : "1989-3-2" } { "_id" : ObjectId("5595f1500369349a9f73e947"), "name" : "mary", "age" : 23 } shopex:PRIMARY> db.user.insert({"name":"tt"}) WriteResult({ "nInserted" : 1 }) shopex:PRIMARY> ``` 當然也可以使用下rs.slaveOk() 命令,使其可以查詢數據(還是不能更新之類的) 拓展: rs相關命令 ``` shopex:PRIMARY> rs.help() rs.status() { replSetGetStatus : 1 } checks repl set status rs.initiate() { replSetInitiate : null } initiates set with default settings rs.initiate(cfg) { replSetInitiate : cfg } initiates set with configuration cfg rs.conf() get the current configuration object from local.system.replset rs.reconfig(cfg) updates the configuration of a running replica set with cfg (disconnects) rs.add(hostportstr) add a new member to the set with default attributes (disconnects) rs.add(membercfgobj) add a new member to the set with extra attributes (disconnects) rs.addArb(hostportstr) add a new member which is arbiterOnly:true (disconnects) rs.stepDown([stepdownSecs, catchUpSecs]) step down as primary (disconnects) rs.syncFrom(hostportstr) make a secondary sync from the given member rs.freeze(secs) make a node ineligible to become primary for the time specified rs.remove(hostportstr) remove a host from the replica set (disconnects) rs.slaveOk() allow queries on secondary nodes rs.printReplicationInfo() check oplog size and time range rs.printSlaveReplicationInfo() check replica set members and replication lag db.isMaster() check who is primary reconfiguration helpers disconnect from the database so the shell will display an error, even if the command succeeds. ``` 后記: 有些問題,關掉2222端口的服務器,3333和4444都提示: ``` couldn't connect to server 127.0.0.1:2222(127.0.0.1) ``` 然后再打開2222端口的服務器,現在3333的變成主服務器了。 再關掉3333提示, `couldn't connect to server 127.0.0.1:3333 (127.0.0.1)`,且使用`rs.status()`顯示3333的狀態是 `stateStr" : "(not reachable/healthy)`。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看