【MongoDB】MongoDB-Change Streams

前言

Change Stream是从mongodb3.6版本开始支持的一种新特性,是mongodb向应用发布数据变更的一种方式,即数据库中有任何数据变化,应用端都可以得到通知,类似于触发器的概念

方案思路

MongoClient去订阅mongodb数据库中某张表最新事件变化,类似于以事件驱动机制对collection变化做监听,化主动为被动,只需要被动等待collection变化消息

Change Stream 与 Tailing Oplog 对比,参考:MongoDB 4.2 内核解析 - Change Stream | MongoDB中文社区

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());
        }
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

女汉纸一枚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值