MongoDB每次都要rs.slaveOk(),好烦啊~
今天来一个MongoDB实用的技巧。
01背景介绍
在MongoDB的副本集中,如果你利用mongo-shell连接一个从节点,进行查询操作,经常会遇到下面的报错:
代码语言:javascript复制[root@ /data1]# /usr/local/bin/mongo mongodb://root:xxxxx@10.xx.xx.xx:27017/admin
MongoDB shell version v3.6.3
connecting to: mongodb://10.xx.xx.xx:27017/admin
MongoDB server version: 3.6.3
Server has startup warnings:
2021-12-24T18:06:34.334 0800 I STORAGE [initandlisten]
2021-12-24T18:06:34.334 0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2021-12-24T18:06:34.334 0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2021-12-24T18:06:36.233 0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2021-12-24T18:06:36.234 0800 I CONTROL [initandlisten]
cluster_name:SECONDARY> show dbs;
2022-01-04T22:50:43.712 0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:65:1
shellHelper.show@src/mongo/shell/utils.js:816:19
shellHelper@src/mongo/shell/utils.js:706:15
@(shellhelp2):1:1
错误信息中,比较明显的给出来了,就是当前连接的是一个secondary,不是primary,而且这个secondary没有开启rs.slaveOk(),也就是不允许直接读取secondary上的数据。
那么,在交互式命令行下面,怎么解决这个问题呢?
代码语言:javascript复制cluster_name:SECONDARY> rs.slaveOk()
cluster_name:SECONDARY> show dbs;
admin 0.000GB
config 0.000GB
local 21.716GB
processlist 0.000GB
test 0.000GB
但是,这种方案只能在当前的连接中生效,下次重新连接,又需要输入一次rs.slaveOk()
这个问题,如果你写shell脚本的话,脚本里面肯定需要带上rs.slaveOk()命令,否则,你无法执行任何命令。
怎么办?
02如何配置rs.slaveOk()永久生效
官方文档有这么一句话:
When starting, mongo checks the user’s HOME directory for a JavaScript file named .mongorc.js. If found, mongo interprets the content of .mongorc.js before displaying the prompt for the first time. If you use the shell to evaluate a JavaScript file or expression, either by using the --eval option on the command line or by specifying a .js file to mongo, mongo will read the .mongorc.js file after the JavaScript has finished processing. You can prevent .mongorc.js from being loaded by using the --norc option.
翻译过来就是:当我们启动MongoDB时,MongoDB 在启动用户的 HOME 目录中检查名为 .mongorc.js 的 JavaScript 文件。如果找到,mongo 会在第一次显示返回客户请求之前应用 .mongorc.js 的内容。 我们可以使用 --norc 选项阻止加载 .mongorc.js。
我们可以将rs.slaveOk()这条命令,写入到这个.mongors.js文件中,这样,就可以让mongo-shell客户端为我们执行这个命令了。
我的MongoDB实例的启动用户是root,所以默认的js文件就在:
/root/.mongors.js 路径下。只需要向其中键入:
echo 'rs.slaveOk()' > /root/.mongors.js 即可
后续登录时候,就不需要手工输入这个rs.slaveOk()的命令了,效果如下:
代码语言:javascript复制[root@ /data1]# cat /root/.mongorc.js
rs.slaveOk()
[root@ /data1]# /usr/local/bin/mongo mongodb://root:xxxxxxx@10.xx.xx.xx:27017/admin
MongoDB shell version v3.6.3
connecting to: mongodb://10.xx.xx.xx:27017/admin
MongoDB server version: 3.6.3
Server has startup warnings:
2021-12-24T18:06:34.334 0800 I STORAGE [initandlisten]
2021-12-24T18:06:34.334 0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2021-12-24T18:06:34.334 0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2021-12-24T18:06:36.233 0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2021-12-24T18:06:36.234 0800 I CONTROL [initandlisten]
qs:SECONDARY> show dbs;
admin 0.000GB
config 0.000GB
local 21.716GB
processlist 0.000GB
test 0.000GB
当然,这个.mongors.js文件,你还可以写上其他的命令。它都可以在你登录mongodb服务的第一时间,自动帮你执行。
03关于rs.slaveOk()命令的小插曲
人种歧视话题,这两年比较敏感,尤其是漂亮国,去年闹出来了黑人被暴力执法的事件。迫于这个问题,数据库厂商在后续版本的迭代中,逐渐取消了slave、black等字眼。
例如:
MySQL低版本中,show slave status命令在8.0版本中会变成show replica status;
Redis低版本中的slaveof命令,6.0版本将会变成replicaof;
MongoDB中的rs.slaveOk()命令,在5.0版本之后,会变成rs.secondaryOk()
这些带slave的命令,将来应该都会消失。
除此之外,那些带有black,white等字眼的单词,也会变成allow、deny,例如防火墙相关的,blacklist---黑名单,whitelist---白名单,这些会逐渐变成allowlist,denylist
不得不说,技术也应该适应普遍的价值观。