mongodb使用docker搭建replicaSet集群與變更監(jiān)聽(tīng)(最新推薦)
在mongodb如果需要啟用變更監(jiān)聽(tīng)功能(watch),mongodb需要在replicaSet或者cluster方式下運(yùn)行。
replicaSet和cluster從部署難度相比,replicaSet要簡(jiǎn)單許多。如果所存儲(chǔ)的數(shù)據(jù)量規(guī)模不算太大的情況下,那么使用replicaSet方式部署mongodb是一個(gè)不錯(cuò)的選擇。
安裝環(huán)境
mongodb版本:mongodb-6.0.5
兩臺(tái)主機(jī):主機(jī)1(192.168.1.11)、主機(jī)2(192.168.1.12)
docker方式mongodb集群安裝
在主機(jī)1和主機(jī)2上安裝好docker,并確保兩臺(tái)主機(jī)能正常通信
目錄與key準(zhǔn)備
在啟動(dòng)mongodb前,先準(zhǔn)備好對(duì)應(yīng)的目錄與訪問(wèn)key
#在所有主機(jī)都創(chuàng)建用于存儲(chǔ)mongodb數(shù)據(jù)的文件夾 mkdir -p ~/mongo-data/{data,key,backup} #設(shè)置key文件,用于在集群機(jī)器間互相訪問(wèn),各主機(jī)的key需要保持一致 cd ~/mongo-data #在某一節(jié)點(diǎn)創(chuàng)建key openssl rand -base64 123 > key/mongo-rs.key sudo chown 999 key/mongo-rs.key #不能是755, 權(quán)限太大不行. sudo chmod 600 key/mongo-rs.key #將key復(fù)制到他節(jié)點(diǎn) scp key/mongo-rs.key root@192.168.1.12:/root/mongo-data/key
以上操作在各主機(jī)中創(chuàng)建了 ~/mongo-data/{data,key,backup} 這3個(gè)目錄,且mongo-rs.key的內(nèi)容一致。
運(yùn)行mongodb
執(zhí)行下列命令,啟動(dòng)mongodb
sudo docker run --name mongo --network=host -p 27017:27017 -v ~/mongo-data/data:/data/db -v ~/mongo-data/backup:/data/backup -v ~/mongo-data/key:/data/key -v /etc/localtime:/etc/localtime -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:6.0.5 --replSet haiyangReplset --auth --keyFile /data/key/mongo-rs.key --bind_ip_all
上面主要將27017端口映射到主機(jī)中,并設(shè)了admin的默認(rèn)密碼為123456。
–replSet為指定開(kāi)啟replicaSet,后面跟的為副本集的名稱。
配置節(jié)點(diǎn)
進(jìn)入某一節(jié)點(diǎn),進(jìn)行集群配置
sudo docker exec -it mongo bash
mongosh
初始化集群前先登錄驗(yàn)證超級(jí)管理員admin
use admin
db.auth(“admin”,“123456”)
再執(zhí)行以下命令進(jìn)行初始化
var config={ _id:"haiyangReplset", members:[ {_id:0,host:"192.168.1.11:27017"}, {_id:1,host:"192.168.1.12:27017"}, ]}; rs.initiate(config)
執(zhí)行成功后,可以看到一個(gè)節(jié)點(diǎn)為主節(jié)點(diǎn),另一個(gè)節(jié)點(diǎn)為從節(jié)點(diǎn)
其他相關(guān)命令
#查看副本集狀態(tài) rs.status() #查看副本集配置 rs.conf() #添加節(jié)點(diǎn) rs.add( { host: "ip:port"} ) #刪除節(jié)點(diǎn) rs.remove('ip:port')
官方客戶端驗(yàn)證
在mongodb安裝好后,再用客戶端連接驗(yàn)證一下。
官方mongodb的客戶端下載地址為:https://www.mongodb.com/try/download/compass
下載完畢后,在客戶端中新建連接。
在本例中,則mongodb的連接地址為:
mongodb://admin:123456@192.168.1.11:27017,192.168.1.12:27017/?authMechanism=DEFAULT&authSource=admin&replicaSet=haiyangReplset
庫(kù)與監(jiān)控信息一目了然~
變更監(jiān)聽(tīng)
對(duì)于mongodb操作的api在mongodb的官網(wǎng)有比較完備的文檔,java的文檔連接為:https://www.mongodb.com/docs/drivers/java/sync/v4.9/
這里試一下mongodb中一個(gè)比較強(qiáng)悍的功能,記錄的變更監(jiān)聽(tīng)。
用這項(xiàng)功能來(lái)做一些審計(jì)的場(chǎng)景則會(huì)非常方便。
官方鏈接為:https://www.mongodb.com/docs/drivers/java/sync/v4.9/usage-examples/watch/
這里以java客戶端為例寫(xiě)個(gè)小demo,試一下對(duì)于mongodb中集合的創(chuàng)建及watch功能。
package io.github.puhaiyang; import com.google.common.collect.Lists; import com.mongodb.client.*; import org.apache.commons.lang3.StringUtils; import org.bson.Document; import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Scanner; import java.util.concurrent.CompletableFuture; /** * @author puhaiyang * @since 2023/3/30 20:01 * MongodbWatchTestMain */ public class MongodbWatchTestMain { public static void main(String[] args) throws Exception { String uri = "mongodb://admin:123456@192.168.1.11:27017,192.168.1.12:27017/?replicaSet=haiyangReplset"; MongoClient mongoClient = MongoClients.create(uri); MongoDatabase mongoDatabase = mongoClient.getDatabase("my-test-db"); String myTestCollectionName = "myTestCollection"; //獲取出collection MongoCollection<Document> mongoCollection = initCollection(mongoDatabase, myTestCollectionName); //進(jìn)行watch CompletableFuture.runAsync(() -> { while (true) { List<Bson> pipeline = Lists.newArrayList( Aggregates.match(Filters.in("ns.coll", myTestCollectionName)), Aggregates.match(Filters.in("operationType", Arrays.asList("insert", "update", "replace", "delete"))) ); ChangeStreamIterable<Document> changeStream = mongoDatabase.watch(pipeline) .fullDocument(FullDocument.UPDATE_LOOKUP) .fullDocumentBeforeChange(FullDocumentBeforeChange.WHEN_AVAILABLE); changeStream.forEach(event -> { String collectionName = Objects.requireNonNull(event.getNamespace()).getCollectionName(); System.out.println("--------> event:" + event.toString()); }); } }); //數(shù)據(jù)變更測(cè)試 { Thread.sleep(3_000); InsertOneResult insertResult = mongoCollection.insertOne(new Document("test", "sample movie document")); System.out.println("Success! Inserted document id: " + insertResult.getInsertedId()); UpdateResult updateResult = mongoCollection.updateOne(new Document("test", "sample movie document"), Updates.set("field2", "sample movie document update")); System.out.println("Updated " + updateResult.getModifiedCount() + " document."); DeleteResult deleteResult = mongoCollection.deleteOne(new Document("field2", "sample movie document update")); System.out.println("Deleted " + deleteResult.getDeletedCount() + " document."); } new Scanner(System.in).next(); } private static MongoCollection<Document> initCollection(MongoDatabase mongoDatabase, String myTestCollectionName) { ArrayList<Document> existsCollections = mongoDatabase.listCollections().into(new ArrayList<>()); Optional<Document> existsCollInfoOpl = existsCollections.stream().filter(doc -> StringUtils.equals(myTestCollectionName, doc.getString("name"))).findFirst(); existsCollInfoOpl.ifPresent(collInfo -> { //確保開(kāi)啟了changeStreamPreAndPost Document changeStreamPreAndPostImagesEnable = collInfo.get("options", Document.class).get("changeStreamPreAndPostImages", Document.class); if (changeStreamPreAndPostImagesEnable != null && !changeStreamPreAndPostImagesEnable.getBoolean("enabled")) { Document mod = new Document(); mod.put("collMod", myTestCollectionName); mod.put("changeStreamPreAndPostImages", new Document("enabled", true)); mongoDatabase.runCommand(mod); } }); if (!existsCollInfoOpl.isPresent()) { CreateCollectionOptions collectionOptions = new CreateCollectionOptions(); //創(chuàng)建collection時(shí)開(kāi)啟ChangeStreamPreAndPostImages collectionOptions.changeStreamPreAndPostImagesOptions(new ChangeStreamPreAndPostImagesOptions(true)); mongoDatabase.createCollection(myTestCollectionName, collectionOptions); } return mongoDatabase.getCollection(myTestCollectionName); } }
輸出結(jié)果如下:
--------> event:ChangeStreamDocument{ operationType=insert, resumeToken={"_data": "8264255A0F000000022B022C0100296E5A10046A3E3757D6A64DF59E6D94DC56A9210446645F6964006464255A105A91F005CFB2E6D20004"}, namespace=my-test-db.myTestCollection, destinationNamespace=null, fullDocument=Document{{_id=64255a105a91f005cfb2e6d2, test=sample movie document}}, fullDocumentBeforeChange=null, documentKey={"_id": {"$oid": "64255a105a91f005cfb2e6d2"}}, clusterTime=Timestamp{value=7216272998402097154, seconds=1680169487, inc=2}, updateDescription=null, txnNumber=null, lsid=null, wallTime=BsonDateTime{value=1680169487686}}
Success! Inserted document id: BsonObjectId{value=64255a105a91f005cfb2e6d2}
Updated 1 document.
--------> event:ChangeStreamDocument{ operationType=update, resumeToken={"_data": "8264255A0F000000032B022C0100296E5A10046A3E3757D6A64DF59E6D94DC56A9210446645F6964006464255A105A91F005CFB2E6D20004"}, namespace=my-test-db.myTestCollection, destinationNamespace=null, fullDocument=Document{{_id=64255a105a91f005cfb2e6d2, test=sample movie document, field2=sample movie document update}}, fullDocumentBeforeChange=Document{{_id=64255a105a91f005cfb2e6d2, test=sample movie document}}, documentKey={"_id": {"$oid": "64255a105a91f005cfb2e6d2"}}, clusterTime=Timestamp{value=7216272998402097155, seconds=1680169487, inc=3}, updateDescription=UpdateDescription{removedFields=[], updatedFields={"field2": "sample movie document update"}, truncatedArrays=[], disambiguatedPaths=null}, txnNumber=null, lsid=null, wallTime=BsonDateTime{value=1680169487708}}
--------> event:ChangeStreamDocument{ operationType=delete, resumeToken={"_data": "8264255A0F000000042B022C0100296E5A10046A3E3757D6A64DF59E6D94DC56A9210446645F6964006464255A105A91F005CFB2E6D20004"}, namespace=my-test-db.myTestCollection, destinationNamespace=null, fullDocument=null, fullDocumentBeforeChange=Document{{_id=64255a105a91f005cfb2e6d2, test=sample movie document, field2=sample movie document update}}, documentKey={"_id": {"$oid": "64255a105a91f005cfb2e6d2"}}, clusterTime=Timestamp{value=7216272998402097156, seconds=1680169487, inc=4}, updateDescription=null, txnNumber=null, lsid=null, wallTime=BsonDateTime{value=1680169487721}}
Deleted 1 document.
到此這篇關(guān)于mongodb使用docker搭建replicaSet集群與變更監(jiān)聽(tīng)的文章就介紹到這了,更多相關(guān)mongodb搭建replicaSet集群內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在Linux服務(wù)器中配置mongodb環(huán)境的步驟
這篇文章主要介紹了在Linux服務(wù)器中配置mongodb環(huán)境的步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07mongoDB數(shù)據(jù)庫(kù)索引快速入門(mén)指南
索引是一種特殊的數(shù)據(jù)結(jié)構(gòu),存儲(chǔ)設(shè)置在一個(gè)易于遍歷形式的數(shù)據(jù)的一小部分。索引存儲(chǔ)一個(gè)特定的字段或一組字段的值,在索引中指定的值的字段排列的,對(duì)mongoDB索引相關(guān)知識(shí)感興趣的朋友跟隨小編一起學(xué)習(xí)下吧2022-03-03db.serverStatus()命名執(zhí)行時(shí)報(bào)無(wú)權(quán)限問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于db.serverStatus()命名執(zhí)行時(shí)報(bào)無(wú)權(quán)限問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07MongoDB游標(biāo)超時(shí)問(wèn)題的4種解決方法
這篇文章主要給大家介紹了關(guān)于MongoDB游標(biāo)超時(shí)問(wèn)題的4種解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MongoDB具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09mongodb 3.4下遠(yuǎn)程連接認(rèn)證失敗的解決方法
這篇文章主要給大家介紹了在mongodb 3.4下遠(yuǎn)程連接認(rèn)證失敗的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。2017-06-06mongodb 修改器($inc/$set/$unset/$push/$pop/upsert)
對(duì)于文檔的更新除替換外,針對(duì)某個(gè)或多個(gè)文檔只需要部分更新可使用原子的更新修改器,能夠高效的進(jìn)行文檔更新。更新修改器是中特殊的鍵2017-04-04深究從MongoDB的ObjectId中獲取時(shí)間信息
MongoDB默認(rèn)使用_id字段作為主鍵,類型為ObjectId。ObjectId的生成有一定的規(guī)則,詳情可以查看這篇文章MongoDB深究之ObjectId2017-03-03