mongodb的变更流解释:

变更流(Change Streams)允许应用程序访问实时数据变更,从而避免事先手动追踪  oplog 的复杂性和风险。应用程序可使用变更流来订阅针对单个集合、数据库或整个部署的所有数据变更,并立即对它们做出响应。由于变更流采用聚合框架,因此,应用程序还可对特定变更进行过滤,或是随意转换通知。(Change Streams - MongoDB Manual v5.0)

使用场景,需要websocket推送实时数据的时候,我们把数据写入mongo的同时,websocket实时监听mongo数据,拿到后推送到订阅组用户。

这里只做一端新增另一端服务监听测试,及windows下副本集快速搭建流程。

sub端代码

package main

import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
) func main() {
// 设置 MongoDB 客户端mongo单机模式不支持这种监听 单机报错 2024/08/10 11:18:54 (Location40573) The $changeStream stage is only supported on replica sets
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(context.TODO()) // 获取数据库和集合
collection := client.Database("testdb").Collection("items") // 设置 Change Stream
pipeline := mongo.Pipeline{}
changeStreamOptions := options.ChangeStream().SetFullDocument(options.UpdateLookup)
changeStream, err := collection.Watch(context.TODO(), pipeline, changeStreamOptions)
if err != nil {
log.Fatal(err)
}
defer changeStream.Close(context.TODO()) fmt.Println("开始监听 Change Stream...") // 读取 Change Stream
for changeStream.Next(context.TODO()) {
var changeEvent bson.M
if err := changeStream.Decode(&changeEvent); err != nil {
log.Fatal(err)
} fmt.Printf("检测到更改: %+v\n", changeEvent)
} if err := changeStream.Err(); err != nil {
log.Fatal(err)
}
}

pub端代码

package main

import (
"context"
"fmt"
"time" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
) func main() {
// 设置 MongoDB 客户端
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
fmt.Println("连接 MongoDB 失败:", err)
return
}
defer client.Disconnect(context.TODO()) // 获取数据库和集合
collection := client.Database("testdb").Collection("items") // 插入数据
for i := 1; i <= 5; i++ {
item := bson.D{{"name", fmt.Sprintf("item%d", i)}, {"value", i}}
_, err := collection.InsertOne(context.TODO(), item)
if err != nil {
fmt.Println("插入数据失败:", err)
return
}
//fmt.Printf("插入数据: %+v\n", item)
fmt.Printf("插入数据第 %d 条", i)
time.Sleep(2 * time.Second) // 模拟一些延迟
}
}

执行结果 pub端

执行结果 sub端

数据库不用新建集合,自动生成很方便

下面是windows下安装副本集步骤一字不拉

