史上最全的mongodb分片集群搭建,从介绍安装到集群搭建授权,你再也找不到比他更加详细的资料了,未经允许禁止转载!!
MongoDB是一个便于开发和扩展设计的文档数据库,属于NoSQL数据库的一种。MongoDB中的记录是一个由字段和值组成的文档,类似于JSON对象。
Mongodb提供高性能的数据永久性
丰富的查询语言
支持数据聚合
例:
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
第一阶段: $match 阶段通过状态字段过滤文档,并将状态等于“ a”的文档传递到下一阶段。
第二阶段: $group 阶段通过 cust _ id 字段对文档进行分组,以计算每个惟一 cust _ id 的总和。
文字搜寻
例:使用以下文档创建一个集合存储
db.stores.insert(
[
{ _id: 1, name: "Java Hut", description: "Coffee and cakes" },
{ _id: 2, name: "Burger Buns", description: "Gourmet hamburgers" },
{ _id: 3, name: "Coffee Shop", description: "Just coffee" },
{ _id: 4, name: "Clothes Clothes Clothes", description: "Discount clothing" },
{ _id: 5, name: "Java Shopping", description: "Indonesian goods" }
]
)
例:直接对名字和描述字段进行文本搜索
db.stores.createIndex( { name: "text", description: "text" } )
例:搜索包含java、coffee、shop中任何术语的所有商店
db.stores.find( { $text: { $search: "java coffee shop" } } )
或者查找所有包含“咖啡店”的文件
db.stores.find( { $text: { $search: "\"coffee shop\"" } } )
或者包括java、shop,不包括coffee的文件
db.stores.find( { $text: { $search: "java shop -coffee" } } )
地理空间查询
高可用性
提供副本集
支持自动的数据转移、数据冗余
副本集属于一组MongoDB服务器,用于维护相同的数据集,提供冗余并增加数据可用性
水平可扩展性
支持多储存引擎,允许第三方开发引擎
导入包管理系统使用的公钥
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
如果报出:ok 则成功;
如果提示gnupg未安装,则:
sudo apt-get install gnupg
之后重新导入密钥:
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
为 MongoDB 创建一个列表文件
Ubuntu 18.04:
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
Ubuntu 20.04:
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
Ubuntu 16.04:
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
重新加载本地包数据库
sudo apt-get update
安装 MongoDB 软件包
sudo apt-get install -y mongodb-org
要运行和管理 mongod 进程,需使用操作系统内置的 init 系统。Linux 的最新版本倾向于使用 systemd (使用 systemctl 命令) ,而 Linux 的旧版本倾向于使用 System v init (使用 service 命令)。
运行以下命令确认平台使用的那个init系统:
ps --no-headers -o comm 1
systemctl启动mongodb:
sudo systemctl start mongod
service启动mongodb:
sudo service mongod start
副本集是维护相同数据集的一组 mongod 实例。一个副本集包含多个数据承载节点和一个可选的仲裁节点。在数据承载节点中,一个且只有一个成员被视为主节点,而其他节点被视为次要节点。
主节点:接收所有写操作,一个副本集只能有一个。
副本节点:复制主节点操作日志,并将操作应用到它们的数据集中,以便副本节点的数据集备份主系统的数据集;在主节点挂掉后,有选举权限的副本节点会自动发起选举,并从中选举出新的主节点;副本节点可以通过配置指定其具体的属性,比如选举、隐藏、延迟同步等,最多可以有50个副本节点,但只能有7个副本节点能参与选举。虽然副本节点不能处理写操作,但可以处理读请求。
副本集架构:搭建一个副本集集群最少需要三个节点:一个主节点,两个备份节点,如果三个节点分布合理,基本可以保证线上数据99.9%安全。
仲裁节点:如果只有一个主节点,一个副本节点,且没有资源拿来当第二个副本节点,那就可以起一个仲裁者节点(arbiter),不存数据,只用来选举用。
副本集成员属性priority、hidden、slaveDelay、tags、votes
priority
对于副本节点可以使用该属性来控制其被选举为主节点的可能,取值范围为:0-1000(仲裁点取值只有0和1),值越大被选举称为主节点的可能性就越大,若为0则不能被选举,也不能发起选举。
hidden
配置hidden为true则会变成隐藏节点,隐藏节点会从主节点同步数据,但对客户端不可见,执行db.isMaster()方法也不会显示,其priority值必须为0,不能被选举为主节点;但是如果配置有选举权则可以参加选举。
slaveDelay
延迟同步即延迟从主节点同步数据,其值若配置为1小时,则1小时后延迟节点才会同步主节点1小时前的数据。延迟节点必须是隐藏节点,priority=0.
tags
支持对副本集成员打标签,查询数据时使用
votes
表示节点是否有权选举,最大可一配置7个副本节点。
写关注
指主节点写入一条数据,主节点处理完成后,需要其他承载数据的副本节点也确认写完后才会返回写入成功。
其主要用于解决主节点挂掉后,数据还未来的及同步到副本节点,而导致的数据丢失问题。
可以配置节点个数:
w:1 表示主节点写入数据成功即可给客户端返回成功;(mongodb 4.4默认)
w:2 表示除了主节点,还需要收到其中一个副本节点返回写入成功;
w:majority 表示需要集群中大多数承载数据且有选举权限的节点返回写入成功。
设置:
自定义:
db.products.insert(
{ item: "envelopes", qty : 100, type: "Clasp" },
{ writeConcern: { w: "majority" , wtimeout: 5000 } }
)
在副本集中配置(建库时添加):
conf = rs.conf()
conf.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
conf.reconfig(conf)
读偏好
读跟写不一样,为了保持一致性,写只能通过主节点,但读可以选择主节点,也可以选择副本节点,区别是主节点数据最新,副本节点因为同步问题可能会有延迟,但从副本节点读取数据可以分散对主节点的压力。
模式 | 特点 |
---|---|
primary | 所有读请求都从主节点读取 |
primaryPreferred | 主节点正常,则所有读请求都从主节点读取,如果主节点挂掉,则从符合条件的副本节点读取 |
secondary | 所有读请求都从副本节点读取 |
secondaryPreferred | 所有读请求都从副本节点读取,但如果副本节点都挂掉了,那就从主节点读取 |
nearest | 主要看网络延迟,选取延迟最小的节点,主节点跟副本节点均可 |
模式选择条件:
Tag Sets(标签)
给节点加上标签,然后查找数据时,可以根据标签选择对应的节点,然后在该节点查找数据。可以通过mongo shell 使用 rs.conf() 查看当前每个节点下面的 tags, 修改或者添加tags 。
给成员添加:
conf = rs.conf();
conf.members[0].tags = { "dc": "east", "usage": "production" };#members:成员目标
conf.members[1].tags = { "dc": "east", "usage": "reporting" };
conf.members[2].tags = { "dc": "west", "usage": "production" };
rs.reconfig(conf);
在连接到副本集的 mongo shell 中,为了将读操作指向标记为特定标记的辅助设备,可以使用 readPref ()方法指定读取首选模式和标记集。比如说
db.collection.find({}).readPref( "secondary", [ { "dc": "east", "usage": "production" } ] )
如果不确定某一标记是否存在,则可以:
db.collection.find({}).readPref( "secondary", [ { "dc": "east"}, { "usage": "production" } ] )
若"dc": “east"没找到,则找"usage”: “production”。
给副本集成员添加:
一个成员VA 标记为 dc_va;一个成员CA 标记为 dc_ca
conf = rs.conf();
conf.members[0].tags = { "dc_va": "rack1"};
conf.members[1].tags = { "dc_va": "rack2"};
conf.members[2].tags = { "dc_ca": "rack1"};
conf.members[3].tags = { "dc_ca": "rack2"};
conf.members[4].tags = { "dc_va": "rack1"};
rs.reconfig(conf);
自定义
定义一个write concern MultipleDC,它要求将 write 传播给两个具有不同 dc _ va 标记值的成员和一个具有任意 dc _ ca 标记值的成员。
conf = rs.conf();
conf.settings = { getLastErrorModes: { MultipleDC : { "dc_va": 2, "dc_ca": 1 } } };
rs.reconfig(conf);
自定义标记的使用:
db.collection.insert( { id: "xyz", status: "A" }, { writeConcern: { w: "MultipleDC" } } )
maxStalenessSeconds (可容忍的最大同步延迟)
一般取回大于90S,小于这个值则会抛出异常
Hedged Read (对冲读取)
mongos 实例路由读取请求时会同时发给两个符合条件的副本集节点,然后那个先返回结果就返回这个结果给客户端(4.4版本和之后版本支持)
创建数据文件夹:
mkdir -p /data/master
mkdir -p /data/slaver
mkdir -p /data/arbiter
效果:data 文件夹包含 arbiter master slaver 三个文件夹
创建日志存放文件:
vi /log/master.log
vi /log/slaver.log
vi /log/arbiter.log
效果:log文件夹包含 master.log slaver.log arbiter.log 三个文件(注意,data文件夹和log文件夹均无上级文件夹,可自行创建不同名称不同位置的文件夹,注意路径与下文中的配置文件一致即可
创建配置文件
在第一步创建的三个文件中创建 文件夹同名.conf 后缀文件,即:master文件夹中应有 master.conf 文件,slaver文件夹中应有 slaver.conf文件,arbiter文件夹中应有 arbiter.conf文件。
各配置文件内容如下:
master.conf:
dbpath =/data/master
logpath = /log/master.log
pidfilepath =/data/ master.pid
directoryperdb = true
logappend = true
replSet = away
bind_ip = localhost
port = 27018
fork = true
slaver.conf:
dbpath =/data/slaver
logpath =/log/slaver.log
pidfilepath = /data/slaver.pid
directoryperdb = true
logappend = true
replSet = away
bind_ip = localhost
port = 27019
fork = true
arbiter.conf:
dbpath = /data/arbiter
logpath = /log/arbiter.log
pidfilepath = arbiter.pid
directoryperdb = true
logappend = true
replSet = away
bind_ip = localhost
port = 27020
fork = true
参数:
dbpath:数据存放目录
logpath:日志存放路径
pidfilepath:进程文件,方便停止mongodb
directoryperdb:为每一个数据库按照数据库名建立文件夹存放
logappend:以追加的方式记录日志
replSet:replica set的名字
bind_ip:mongodb所绑定的ip地址
port:mongodb进程所使用的端口号,默认为27017
oplogSize:mongodb操作日志文件的最大大小。单位为Mb,默认为硬盘剩余空间的5%
fork:以后台方式运行进程
noprealloc:不预先分配存储
启动mongod程序
mongod --config <配置路径>
例如:
lhd@lhd:~$ sudo mongod --config /data/master/master.conf
[sudo] lhd 的密码:
主从配置
启动mongo客户端:
mongo localhost:27018
设置主,从,仲裁点
use admin
switched to db admin
zjd={_id:"one",members:[{_id:0,host:"localhost:27018",priority:2},{_id:1,host:"localhost:27019",priority:1},{_id:2,host:"localhost:27020",arbiterOnly:true}]};
参数:
zjd是可以任意的名字,不要用mongodb的关键字,conf,config都可以。
第一个_id表示replica set的名字,这个数据必须和第三步配置文件中的replica set一致,不然会报错。
members里包含的是所有节点的地址以及优先级,优先级最高的即成为主节点,值为0则不会参加选举成为主节点,对于仲裁节点,需要有个特别的配置——arbiterOnly:true。这个千万不能少了,不然主备模式就不能生效。
使配置生效:
rs.initiate(zjd)
查看状态: rs.status()
分片: 分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。通过一个名为mongos的路由进程进行操作,mongos知道数据和片的对应关系(通过配置服务器)。
均衡器:负责数据迁移,周期性的检查分片是否存在不均衡,如果不存在则会开始块的迁移,config.locks集合里的state表示均衡器是否找正在运行,0表示非活动状态,2表示正在均衡。均衡迁移数据的过程会增加系统的负载:目标分片必须查询源分片的所有文档,将文档插入目标分片中,再清除源分片的数据。可以关闭均衡器(不建议):关闭会导致各分片数据分布不均衡,磁盘空间得不到有效的利用。
服务器1:192.168.11.152 | 服务器2:192.168.11.153 | 服务器3 :192.168.11.154 |
---|---|---|
mongos | mongos | mongos |
config server | config server | config server |
shard1 主节点 | shard1 副本节点 | shard1 副本节点 |
shard2 主节点 | shard2 副本节点 | shard1 副本节点 |
shard3 主节点 | shard2 副本节点 | shard1 副本节点 |
服务 | 端口 | 说明 |
---|---|---|
mongos | 20000 | 路由服务器 |
config | 21000 | 配置服务器 |
shard1 | 27001 | 分片服务器 |
shard2 | 27002 | 分片服务器 |
shard3 | 27003 | 分片服务器 |
mkdir -p /usr/local/mongodb/conf #配置文件目录
mkdir -p /usr/local/mongodb/mongos/log #路由服务日志目录
mkdir -p /usr/local/mongodb/config/data #配置服务数据文件目录
mkdir -p /usr/local/mongodb/config/log #配置服务日志目录
mkdir -p /usr/local/mongodb/shard1/data #分片服务器数据文件目录
mkdir -p /usr/local/mongodb/shard1/log #分片服务器日志目录
mkdir -p /usr/local/mongodb/shard2/data
mkdir -p /usr/local/mongodb/shard2/log
mkdir -p /usr/local/mongodb/shard3/data
mkdir -p /usr/local/mongodb/shard3/log
vi /etc/profile
# MongoDB 环境变量内容
export PATH=/usr/local/mongodb/bin:$PATH
source /etc/profile
注:三台服务器都需搭建(参照服务器分配表)
vi /usr/local/mongodb/conf/config.conf
pidfilepath = /usr/local/mongodb/config/log/configsrv.pid
dbpath = /usr/local/mongodb/config/data
logpath = /usr/local/mongodb/config/log/congigsrv.log
logappend = true
bind_ip = 0.0.0.0
port = 21000
fork = true
#declare this is a config db of a cluster
configsvr = true
#副本集名称
replSet = configs
#设置最大连接数
maxConns = 20000
mongod -f /usr/local/mongodb/conf/config.conf
使用任意一台服务器,连接 MongoDB
mongo --port 21000
设置config 变量
config = {
_id : "configs",
members : [
{_id : 0, host : "192.168.11.152:21000" },
{_id : 1, host : "192.168.11.153:21000" },
{_id : 2, host : "192.168.11.154:21000" }
]
}
初始化副本集
rs.initiate(config)
查询状态
rs.status()
搭建分片集群
注:三台服务器配置相同,注意:端口号、副本集名称、目录路经!!!!
配置文件
vi /usr/local/mongodb/conf/shard1.conf
配置文件内容
pidfilepath = /usr/local/mongodb/shard1/log/shard1.pid
dbpath = /usr/local/mongodb/shard1/data
logpath = /usr/local/mongodb/shard1/log/shard1.log
logappend = true
bind_ip = 0.0.0.0
port = 27001
fork = true
#副本集名称
replSet = shard1
#declare this is a shard db of a cluster;
shardsvr = true
#设置最大连接数
maxConns = 20000
启动shard服务(注:shard1、shard2、shard3都要启动)
mongod -f /usr/local/mongodb/conf/shard1.conf
初始化副本集
登录任意一台服务器,连接MongoDB(注:三个端口27001、27002、27003都要做!!)
mongo --port 27001
use admin
config = {
_id : "shard1",
members : [
{_id : 0, host : "192.168.11.152:27001",priority:2},
{_id : 1, host : "192.168.11.153:27001",priority:1},
{_id : 2, host : "192.168.11.154:27001",priority:1}
]
}
rs.initiate(config)
配置路由服务器mongos
配置文件
vi /usr/local/mongodb/conf/mongos.conf
文件内容
pidfilepath = /usr/local/mongodb/mongos/log/mongos.pid
logpath = /usr/local/mongodb/mongos/log/mongos.log
logappend = true
bind_ip = 0.0.0.0
port = 20000
fork = true
#监听的配置服务器,只能有1个或者3个(初始设计为三个,详见服务器分配) configs为配置服务器的副本集名字
configdb = configs/192.168.11.152:21000,192.168.11.153:21000,192.168.11.154:21000
#设置最大连接数
maxConns = 20000
启动mongos服务(注:启动顺序为配置服务器,分片服务器,路由服务器,三台服务器全部启动)
mongos -f /usr/local/mongodb/conf/mongos.conf
串联路由服务器
目前搭建了mongodb配置服务器、路由服务器,各个分片服务器,应用程序连接到mongos路由服务器还不能使用分片机制(各个分片还处于相互独立阶段),需要在程序里设置分片配置,让分片生效。
登录任意一台路由服务器
mongo --port 20000
使用admin数据库
use admin
串联路由服务器与分配副本集
sh.addShard("shard1/192.168.11.152:27001,192.168.11.153:27001,192.168.11.154:27001")
sh.addShard("shard2/192.168.11.152:27002,192.168.11.153:27002,192.168.11.154:27002")
sh.addShard("shard3/192.168.11.152:27003,192.168.11.153:27003,192.168.11.154:27003")
查看集群状态(注:sh代表分片集群,rs代表副本集)
sh.status()
结果大致如图
启用集合分片生效
登录任意一台路由服务器
mongo --port 20000
使用admin数据库
use admin
指定数据库分片生效(注:此时我们的数据库为空,需要建立一个测试库)
sh.enableSharding("test")
指定数据库分片集合和片键(注: id字段是片键。片键的选择:利于分块、分散写请求、查询数据。)
sh.shardCollection("test.table1",{"id":1})
注:片键有两种分片方式,1.哈希分片,2.远程分片;哈希分片依靠哈希值分片,远程分片基于范围分片(默认此方式)
测试分片结果
追加分片
进行分片配置和启动分片过程后
sh.addShard("192.168.11.152:27004,192.168.11.153:27004,192.168.11.154:27004")
进入主配置服务器
mongo --port 21000
创建root账户
use admin
db.createUser({user:'root',pwd:'root.123',roles:[{role:'root',db:'admin'}]})
创建管理员账户
db.createUser({user:'admin', pwd:'admin.123', roles:[{role: 'userAdminAnyDatabase', db:'admin' }]})
创建集群管理员账号
db.createUser({user:'clusteradmin', pwd:'cluster.123', roles:[{role: 'clusterAdmin', db:'admin' }]})
创建自定义账号
use yourdb
db.createUser({user:'test', pwd:'test.123', roles:[{role: 'readWrite', db:'yourdb' }]})
数据库用户角色
read:允许用户读取指定的数据库
readWrite:允许用户读写指定数据库
数据库管理角色
dbAdmin:允许用户在指定数据库执行管理函数,创建索引,删除索引,查看统计.
userAdmin:允许用户向system.users集合写入,可以在指定数据库创建删除管理账号
dbOwner:指定数据库最大的权限,是readWrite+dbAdmin+userAdmin的和。
群集管理角色(只在admin数据库可用)
clusterAdmin:用户所有分片和复制集相关函数的管理权限
clusterManager:管理和监控群集。
clusterMonitor:只能访问监控工具。
hostManager:监视和管理。
备份和还原角色
所有角色(只在admin数据库可用)
readAnyDatabase:赋予用户所有数据库的读权限
readWriteAnyDatabase:赋予用户所有数据库的读写权限
userAdminAnyDatabase:赋予所有数据库的useradmin权限
dbAdminAnyDatabase:赋予所有数据库的dbadmin权限。
超级角色(只在admin可用)
root:超级账号,超级权限
创建集群认证文件
openssl rand -base64 756 > mongo_keyf
chmod 400 mongo_keyfile
将文件发送到其他两个服务器
scp mongo_keyfile [email protected]:/usr/local/mongodb/
配置修改
修改config.conf文件
vi conf/config.conf
# 新增以下内容行
auth = true
keyFile = /usr/local/mongodb/mongo_keyfile
修改shard.conf文件(注:有三个服务器的,总计九个文件)
vi conf/shard1.conf
# 新增以下内容行
auth = true
keyFile = /usr/local/mongodb/mongo_keyfile
修改mongos.conf文件
vi conf/mongos.conf
# 新增以下内容行
keyFile = /usr/local/mongodb/mongo_keyfile