1.mongodb特殊从节点
a.可以将从节点的Priority属性设置为0,也就是选举优先级为0,不会被选举为Primary
b. 可以将从节点的vote属性设置为0,即不参与选举主节点
c. Hidden属性:不能被选为主(Priority为0),并且对Driver不可见。因Hidden节点不会接受Driver的请求,可使用Hidden节点做一些数据备份、离线计算的任务,不会影响复制集的服务。
d. Delayed属性:必须是Hidden节点,并且其数据落后与Primary一段时间(可配置,比如1个小时)。因Delayed节点的数据比Primary落后一段时间,当错误或者无效的数据写入Primary时,可通过Delayed节点的数据来恢复到之前的时间点。
2.mongodb中的oplog
Primary与Secondary之间通过oplog来同步数据,Primary上的写操作完成后,会向特殊的local.oplog.rs特殊集合写入一条oplog,Secondary不断的从Primary取新的oplog并应用。因oplog的数据会不断增加,local.oplog.rs被设置成为一个capped集合,当容量达到配置上限时,会将最旧的数据删除掉。另外考虑到oplog在Secondary上可能重复应用,oplog必须具有幂等性,即重复应用也会得到相同的结果。
如下oplog的格式,包含ts、h、op、ns、o等字段
{
"ts" : Timestamp(1446011584, 2),
"h" : NumberLong("1687359108795812092"),
"v" : 2,
"op" : "i",
"ns" : "test.nosql",
"o" : { "_id" : ObjectId("563062c0b085733f34ab4129"), "name" : "mongodb", "score" : "100" }
}
- ts: 操作时间,当前timestamp + 计数器,计数器每秒都被重置
- h:操作的全局唯一标识
- v:oplog版本信息
- op:操作类型
- i:插入操作
- u:更新操作
- d:删除操作
- c:执行命令(如createDatabase,dropDatabase)
- n:空操作,特殊用途
- ns:操作针对的集合
- o:操作内容,如果是更新操作
- o2:操作查询条件,仅update操作包含该字段
Secondary初次同步数据时,会先进行init sync,从Primary(或其他数据更新的Secondary)同步全量数据,然后不断通过从Primary的local.oplog.rs集合里查询最新的oplog并应用到自身。
init sync过程包含如下步骤
- T1时间,从Primary同步所有数据库的数据(local除外),通过listDatabases + listCollections + cloneCollection命令组合完成,假设T2时间完成所有操作。
- 从Primary应用[T1-T2]时间段内的所有oplog,可能部分操作已经包含在步骤1,但由于oplog的幂等性,可重复应用。
- 根据Primary各集合的index设置,在Secondary上为相应集合创建index。(每个集合_id的index已在步骤1中完成)。
oplog集合的大小应根据DB规模及应用写入需求合理配置,配置得太大,会造成存储空间的浪费;配置得太小,可能造成Secondary的init sync一直无法成功。比如在步骤1里由于DB数据太多、并且oplog配置太小,导致oplog不足以存储[T1, T2]时间内的所有oplog,这就Secondary无法从Primary上同步完整的数据集。
3.应用程序有关mongodb的读写设置
3.1 读数据库相关
默认情况下,复制集的所有读请求都发到Primary,Driver可通过设置Read Preference来将读请求路由到其他的节点。
- primary: 默认规则,所有读请求发到Primary
- primaryPreferred: Primary优先,如果Primary不可达,请求Secondary
- secondary: 所有的读请求都发到secondary
- secondaryPreferred:Secondary优先,当所有Secondary不可达时,请求Primary
- nearest:读请求发送到最近的可达节点上(通过ping探测得出最近的节点)
3.2 写数据库相关
默认情况下,Primary完成写操作即返回,Driver可通过设置Write Concern来设置写成功的规则。
如下的write concern规则设置写必须在大多数节点上成功,超时时间为5s。
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: majority, wtimeout: 5000 } }
)
4.mongodb的备份与恢复
mongodump命令来备份MongoDB数据。该命令可以导出所有数据到指定目录中。
mongodb使用 mongorestore 命令来恢复备份的数据。
5.mongodb监控
a.mongostat是mongodb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。
b. mongotop也是mongodb下的一个内置工具,mongotop提供了一个方法,用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。
6.mongodb查询分析
MongoDB 查询分析可以确保我们建立的索引是否有效,是查询语句性能分析的重要工具;mongodb查询是否能使用索引有一个前缀匹配原则,也就是mongodb的查询与排序语句中的字段是索引的前缀就能使用这个索引。
a.db.collection.find().explain("executionStats")提供了我们查询消耗了多长时间、查询中匹配到的索引、以及扫描了多少记录、匹配中的多少记录等信息
b.db.collection.find().hint(索引)可以强制MongoDB的查询使用某个索引
7.mongodb全文检索
全文检索对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。
例如:db.posts.save({"post_text": "enjoy the mongodb articles on Runoob"})
对post_text建立全文索引:db.posts.ensureIndex({post_text:"text"})
全文检索:db.posts.find({$text:{$search:"runoob"}})全文检索不区分大小写
8.mongodb正则表达式
正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,正则表达式可以使用$regex或者//,例如:db.posts.save({"post_text": "enjoy the mongodb articles on Runoob"})
db.posts.find({"post_text":/mongodb/})或者
db.posts.find({"post_text":{$regex:"mongodb"}})
9.mongodb GridFS
GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。
GridFS 可以更好的存储大于16M的文件。
GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
例如: mongofiles -d test -h localhost:27018 put D:\work\1.jpg
通过db.fs.files.find()找到_id也就是fs.chunks的files_id
例如:db.fs.chunks.find({"files_id":ObjectId("58de42af2119591f483bee9c")})就可以找到相应的chunks存储的文件数据
10.mongodb键值自增长
mongodb没有键值自增长的功能,假设现在我们有一个表products需要它的键值按照1,2,3,4....这种方式自增长,我们可以引入另外一个集合counters的product_id记录product当前的键值最大值,每一次我们需要向products表插入记录,我们首先使用db.counters.findAndModify({query:{},update:{$inc:{product_id:1}},new:true,upsert:true})获得增加product_id之后新的值,然后利用这个值作为products新记录的_id