-
mongodb挺好用的,存json数据方便。但默认安装后是不需要认证就可以直接连接,有点危险,下面就来配置mongodb的访问控制。系统环境: OS:centos7.6其他信息: mongodb server服务端下载地址:https://www.mongodb.com/try/download/community mongodb shell客户端下载地址:https://www.mongodb.com/try/download/shell安装过程我就不写出来了,下载好rpm包到服务器直接用rpm 命令安装就行。1.启动mongodb服务systemctl restart mongod2.添加管理员账号#启动mongodb客户端 mongosh #进入admin数据库 use admin #创建用户,user:用户名,pwd:密码,roles:角色 db.createUser({user: 'root', pwd: passwordPrompt(), roles: ['root']})3.关闭mongodb服务systemctl stop mongod4.设置开启访问控制启动#编辑mongodb服务 vi /usr/lib/systemd/system/mongod.service5.登录时验证#启动mongodb客户端 mongosh #进入admin数据库 use admin #进行身份验证,执行完后会提示输入密码 db.auth("root", passwordPrompt())如果需要在python使用带身份验证的mongodb,from pymongo import MongoClient # user:用户名,pwd:密码,server:服务器地址,port:服务端口,database:要连接的数据库 client = MongoClient('mongodb://user:pwd@server:port/database?authSource=admin')如果要修改密码请用这个命令db.changeUserPassword("user123", passwordPrompt())
-
这次以MongoDB 4.0.12为例演示如何在OpenEuler 20.03(LTS)编译安装。由于MongoDB 4.0.12安装需要不能少于50G磁盘剩余空间,请首先确认是否满足此条件。另外还需要执行以下基础组件安装:yum -y install libyaml libyaml-devel python-setuptools libcurl-devel python-devel gmp gmp-devel mpfr mpfr-devel libmpc libmpc-devel libpcap-dev*。如果上面安装过程无法识别,请参考“配置OpenEuler的网络yum源”,链接如下:https://bbs.huaweicloud.com/forum/thread-98091-1-1.html下面开始演示:1、 前置环境准备:cmake>=3.5.2;gcc>=7.3,对于openEuler20.03来说默认都是满足的。如下图所示:Cmake版本信息Gcc版本信息2、 安装MongoDB还需要依赖python和python相关模块,默认python2.7应该是默认已经安装成功的,如下图所示其他python组件信息如下表所示:软件名称及版本链接地址pyyamlhttps://github.com/yaml/pyyaml.gittypinghttps://github.com/python/typing.gitcheetah3https://github.com/CheetahTemplate3/cheetah3.gitA) 安装pyyaml下载pyyaml:git clone https://github.com/yaml/pyyaml.git进入pyyaml目录进项安装组件:B) 安装typing下载typing:git clone https://github.com/python/typing.git进入typing并开始安装:python setup.py installC) 安装cheetah3下载cheetah3:git clone https://github.com/CheetahTemplate3/cheetah3.git进入cheetah3安装 3、 MongoDB源码安装A) 下载MongoDB源码:wget https://github.com/mongodb/mongo/archive/r4.0.12.tar.gz【注意】下载速度可能有些慢,可以先通过下载工具完成下载,然后上传到服务器上B) 解压并安装:tar xzvf mongo-4.0.12.tar.gz,解压完成计入文件夹cd mongo-4.0.12C) 编译MongoDB源码:python2 buildscripts/scons.py MONGO_VERSION=4.0.12 all CFLAGS="-march=armv8-a+crc -mtune=generic" –j8 --disable-warnings-as-errors【注意】由于ECS的机器配置不能,编译的时间也是不定的D) 执行安装:python2 buildscripts/scons.py MONGO_VERSION=4.0.12 --prefix=/usr/local/mongo --disable-warnings-as-errors CFLAGS="-march=armv8-a+crc" install -j8E) 查看结果,通过上面截图可以看出安装目录位于:/usr/local/mongo/bin/目录中4、 验证:简单实用MongoDB,验证MongoDB是否可用A) 准备必要的文件和文件夹:B) 启动MongoDB服务端:C) 客户端登录:添加用户:添加数据并查询
-
【功能模块】【操作步骤&问题现象】1、安装mongoDB,中途更新python导致yum命令无法执行,显示python不兼容。2、依照网上的提示:更改 #!/usr/bin/python => #!/usr/local/bin/python2.73、但是还是报同样的错误【截图信息】There was a problem importing one of the Python modules required to run yum. The error leading to this problem was:No module named yumPlease install a package which provides this module, or verify that the module is installed correctly.It’s possible that the above module doesn’t match the current version of Python, which is:If you cannot solve this problem yourself, please go to the yum faq at:【日志信息】(可选,上传日志内容或者附件)
-
【功能模块】【操作步骤&问题现象】1、根据这个连接https://www.huaweicloud.com/kunpeng/software/mongodb.html安装2、到达第六步,执行报错:根据上面的安装步骤 6) 执行以下命令,构建编译环境。 scl enable devtoolset-7 "/usr/local/bin/pip2 install -r buildscripts/requirements.txt" 执行第六步以后,报了这个错: Failed to bulid cryptography ERROR Could not build wheels for cryptography which use PEP 517 and cannot be installed directly【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
【功能模块】【操作步骤&问题现象】1、通过yum install -y mongodb-org2、报错Error:Nothing todo3、通过二进制包安装提示:无法执行二进制文件【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
系统:Linux ecs-arm-iot-0005 4.18.0-80.7.2.el7.aarch64 #1 SMP Thu Sep 12 16:13:20 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux文档:https://www.huaweicloud.com/kunpeng/software/mongodb.html我按照这个文档安装MongoDB,当构建编译环境:#scl enable devtoolset-7 "/usr/local/bin/pip2 install -r buildscripts/requirements.txt"发生了如下报错:
-
系统:Linux ecs-arm-iot-0005 4.18.0-80.7.2.el7.aarch64 #1 SMP Thu Sep 12 16:13:20 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux文档:https://www.huaweicloud.com/kunpeng/software/mongodb.html我按照这个文档安装MongoDB,当构建编译环境的时候发生了如下报错:#scl enable devtoolset-7 "/usr/local/bin/pip2 install -r buildscripts/requirements.txt"
-
文档数据库DDS介绍页入口,详情请点击链接文档数据库DDS迁移指导入口, 详情请点击链接噔噔,新一期的数据库干货又来啦~如果您因业务调整或需要使用华为云文档数据库特性功能时,可以通过数据迁移功能将原有MongoDB数据库的数据迁移至华为云文档数据库。小云妹带来了几种不同的方式,一起来学习下 【往期回顾】●【第一期】华为云DDS-云上高性价比文档数据库服务●【第二期】小云妹之DDS实例安全基本操作●【第三期】文档数据库可视化运维 高频需求一键式便捷操作
-
-
Q1:GaussDB(for Mongo)在使用上和社区版MongoDB有什么不一样的地方?有哪些不兼容的地方需要注意?ANS:GaussDB(for Mongo)对社区版本完全兼容,不过出于安全和防呆的考虑,禁用了一部分高危命令。Q2:啥时候出GaussDB(for PgSQL)啊?ANS:非常开心的告诉大家,GaussDB(for PostgreSQL)已经在研发中,预计年底将在官网上跟大家见面,感兴趣的开发者届时可以来试用。Q3:话说,副本集是个什么形态?ANS:这是MongoDB基础概念,具体可以参考官方文档,或者在中文社区上搜索相关资料 https://docs.mongodb.com/manual/replication/ https://mongoing.com/Q4:从节点的个数变多会影响主节点的写性能吗?ANS:对于社区版来说,由于从节点需要从主节点拉去oplog,所以多增加主节点的压力,会影响写性能。对于GaussDB(for Mongo)来说则不会影响主节点的写性能。Q5:GaussDB(for Mongo) 最高支持MongoDB4.0协议版本,那么后续社区版4.2, 4.4的分布式事务等新特性,GaussDB(for Mongo)会持续跟进吗?ANS:后续社区上的新特性,GaussDB(for Mongo)都会在当前版本兼容起来.Q6:不同mongod的cache如何解决?ANS:每个Mongod的cache独立处理采用统一的策略,互相之间没有影响。Q7:for mongo是啥意思?ANS:即兼容Mongo协议、语法、生态。Q8:共享文件系统里面是以chunk为单位的?ANS:这里提到的是Mongo层的chunk,分片集合的数据就是通过chunk管理的,在balance过程中迁移的最小单元。Q9:不同shard双写同一个key如何解冲突?ANS:应该是想问不同的shard同时写一个共享的数据文件是如何解决冲突的。一个数据文件只会归属shard,通过文件系统层的写锁提供保证。Q10:GaussDB(for Mongo) ,GaussDB(for MySQL)、还有未见面的GaussDB(for PgSQL) 比原生的是否都有什么类似的改进,都加个GaussDB?ANS:GaussDB是华为云面向政企、金融客户打造的自研数据库,兼容开源生态,自主可控。在底层统一采用了存算分离架构,可以达到分钟级甚至秒级水平扩容,无论是存储节点,还是计算节点。各云服务还提供了许多特有的价值特性。您可以关注华为云数据库社区&论坛(https://developer.huaweicloud.com/techfield/db.html)和“HW云数据库”公众号,我们持续在输出精品文章、技术沙龙、学习课程、培训认证、产品文档、免费试用等。Q11:采用的是分布式存储方式吧?ANS:是的。Q12:水平扩展性能这么好,那单节点读写性能和社区版MongoDB相比,是否具有优势?ANS:在新架构上,对于单节点收益不大,所以不提供单节点。本身单节点的可靠性,高可用都是有问题的,所以即使使用社区版也不建议采用这种部署方式。Q13:单独的存储池,GaussDB数据只存了2份?ANS:GaussDB(for Mongo)数据在存储层是3副本。Q14:GaussDB相较于传统数据库,最大的优势是什么?ANS:计算存储分离,性能更好,相同的业务需求有更高的性价比,以及更快的弹性伸缩能力,更高的可用性。Q15:存算分离,容灾备份机制目前采用哪种方式最好?会增加建设成本吗?ANS:关于建设成本主要影响因素是容灾的具体方案,存算分离本身不增加额外的成本。Q16:突然掉电,能保证计算节点在掉电瞬间的的数据存储的完整性吗?ANS:文件系统层提供了这样的保证,计算节点掉电并不会损坏数据文件。Q17:安全策略上,与其他产品或方案最大的区别在哪里?ANS:在社区版本安全策略的基础上,增加禁止了高危命令,用户权限控制,密码策略等一系列加固手段。并且华为云统一提供VPC、子网等安全策略。Q18:副本集轻写,能达到什么写量级?ANS:8U实例纯写可以达到38000 ops。Q19:计算存储分离以后存储的时延是否变大了?ANS:与EVS的存储性能相比更优(更大吞吐更低时延),与本地盘相比时延略高。Q20:老师为什么叫GoldenJohn?ANS:1、谐音 2、为了闪闪发亮、高大上的GoldenQ21:副本集和热备容灾有多大的区别?ANS:副本集提供实例级别内的高可用,高可靠的能力。容灾提供实例级别的高可用和高可靠能力。前者实时性更好,倒换全自动不需要外部干预,故障恢复时间短,社区提供的基础能力。对于热备容灾来说,受传输影响大,无法自动接管需要人力介入。故障恢复时间相关更长。
-
一、_id 索引我们介绍过,我们往集合中添加文档时,默认情况下MongoDB都会帮助我们创建一个名为_id的字段,这个字段就是一个索引。默认情况下,一般的集合都会帮我们创建这个字段作为索引,但也有一些集合不会将_id默认作为索引,比如固定集合,这个我们后面会详细说到这个问题。二、复合索引如果我们的查询条件有多个的话,我们可以对这多个查询条件都建立索引,比如我们可以对文档中的x和y字段都建立索引,如下:db.sang_collect.ensureIndex({x:1,y:-1})1此时执行如下查询语句时就会用到这个复合索引:db.sang_collect.find({x:1,y:999})1小伙伴们也可以通过查看查询计划来确定确实使用到了上文创建好的索引。三、过期索引顾名思义,过期索引就是一种会过期的索引,在索引过期之后,索引对应的数据会被删除,创建方式如下:db.sang_collect.ensureIndex({time:1},{expireAfterSeconds:30})1expireAfterSeconds表示索引的过期时间,单位为秒。time表示索引的字段,time的数据类型必须是ISODate或者ISODate数组,否则的话,当索引过期之后,time的数据就不会被删除。四、全文索引全文索引虽然好用,可惜不支持中文,我们这里就先做一个简单的了解。比如,我的数据集如下:{ "_id" : ObjectId("59f5a3da1f9e8e181ffc3189"), "x" : "Java C# Python PHP"}{ "_id" : ObjectId("59f5a3da1f9e8e181ffc318a"), "x" : "Java C#"}{ "_id" : ObjectId("59f5a3da1f9e8e181ffc318b"), "x" : "Java Python"}{ "_id" : ObjectId("59f5a3da1f9e8e181ffc318c"), "x" : "PHP Python"}{ "_id" : ObjectId("59f5a4541f9e8e181ffc318d"), "x" : "C C++"}1234567891011121314151617181920我们可以给x字段建立一个全文索引,创建方式如下:db.sang_collect.ensureIndex({x:"text"})1MongoDB会自动对x字段的数据进行分词,然后我们就可以通过如下语句进行查询:db.sang_collect.find({$text:{$search:"Java"}})1此时x中包含Java的文档都会被查询出来。如果想查询既包含Java又包含C#的文档,操作如下:db.sang_collect.find({$text:{$search:"\"Java C#\""}})1用一对双引号将查询条件括起来,如果想查询包含PHP或者Python的文档,操作如下:db.sang_collect.find({$text:{$search:"PHP Python"}})1如果想查询既有PHP,又有Python,但是又不包括Java的文档,如下:db.sang_collect.find({$text:{$search:"PHP Python -Java"}})1建立了全文索引之后,我们也可以查看查询结果的相似度,使用$meta,如下:db.sang_collect.find({$text:{$search:"PHP Python"}},{score:{$meta:"textScore"}})1此时查询结果中会多出一个score字段,该字段的值越大,表示相似度越高,我们可以根据score利用sort来对其进行排序,如下:db.sang_collect.find({$text:{$search:"PHP Python"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})1全文索引目前看起来功能还是很强大,可惜暂时不支持中文,不过网上对此也有很多解决方案,小伙伴们可以自行搜索查看。五、地理空间索引1. 2d 索引2d索引,可以用来存储和查找平面上的点。,2d索引一般我们可以用在游戏地图中向集合中插入一条记录点的数据:db.sang_collect.insert({x:[90,0]})1插入数据的格式为[经度,纬度],取值范围,经度[-180,180],纬度[-90,90]。数据插入成功之后,我们先通过如下命令创建索引:db.sang_collect.ensureIndex({x:"2d"})1然后通过$near我们可以查询某一个点附近的点,如下:db.sang_collect.find({x:{$near:[90,0]}})1默认情况下返回该点附近100个点,我们可以通过$maxDistance来设置返回的最远距离:db.sang_collect.find({x:{$near:[90,0],$maxDistance:99}})1我们也可以通过$geoWithin查询某个形状内的点,比如查询矩形中的点:db.sang_collect.find({x:{$geoWithin:{$box:[[0,0],[91,1]]}}})1两个坐标点用来确定矩形的位置。查询圆中的点:db.sang_collect.find({x:{$geoWithin:{$center:[[0,0],90]}}})1参数分别表示圆的圆心和半径。查询多边形中的点:db.sang_collect.find({x:{$geoWithin:{$polygon:[[0,0],[100,0],[100,1],[0,1]]}}})1这里可以填入任意多个点,表示多边形中的各个点。2. 2d sphere 索引2dsphere适用于球面类型的地图,它的数据类型是GeoJSON格式的,我们可以在http://geojson.org/地址上查看GeoJSON格式的样式,比如我们描述一个点,GeoJSON如下:{ "_id" : ObjectId("59f5e0571f9e8e181ffc3196"), "name" : "shenzhen", "location" : { "type" : "Point", "coordinates" : [ 90.0, 0.0 ] }}1234567891011描述线,GeoJSON格式如下:{ "_id" : ObjectId("59f5e0d01f9e8e181ffc3199"), "name" : "shenzhen", "location" : { "type" : "LineString", "coordinates" : [ [ 90.0, 0.0 ], [ 90.0, 1.0 ], [ 90.0, 2.0 ] ] }}123456789101112131415161718192021描述多边形,GeoJSON格式如下:{ "_id" : ObjectId("59f5e3f91f9e8e181ffc31d0"), "name" : "beijing", "location" : { "type" : "Polygon", "coordinates" : [ [ [ 0.0, 1.0 ], [ 0.0, 2.0 ], [ 1.0, 2.0 ], [ 0.0, 1.0 ] ] ] }}123456789101112131415161718192021222324252627还有其他的类型,具体小伙伴们可以参考http://geojson.org/。有了数据之后,我们可以通过如下操作来创建地理空间索引了:db.sang_collect.ensureIndex({location:"2dsphere"})1比如我想查询和深圳这个区域有交集的文档,如下:var shenzhen = db.sang_collect.findOne({name:"shenzhen"})db.sang_collect.find({location:{$geoIntersects:{$geometry:shenzhen.location}}})12这里的查询结果是和深圳这个区域有交集的都会查到(比如经过深圳的高速公路、铁路等),我们也可以只查询深圳市内的区域(比如深圳市内所有的学校),如下:var shenzhen = db.sang_collect.findOne({name:"shenzhen"})db.sang_collect.find({location:{$within:{$geometry:shenzhen.location}}})12也可以查询腾讯附近的其他位置,如下:var QQ = db.sang_collect.findOne({name:"QQ"})db.sang_collect.find({location:{$near:{$geometry:QQ.location}}})12六、复合地理空间索引位置往往只是我们查询的一个条件,比如我要查询深圳市内所有的学校,那我得再增加一个查询条件,如下:var shenzhen = db.sang_collect.findOne({name:"shenzhen"})db.sang_collect.find({location:{$within:{$geometry:shenzhen.location}},name:"QQ"})12其他的查询条件跟在后面就行了。
-
1.摘要GaussDB(for Mongo)是华为云自主研发兼容MongoDB4.0接口的文档数据库。基于共享存储的存算分离架构,对于传统MongoDB社区版有如下优势:秒级添加Secondary节点(相比社区版Mongo小时级添加Secondary节点)基于WAL复制, Secondary节点无写IO,从根本上解决社区版Seconary节点Oplog脱节问题Primary/Seconary无任何IO交互,Secondary节点个数理论无上限, 支持百万OPS的读事务能力LSMTree Compaction 计算/IO卸载到Compaction统一调度池,集中管理,不浪费用户读写IO基于共享存储,Chunk分裂/迁移动作不引起真实IO,只更新路由元数据,秒级分裂/均衡2.GaussDB(for Mongo)技术架构1)容忍更多Shard宕机与社区版MongoDB的`Share-Nothing`模式不同的是,GaussDB(for Mongo)采用`Share-Storage`架构,计算存储分离。集群模式下,N个Shard节点,可以容忍N-1个Shard宕机。某个Shard节点宕机后,其负责的数据由于存在于共享的存储池中,因此不需要物理拷贝数据,只需要修改元数据路由信息,即可被其他分片节点接管。2)更快的分裂与均衡能力此外,由于Chunk数据在存储池中,Chunk的分裂与均衡不涉及到数据拷贝,可以做到分钟级分裂与扩容,分裂与扩容对用户的影响也远比社区版MongoDB小。3)百万级读OPS能力GaussDB(for Mongo)副本集模式下,Primary/Secondary节点之间共享同一份数据库文件。Secondary节点只复制Primary节点的WriteAheadLog以及LSMTree的结构变更信息,并应用到内存中。Secondary节点没有LSMTree的Compaction和Flush任务,因此对用户的读业务影响很小。此外,由于`Share-Storage`的架构优势,添加Secondary节点并不需要拷贝数据,添加Secondary节点的动作可以秒级完成。而Primary/Secondary之间只传递元数据变更,不传递WriteAheadLog,因此Secondary节点的个数即使变多,也不影响Primary节点的写性能。Secondary节点可以水平扩展,支撑百万级的读OPS。4)主节点IO卸载LSMTree的写压力来源于三部分:用户的业务写入导致的Memtable Flush后台SST文件CompactionWAL的持续写入根据线上业务的实际测算,三者的IO资源消耗占比为: 1:10:1。后台的SST文件Compaction占了绝大部分IO带宽,通过将Compaction任务集中化管理,从计算池卸载到存储池,进一步减少了用户计算节点的CPU和IO资源消耗。5)GaussDB(for Mongo) 只读节点设计传统社区版MongoDB副本集基于Oplog做数据复制,只读节点需要镜像主节点的所有写IO操作。GaussDB(for Mongo) 的只读节点和主节点共享同一份底层数据库文件(LSMTree的SST文件),只读节点并不自己生成SST文件。随着业务数据的写入,Compaction的不断执行,LSMTree的当前版本(包含哪些SST文件)不断更新,LSMTree的元数据更新(增删SST文件的记录)被同步到只读节点执行。RocksDB中,数据的变更被持久化到WAL里,元数据的变更(增删文件的操作, 叫做VersionEdit)被持久化到Mainifest里。RocksDB的数据和元数据是分开的,WAL流和VersionEdit流是并行的,没有严格的先后顺序。为了保证只读节点和主节点完全一致的事件回放顺序,WAL和VersionEdit流必须要合并成一个流,在双流合并后,通过LSN就可以为每个事件(WAL的写操作/VersionEdit)定序。基于WAL+VersionEdit复制,而不基于Oplog复制共享文件(sst/wal)的生命周期管理由主节点负责sst文件和wal的文件的生命周期由主节点负责。RocksDB中,SST文件通过层级的引用计数来维持不被删除。如下图,RocksDB的每个游标会维持SuperVersion,如下图中的S0,S1,S2。每个SuperVersion会引用一个Version,一个Version代表LSMTree在不断变形(通过增删SST文件变形)的过程中,某个时间点的形状,最新的Version就代表LSMTree当前的形状。在GaussDB(for Mongo)中,主节点会记录所有只读节点在使用的Version,并为这些Version增加引用计数从而维持SST文件的生命周期。对于WAL,主节点会记录所有只读节点中最老的LSN(`oldestLsn`),最老的LSN来自于复制最慢的只读节点。并删除比oldestLsn还旧的WAL文件。元数据变更通知,无论是oldestLsn还是只读节点的当前在用的活跃的Version,都需要及时推进,这些元数据的变更是通过主从节点的定期心跳上报到主节点上的。主节点利用心跳数据对垃圾版本与WAL做清理。如下图所示,在经历一次心跳后,主节点发现Secondary0的Version0和Secondary1的Version0不再使用。删除这两个Version后,SST0的引用计数为0,表示SST0可以被删除。OldestLsn也从100推进到了250,可以清理掉250之前的WAL。只读节点的memtable的释放:主节点的Memtable不会实时Flush为SST文件。如果只读节点不处理主节点的Memtable的话,只读节点的数据就不是实时的,且存在数据一致性问题。只读节点通过回放WAL到内存的Memtable中,来覆盖SST文件与主节点的Memtable的Gap。上文介绍了只读节点是不往共享存储写入数据的, 所以只读节点上的 Memtable 最后的结局一定是被丢弃掉。但什么时候丢弃这个 Memtable 就是一个问题。过早的丢弃,会造成SST文件与Memtable之间的数据不连续,存在Gap,过晚的丢弃会造成内存的浪费。只有当只读节点识别到SST的数据已经完全能够Cover某个Memtable时,这个Memtable才可以被丢弃。GaussDB(for Mongo)的只读节点在每次应用VersionEdit后,检查所有SST中的最大的LSN与Memtable的最小的LSN的关系,来决定是否要丢弃某个Memtable。内存元数据的反向更新:传统的复制,数据流从Oplog来,走一遍完整的数据库Server层CRUD接口,再落到引擎层。这种逻辑和主节点上业务的写入逻辑是一致的,因此Server层的一些内存元数据结构,在这个过程中就自然而然的得到更新了。但是当采用基于WAL的复制后,整个WritePath并不经过只读节点的Server层。因此Server层的内存元数据更新,就是一个很大的挑战。在这里,只读节点对每一条WAL做分析,如果WAL的内容会影响Mongo内存元数据,就会reload对应的元数据模块。3.总结GaussDB(for Mongo) 基于Share-Storage架构,实现秒级Chunk分裂与均衡,对业务影响更小,水平扩展速度更快,能容忍更多节点宕机。只读节点功能,实现了一份数据多计算节点共用的功能。极大的提升了存储的利用效率,提高了计算节点的读取数据能力。为了让副本节点具有持续的读扩展能力,整个只读方案采用元数据的同步模式,在不降低主节点负载的情况下,极大的提升了整个系统的读数据的处理能力。为3节点,5节点,乃至于15节点以上的副本集的工作提供了可能。
-
MongoDB经典故障系列一:数据库频繁启动失败怎么办?MongoDB经典故障系列二:如何限制最大连接数? MongoDB经典故障系列三:副本集延迟太高怎么办?MongoDB经典故障系列四:调整oplog大小,引起从库宕机怎么办?MongoDB经典故障系列五:sharding集群执行sh.stopBalancer()命令被卡住怎么办?MongoDB经典故障系列六:CPU利⽤率太⾼怎么办?
-
摘要:本文尝试对Mongo的复制和分布式事务的原理进行描述,在必要的地方,对实现的正确性进行论证,希望能为MongoDB内核爱好者提供一些参考。1.前言MongoDB基于wiredTiger提供的泛化SI的功能,重构了readHistory(readMajority)的能力基于wiredTiger提供的AllCommittedTimestamp API,重构了前缀一致的主从复制(Prefix-Consistent-Replication)引入混合逻辑时钟(HLC),每个节点(Mongos/Mongod)的逻辑时钟维持在接近的值,基于此实现ChangeStream, 结合HLC与CLOCK-SI,实现分布式事务,HLC和泛化SI,CLOCK-SI两篇Paper可以作为理解MongoDB的设计的理论参考(这里并没有说MongoDB是Paper的实现)。本文尝试对Mongo的复制和分布式事务的原理进行描述,在必要的地方,对实现的正确性进行论证,希望能为MongoDB内核爱好者提供一些参考。2.MongoDB副本集事务介绍MongoDB 副本集的事务MongoDB副本集的复制是基于raft协议,相比于Paxos,raft协议实现简单,但是raft协议只支持single-master,对应的,MongoDB的副本集是主从架构,而且只有主节点支持写入操作。MongoDB副本集的事务管理,包括冲突检测,事务提交等关键操作,都只在主节点上完成。也就是说副本集的事务在事务管理方面,跟单节点逻辑基本一致。MongoDB的事务,仍然是实现了 ACID 四个特性, MongoDB使用 SI 作为事务的隔离级别。3.SI的简介SI,即SnapshotIsolation,中文称为快照隔离,是一种mvcc的实现机制,它在1995年的A Critique of ANSI SQL Isolation Levels中被正式提出。因快照时间点的选取上的不同,又分为Conventional Si 和 Generalized SI。CSI(Convensional SI)CSI 选取当前最新的系统快照作为事务的读取快照就是在事务开始的时候,获得当前db最新的snapshot,作为事务的读取的snapshot,snapshot(Ti) = start(Ti)可以减少写事务冲突发生的概率,并且提供读事务读取最新数据的能力一般我们说一个数据库支持SI隔离级别,其实默认是说支持CSI。比如RocksDB支持的SI就是CSI,WiredTiger在3.0版本之前支持的SI也是CSI。GSI(Generalized SI)GSI选择历史上的数据库快照作为事务的读取快照,因此CSI可以看作GSI的一个特例。在复制集的情况下,考虑 CSI, 对于主节点上的事务,每次事务的开始时间选取的系统 最新的快照, 但是对于其他从节点来说, 并没有 统一的 “最新的” 快照这个概念。泛化的快照实际上是基于快照观测得到的,对于当前事务来说,我们通过选取合适的 更早时间的快照,可以让 从节点上的事务正确且无延迟的执行。举例如下:例如当前数据库的状态是, S={T1, T2, T3}, 现在要开始执行T4,如果我们知道T4要修改的值,在T3上没有被修改, 那么我们在执行T4的时候, 就可以按照 T2 commit后的snashot进行读取。如何选择更早的时间点,需要满足下面的规则,符号定义Ti: 事务iXi: 被事务i修改过的X变量snapshot(Ti): 事务i的选取的快照时间start(Ti): 事务i的开始时间commit(Ti): 事务i的提交时间abort(Ti): the time when Ti is aborted.end(Ti): the time when Ti is committed or aborted.公式解释读规则G1.1, 如果变量X被本事务修改了值且读取到了新的值, 那么 读操作一定在写操作后面;G1.2, 如果事务i读取了事务j更新的变量的X, 那么一定不会有事务i更新X的操作,在事务i读取了事务j更新的变量的X这个操作前面;G1.3, 事务j的提交时间早于事务i的快照时间;G1.4, 对于任意一个会更新变量X的事务k, 那么这个事务k一定满足, 要么事务k的提交时间小于事务j, 要么这个事务k的提交时间大于事务i。写规则G2, 对于任意已经在提交历史里的两个事务,Ci, Cj, 那么一定可以保证当 事务j的commit时间戳在 事务i的观测时间段内时(snapshot(Ti), commit(Ti)), 那么他们更新的变量交集一定为空。PCSI(PREFIX-CONSISTENT SNAPSHOT ISOLATION SI)GSI 只是定义了一个范围的range,都可以作为SI使用,并没有定义具体应该选择哪个SI。PCSI 是为了复制集而设计的。对于一个事务Ti 要开S节点开始运行, 那么 S节点将必须包含这个事务所需要的所有前置事务都必须运行且提交。相比较于GSI, PCSI的读规则,额外增加了 P1.5 规则。SI的提交时间戳设置,依据 A Critique of ANSI SQL Isolation Levels 中的描述, 提交时间戳的设置应该是单调递增的。新设置的时间戳,应该大于系统中已经存在的开始时间戳和提交时间戳。SI 读取时间戳的设置,必须保证比当前系统中正在运行的事务的最小的提交时间戳还要小, 因为一旦大于当前系统中正在运行事务的最小的提交时间戳,那么这个读事务读取到的数据就是未定义的, 取决于读事务启动的时间,而不是snapshot的时间,这违背了 一致性的要求。举例如下当前已经完成的事务是T1,正在运行的事务是T2, 将要运行的读事务是T3, 如果 T3的读时间戳大于T2事务提交时间戳, 并且T2事务正在运行,等到T2事务执行完后。我们观察这个 database,就会发现 他违背了GSI,事务执行顺序如下所示是:T1 commited and commitTs(1) -> T2 start -> T2 set commitTs(2) -> T3 start -> T3 set snapshotTs(3) -> T3 commit -> pointA -> T2 commit -> pointB那么可知, T3事务实际读取的值是 T1事务的值。但根据 pointB 点来看 GSI的读规则 1.4 的要求,会发现, 如果T3读到T1的事务的修改,那么必然要求, T3和T1之间没有空洞。但实际上 T2 是落在了 T3和T1之间的, 也就是说, 违反了 GSI 1.4的读规则。所以我们必须规定, SI 读取时间戳的设置,必须保证比当前系统中正在运行的事务的最小的提交时间戳还要小。4.MongoDB副本集时间戳应用MongoDB 4.0的复制也是利用时间戳特性解决了3.x系列MongoDB从节点复制造成从节点性能下降的关键方案。MongoDB oplog 乱序问题MongoDB主备节点的数据同步并不基于WiredTiger的wal日志来做的。相反,mongodb会将每次操作的数据变更写入到一个叫做oplog的集合里。oplog这个集合,虽然名字带有log,但实际上,它是一个MongoDB的表, 对oplog的写入,并不是 append的方式修改的, 而是呈现出一种尾部乱序的方式。对于oplog来说, oplog的读取顺序是按照TS字段来排序的, 跟上层的提交顺序无关。所以存在后开始的事务,在oplog先读取的场景。oplog 空洞因为出现了乱序,所以从节点在读取oplog的时候,就会在某些时间点出现空洞。举例如下:时间点1: oplog 顺序为: Ta -> Tb, 此时系统中还有一个事务Tc在运行时间点2: oplog 顺序为: Ta -> Tc -> Tb, 当Tc运行结束后, 因为ts的顺序, 看起来是将Tc插入到了Ta和Tb之间。那么当 从节点 在时间点1 reply 到 Tb的时候, 实际上是漏了 Tc的,这个就是oplog的空洞, 他产生的原因是因为,从节点如果每次读取oplog最新的数据,就有可能会得到一个不连续的数据, 例如 时间点1上 Ta-> Tb. 这就是oplog空洞。在具体复制逻辑中,我们必须想办法来从节点读取到含有空洞的oplog数据。这也是GSI的要求, snapshot的选取不能含有空洞。因为 oplog的Ts是mongo上层给的,我们很容易知道哪些事务有哪些ts, 我们再将这个ts 作为事务的commitTs 放到 oplog存储的事务里, 这样我们读取 oplog的顺序事务的可见性顺序相一致了,在这种情况下,我们就可以 根据 活跃事务列表, 就可以将oplog 分为两个部分,假设活跃commitTs列表的事务是 {T10, T11, T12}, 活跃事务列表是 {T10, T11, T12, T13, T14}, 那么意味着, 目前有 T10, T11, T12, T13, T14 再运行,并且 T10, T11, T12 已经设置了 commitTs, 又因为 上面讨论的 commitTs 是单调递增的, 那么我们可知, T13, T14 的commitTs 一定大于 maxCommitTs(T10, T11, T12), 而且我们还可知, minCommitTs(T10,T11,T12) 就是全局最小的 commitTs, 而小于这些的 commitTs的事务,因为不在 活跃事务列表里了, 表示已经提交了, 那么我们可以知道, oplog ts 在 全局最小的 commitTs 之前的, 就是都提交了的, oplog 按照 commitTs 排序后,如下所示… Tx | minCommitTs(T10,T11,T12) | …我们可以知道 T9, 或者说小于 minCommitTs(T10,T11,T12) 都是无空洞,因为系统不会再提交小于 minCommitTs(T10,T11,T12) 的事务到oplog里了, 所以从节点可以直接恢复这里的数据。上面说的oplog minCommitTs(T10,T11,T12) 在 mongodb里,就是特殊的timestamp, 这个后文会讲。通过上面的方案,我们可以解决空洞的问题。这个时候,从节点每次恢复数据的时候,将读取的snapshot,设置为上一次恢复的Ts(同样也是无空洞的Ts), 这样的话, 从节点的恢复数据和读取数据也就做到了互不冲突。从而解决了 3.x系列的 从节点同步数据造成节点性能下降的问题。转载自:华为云开发者论坛
-
1. 简介Mongo-tools是使用MongoDB的一系列工具,每个工具有具有相应的功能:bsondump - 将BSON格式的文件转换为可读性更强的文件格式mongodump - MongoDB数据存储工具mongoexport - MongoDB导出工具mongofiles – MongoDB文件操作工具mongoimport - MongoDB导入程序mongorestore - MongoDB数据恢复工具mongostat – MongoDB状态检测工具mongotop – MongoDB监控工具 2. 部署环境Packet NameVersionDetailCentOSCentOS 7.5 64bit with ARMarm通用计算增强型 2vCPUs | 4GB | kc1.large.2Go1.12以上GCC4.8.5Yum安装 3. 安装部署3.1 配置Go环境wget https://obs-mirror-ftp4.obs.cn-north-4.myhuaweicloud.com/middleware/go1.14.5.linux-arm64.tar.gz tar -zxvf go1.14.5.linux-arm64.tar.gz -C /usr/local解压后配置环境变量vim /etc/profile //在文件的最后加上 export GOROOT=/usr/local/go export GOPATH=/usr/local/go export PATH=$PATH:$GOPATH/bin 完成编辑之后 source /etc/profile执行ln -s /usr/bin/go /usr/local/go/bin/go go version查看已配置的go版本3.2 构建Mongo-tools下载mongo-tools安装包wget https://obs-mirror-ftp4.obs.cn-north-4.myhuaweicloud.com/middleware/mongo-tools.tar.gz创建文件目录,将文件夹移动到对应位置tar -xvf mongo-tools.tar.gz mkdir -p /root/mongodb-tools-r4.2.0/src/github.com/mongodb mv mongo-tools /root/mongodb-tools-r4.2.0/src/github.com/mongodb建立GCC软链接mkdir -p /opt/mongodbtoolchain/v3/bin ln -s /usr/bin/gcc /opt/mongodbtoolchain/v3/bin/aarch64-mongodb-linux-gcc构建mongo-toolscd /root/mongodb-tools-r4.2.0/src/github.com/mongodb/mongo-tools . ./set_goenv.sh set_goenv ./build.sh ./build.sh ssl ./build.sh ssl sasl4 示例测试查看bin目录,可见5 FAQ如果遇到下面的错误,请升级go版本,重新配置路径。在http://www.cloud-onlinelab.cn/有编译好的mongodb-tools可供下载。
上滑加载中