前言
Change Stream是从mongodb3.6版本开始支持的一种新特性,是mongodb向应用发布数据变更的一种方式,即数据库中有任何数据变化,应用端都可以得到通知,类似于触发器的概念
方案思路
MongoClient去订阅mongodb数据库中某张表最新事件变化,类似于以事件驱动机制对collection变化做监听,化主动为被动,只需要被动等待collection变化消息
Change Stream 与 Tailing Oplog 对比,参考:http://www.mongoing.com/archives/29921
Java版本demo
public class MongodbStreamResumeToken {
/**
* 用于模拟断点续传的存储,后期可以存储redis缓存中
*/
private HashMap hashMap = new HashMap();
public MongoDatabase getDatabase(){
MongoDatabase database = null;
MongoClient mongoClient = null;
// MongoCredential credential = MongoCredential.createScramSha1Credential("userName","source","password");
MongoClientOptions.Builder build = new MongoClientOptions.Builder();
build.connectionsPerHost(50);
build.threadsAllowedToBlockForConnectionMultiplier(50);
build.maxWaitTime(1000*60*2);
build.connectTimeout(1000*60);
MongoClientOptions mongoClientOptions = build.build();
ServerAddress serverAddress = new ServerAddress("127.0.0.1",27112);
mongoClient = new MongoClient(serverAddress,mongoClientOptions);
database = mongoClient.getDatabase("seal");
return database;
}
/**
*
* @param collection 需要监听的集合
*/
public void WatchDb(String collection) {
MongoDatabase database = getDatabase();
MongoCollection<Document> paper = database.getCollection(collection);
//FullDocument.UPDATE_LOOKUP选项启用后,在update变更事件中将携带完整的文档数据(FullDocument)。
MongoCursor<ChangeStreamDocument<Document>> cursor = null;
//需要存取resumeToken,便于后期断点续传(监控程序意外关闭,可以根据resumeToken,继续同步关闭期间内的增删操作)
hashMap.put(collection,"{ \"_data\" : { \"$binary\" : \"gl5XgIsAAAABRmRfaWQAZF5WksTLMTgwnAlAZQBaEATiSsNQNiVOwb+UWStKFczoBA==\", \"$type\" : \"00\" } }");
Object temp = hashMap.get(collection);
//断点续传
if (temp != null){
String afterToken = String.valueOf(temp);
BsonDocument resumeToken = BsonDocument.parse(afterToken);
cursor = paper.watch().fullDocument(FullDocument.UPDATE_LOOKUP).resumeAfter(resumeToken).iterator();
}else {
cursor = paper.watch().fullDocument(FullDocument.UPDATE_LOOKUP).iterator();
}
//cursor.hasNext()这个方法是阻塞等待新的消息进来的,可以放心使用
while (cursor.hasNext()) {
ChangeStreamDocument<Document> next = cursor.next();
JSONObject jsonObject = new JSONObject();
if (StringUtils.isEmpty(next.getFullDocument())){
jsonObject.put("o", null);
}else {
jsonObject.put("o", next.getFullDocument().toJson());
}
jsonObject.put("ns", next.getNamespace().getFullName());
jsonObject.put("op", next.getOperationType().getValue());
//操作类型
log.info(next.getOperationType().getValue());
//收集变更信息,通过mq异步处理
log.info(JSON.toJSONString(next));
//存储断点续传
BsonDocument newResumeToken = next.getResumeToken();
System.out.println(newResumeToken.toString());
hashMap.put(collection,newResumeToken.toString());
}
}
}
来源:CSDN
作者:周周周6688
链接:https://blog.csdn.net/zlt995768025/article/details/104582376