https://www.mongodb.com/try/download/community  下载zip包解压 bin目录同级创建data-data4(data内部需要创建好db目录),log-log4
MongoDB shell version v5.0.28
注意 data目录下没有db文件夹net start MongoDB执行服务起不来 192.168.2.6 本机ip
mongod.exe --config "E:\mongodb\mongod.conf" --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install mongod.exe --config "E:\mongodb\mongod1.conf" --serviceName "MongoDB1" --serviceDisplayName "MongoDB1" --install mongod.exe --config "E:\mongodb\mongod2.conf" --serviceName "MongoDB2" --serviceDisplayName "MongoDB2" --install mongod.exe --config "E:\mongodb\mongod3.conf" --serviceName "MongoDB3" --serviceDisplayName "MongoDB3" --install net start MongoDB
net start MongoDB1
net start MongoDB2
net start MongoDB3 bin目录下打开cmd执行mongo.exe rs_conf={_id:"rs",
members:[
{_id:0,host:"192.168.2.6:27017",priority:1},
{_id:1,host:"192.168.2.6:27018",priority:2},
{_id:2,host:"192.168.2.6:27019",priority:3},
{_id:4,host:"192.168.2.6:27020", arbiterOnly:true}
]} 返回这个代表成功:
{
"_id" : "rs",
"members" : [
{
"_id" : 0,
"host" : "192.168.2.6:27017",
"priority" : 1
},
{
"_id" : 1,
"host" : "192.168.2.6:27018",
"priority" : 2
},
{
"_id" : 2,
"host" : "192.168.2.6:27019",
"priority" : 3
},
{
"_id" : 4,
"host" : "192.168.2.6:27020",
"arbiterOnly" : true
}
]
} rs.initiate(rs_conf) 执行配置
{"ok":1}
rs.status() 查看状态
{
"set" : "rs",
"date" : ISODate("2024-08-10T02:40:20.391Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncSourceHost" : "192.168.2.6:27019",
"syncSourceId" : 2,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 3,
"writeMajorityCount" : 3,
"votingMembersCount" : 4,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"lastCommittedWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"lastAppliedWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"lastDurableWallTime" : ISODate("2024-08-10T02:40:16.003Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1723257586, 1),
"electionParticipantMetrics" : {
"votedForCandidate" : true,
"electionTerm" : NumberLong(2),
"lastVoteDate" : ISODate("2024-08-10T02:39:15.909Z"),
"electionCandidateMemberId" : 2,
"voteReason" : "",
"lastAppliedOpTimeAtElection" : {
"ts" : Timestamp(1723257547, 5),
"t" : NumberLong(1)
},
"maxAppliedOpTimeInSet" : {
"ts" : Timestamp(1723257547, 5),
"t" : NumberLong(1)
},
"priorityAtElection" : 1,
"newTermStartDate" : ISODate("2024-08-10T02:39:15.997Z"),
"newTermAppliedDate" : ISODate("2024-08-10T02:39:16.928Z")
},
"members" : [
{
"_id" : 0,
"name" : "192.168.2.6:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 2677,
"optime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2024-08-10T02:40:16Z"),
"lastAppliedWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"lastDurableWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"syncSourceHost" : "192.168.2.6:27019",
"syncSourceId" : 2,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 2,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "192.168.2.6:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 85,
"optime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2024-08-10T02:40:16Z"),
"optimeDurableDate" : ISODate("2024-08-10T02:40:16Z"),
"lastAppliedWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"lastDurableWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"lastHeartbeat" : ISODate("2024-08-10T02:40:19.059Z"),
"lastHeartbeatRecv" : ISODate("2024-08-10T02:40:20.083Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "192.168.2.6:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 2
},
{
"_id" : 2,
"name" : "192.168.2.6:27019",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 85,
"optime" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1723257616, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2024-08-10T02:40:16Z"),
"optimeDurableDate" : ISODate("2024-08-10T02:40:16Z"),
"lastAppliedWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"lastDurableWallTime" : ISODate("2024-08-10T02:40:16.003Z"),
"lastHeartbeat" : ISODate("2024-08-10T02:40:19.060Z"),
"lastHeartbeatRecv" : ISODate("2024-08-10T02:40:20.022Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1723257555, 1),
"electionDate" : ISODate("2024-08-10T02:39:15Z"),
"configVersion" : 1,
"configTerm" : 2
},
{
"_id" : 4,
"name" : "192.168.2.6:27020",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 85,
"lastHeartbeat" : ISODate("2024-08-10T02:40:19.059Z"),
"lastHeartbeatRecv" : ISODate("2024-08-10T02:40:20.092Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1,
"configTerm" : 2
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1723257616, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1723257616, 1)
}

demo代码链接

go/mongochangestreamsdemo/demo at main · liuzhixin405/go (github.com)

mongo配置链接

config/mongo windows集群 at main · liuzhixin405/config (github.com)

mongo变更流使用及windows下副本集五分钟搭建的更多相关文章

  1. 《sed的流艺术之四》-linux命令五分钟系列之二十四

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  2. 《sed的流艺术之三》-linux命令五分钟系列之二十三

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  3. 《sed的流艺术之一》-linux命令五分钟系列之二十一

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  4. zookeeper windows伪集群搭建

    1.下载zookeeper http://mirror.bit.edu.cn/apache/zookeeper/ 解压后,目录重命名为zookeeper1,进入 conf目录,把zoo_sample. ...

  5. 《sed的流艺术之二》-linux命令五分钟系列之二十二

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  6. MongoDB 变更流(Change Stream)介绍

    1. 什么是Change Stream Change Stream 是MongoDB用于实现变更追踪的解决方案,类似于关系数据库的触发器,但原理不完全相同: | | Change Stream | 触 ...

  7. 在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群

    需要说明的是我们搭建的SQL Server故障转移集群(SQL Server Failover Cluster)是可用性集群,而不是负载均衡集群,其目的是为了保证服务的连续性和可用性,而不是为了提高服 ...

  8. windows+mysql集群搭建-三分钟搞定集群

    注:本文来源:  陈晓婵   <  windows+mysql集群搭建-三分钟搞定集群   > 一:mysql集群搭建教程-基础篇 计算机一级考试系统要用集群,目标是把集群搭建起来,保证一 ...

  9. Kettle在windows下分布式集群的搭建

    集群的搭建 我这里用的是kettle7.1版本的 下载解压 我们打开kettle的安装目录,进入到data-integration->pwd目录,找到carte-config-master-80 ...

  10. Solr集群的搭建以及使用(内涵zookeeper集群的搭建指南)

    1   什么是SolrCloud SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud.当一个系统的索引数据量少的时候 ...

随机推荐

  1. vue cli4.0项目引入typescript

    现有的项目是采用vue cli4.0脚手架生成的,现在想要引入typescript. 1.执行安装命令 npm install --save-dev typescript npm install -- ...

  2. springboot+security自定义登录-1-基础-自定义用户和登录界面

    为何学习spring security? 理由如下: 1)虽然可以不用,但难免部分客户又要求 2)某种程度上,security还是不错的,譬如csrf,oauth等等,省了一些功夫. 3)虽然spri ...

  3. Linux内核:regmap机制

    背景 在学习SPI框架的时候,看到了有一个rtc驱动用到了regmap,本想通过传统方式访问spi接口的我,突然有点不适应,翻了整个驱动,愣是没有找到读写spi的范式:因此了解了regmap以后,才发 ...

  4. uboot 修改代码 增加 环境变量

    --- title: uboot修改代码增加环境变量 date: 2019-12-27 21:26:39 categories: tags: - uboot --- 以"tftp下载kern ...

  5. EC热键问题

    EC热键问题 ec 问题描述 ACPI事件监控 按键监控 UDEV事件监控 kprobe探测 初步总结热键功能流程 调试记录 PS2 问题描述 系统无触摸板打开和关闭的提示 已知热键功能 快捷键 功能 ...

  6. 韦东山freeRTOS系列教程之【第八章】事件组(event group)

    目录 系列教程总目录 概述 8.1 事件组概念与操作 8.1.1 事件组的概念 8.1.2 事件组的操作 8.2 事件组函数 8.2.1 创建 8.2.2 删除 8.2.3 设置事件 8.2.4 等待 ...

  7. ChatGPT学习之旅 (8) 单元测试助手

    大家好,我是Edison. 本篇我们基于上一篇的基础,来写一个单元测试助手的prompt,让它帮我们写一些我们.NET开发者不太愿意编写的单元测试代码,进而提高我们的代码质量,同时还降低我们的开发工作 ...

  8. Java报表开发工具总结

    Java报表工具,首先可以分成两大类:纯Java报表工具,和支持Java的报表工具. 支持Java的报表工具 支持Java的报表工具.其实就是非Java的报表工具,但是可以在Java程序中调用,这样的 ...

  9. 文件系统(九):一文看懂yaffs2文件系统原理

    liwen01 2024.07.07 前言 yaffs 是专为nand flash 设计的一款文件系统,与jffs 类似,都是属于日志结构文件系统.与jffs 不同的是,yaffs 文件系统利用了na ...

  10. 首届 DIVE 精彩回顾丨践行企业数字化,基础软件如何创新

    "墙高基下,虽得必失."在构建数字企业大厦的工程中,基础软件的重要性不言而喻.但对于各行各业而言,面向传统经营模式设计的基础软件已经难以支撑数字业务的创新,唯有汲取专业团队的经验, ...