写在前面的话
数据库产品已经学习了两个,MySQL 和 Redis。接下来开始研究另外一款 NoSQL 产品 MongoDB,注意跟芒果没啥关系。该产品对于运维来说,相对于操作少一些。
关于 MongoDB
对于 NoSQL 产品,可以简单的做个区分:
用于键值存储:Redis 和 Memcached 等。
用于文档存储:MongoDB 等。
用于图存储:FlockDB 等。
用于列存储:Hbase(大数据)等。
在 MongoDB 中数据以 Json 形式存储。其结构包含:库,集合(表),文档(数据行)。
安装 MongoDB
本文选用的是目前 MongoDB 最新社区版本:4.2.1
https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.1.tgz
选择版本:
1. 系统方面的初始化优化配置:
# 关闭大页内存机制 if test -f /sys/kernel/mm/transparent_hugepage/enabled; then echo never > /sys/kernel/mm/transparent_hugepage/enabled fi if test -f /sys/kernel/mm/transparent_hugepage/defrag; then echo never > /sys/kernel/mm/transparent_hugepage/defrag fi # 查看设置结果 cat /sys/kernel/mm/transparent_hugepage/enabled cat /sys/kernel/mm/transparent_hugepage/defrag # 初始化目录 mkdir -p /data/{backup,data,logs,packages,services}
mkdir -p /data/packages/mongodb
将安装包上传到:/data/packages/mongodb 下
2. 解压安装:
# 解压 cd /data/packages/mongodb tar -zxf mongodb-linux-x86_64-rhel70-4.2.1.tgz mv mongodb-linux-x86_64-rhel70-4.2.1 /data/services/mongodb # 配置基础目录 cd /data/services/mongodb rm -f LICENSE-Community.txt MPL-2 README THIRD-PARTY-NOTICES THIRD-PARTY-NOTICES.gotools mkdir data logs conf
3. 添加配置文件(配置文件支持 YAML 格式):
cat > /data/services/mongodb/conf/mongo.conf << EOF # 系统日志有关 systemLog: destination: file # 日志位置 path: "/data/services/mongodb/logs/mongodb.log" # 日志以追加模式记录 logAppend: true # 数据存储有关 storage: journal: enabled: true # 数据路径的位置 dbPath: "/data/services/mongodb/data" # 进程控制 processManagement: # 后台守护进程 fork: true # pid文件的位置 pidFilePath: "/data/services/mongodb/logs/mongodb.pid" # 网络配置有关 net: # 监听地址 bindIp: 192.168.200.101,127.0.0.1 # 端口号 port: 27000
EOF
mongodb 的默认端口号为 27017,但是对于我们管理这个服务而言,我自己是会更改他的端口号的。这有助于服务的安全性。
当然,这个端口会是我们内部自己约定好的,比如上一节的 Redis 采用 17000。
4. 启动 mongodb:
/data/services/mongodb/bin/mongod -f /data/services/mongodb/conf/mongo.conf
在 CentOS 7 中可以采用 systemd 来进行管理:
cat > /etc/systemd/system/mongod-27000.service <<EOF [Unit] Description=mongodb-27000 After=network.target remote-fs.target nss-lookup.target [Service] User=root Type=forking ExecStart=/data/services/mongodb/bin/mongod --config /data/services/mongodb/conf/mongo.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/data/services/mongodb/bin/mongod --config /data/services/mongodb/conf/mongo.conf --shutdown PrivateTmp=true [Install] WantedBy=multi-user.target EOF
此时就可以使用 systemctl 启动关闭:
# 启动 systemctl start mongod-27000 # 关闭 systemctl stop mongod-27000
5. 登录库,由于修改了端口所以需要指定:
/data/services/mongodb/bin/mongo --port 27000
基本操作
1. 在 mongodb 中,有三个和 MySQL 可以一样使用的命令:
# 查看数据库 show databases; # 切换数据库 use admin; # 查看表 show tables;
当然,这是为了便于我们理解,才用的命令。除了这三个之外,mongodb 和 MySQL 一点都不一样,看看 mongdb 原生的命令:
# 显示数据库 show dbs # 显示表 show collections # 查看当前所在库 db
结果如图:
在 mongdb 的命令使用就像代码中的函数调用一样。可以将其分为三类,db 对象类,rs 复制集类,sh 分片集群类。
同时,我们可以使用 tab 来进行命令补全:
或者使用 help 查看用法:
2. 关于 mongdb 的库:
在 mongodb 中,默认存在 4 个库:
admin:mongdb 系统预留库。
local:本地预留库,用于存储关键日志。
config:用于保存 mongdb 配置信息。
test:这个库 show dbs 没有显示,却是我们登录后默认所在的库。
同时,mongdb 没有所谓的创建数据库的概念,只要你需要,use 库名即可创建,但是如果库里面是空的,我们就没法看到他。
3. 简单操作:
库操作:
> use test switched to db test > db.dropDatabase() { "ok" : 1 }
表操作:
> use hello switched to db hello > db.createCollection('a') { "ok" : 1 } > db.createCollection('b') { "ok" : 1 } > show collections a b
当然,mongodb 中表也不需要预先创建,直接插入数据就能创建:
> use hello switched to db hello > db.c.insert({name:"zhangsan",age:18}) WriteResult({ "nInserted" : 1 }) > show collections a b c
和 MySQL 不通的是,mongdb 中每行数据没有字段的概念,不存在约束:
> use hello switched to db hello > db.d.insert({name:"zhangsan"}) WriteResult({ "nInserted" : 1 }) > db.d.insert({age:18}) WriteResult({ "nInserted" : 1 }) > db.d.insert({gender:"m",address:"sz"}) WriteResult({ "nInserted" : 1 })
文档操作:插入10000行数据:
for(i=0;i<10000;i++){db.log.insert({"uid":i,"name":"mongo","date":new Date()})}
简单的操作:
# 统计记录数量 > db.log.count() 10000 # 查找指定记录 > db.log.find({uid:999}) { "_id" : ObjectId("5dd2470be595a02ad9dc26f9"), "uid" : 999, "name" : "mongo", "date" : ISODate("2019-11-18T07:23:55.147Z") } # 查找指定记录并友好显示 > db.log.find({uid:999}).pretty() { "_id" : ObjectId("5dd2470be595a02ad9dc26f9"), "uid" : 999, "name" : "mongo", "date" : ISODate("2019-11-18T07:23:55.147Z") } # 删除所有记录 > db.log.remove({}) WriteResult({ "nRemoved" : 10000 })
查看数据占用大小:
> db.log.totalSize()
274432
用户管理
在过去的 mongo 版本中,没有强制用户绑定 IP 地址,有些用户也不会设置密码,和 Redis 一样,在公网上裸奔,于是经常出现被攻击的情况。然后以讹传讹说这东西不安全乱七八糟的。所以作为运维,我们从根源上规避这些问题。对于这类数据库类产品,部署云服务器应该尽量避免拥有外网访问权限。配合更改默认端口,配置用户验证等方式提高其安全性。
在 mongdb 中,用户可以分为管理员用户和普通用户。
普通用户又可以根据权限分为只读,读写用户。
1. 创建超级管理员用户:
db.createUser({user: "root",pwd: "123456",roles: [{role:"root",db:"admin"}]})
role 包含三种角色,root / read / readWrite
但是此时单是设置用户没用,因为我们的配置文件并未开启用户认证,需要增加配置然后重启:
# 安全验证有关配置 security: # 是否打开用户名密码验证 authorization: enabled
2. 此时登录:
/data/services/mongodb/bin/mongo --port 27000
结果如图:
可以发现啥也看不到!
3. 登录用户:
/data/services/mongodb/bin/mongo -uroot -p 123456 --port 27000
此时就可以执行查看:
4. 当然,也可以在里面登录:
> use admin switched to db admin > db.auth("root","123456") 1
必须先切换到 admin 库才能登录!
5. 查看用户:
db.system.users.find().pretty()
结果如下:
6. 给普通的库建立单独的用户:
# 切换库 use world # 创建用户 db.createUser({user:"app",pwd:"123456",roles:[{role:"readWrite",db:"world"}]})
此时可以切换到 admin 库查看刚刚新建的用户。
7. 删除用户:
> use world switched to db world > db.dropUser("app") true
8. 修改用户密码两种方式:
方式1:再次添加用户,密码就能覆盖。
方式2:直接修改
db.changeUserPassword("app","helloworld")
基本管理暂时到这里!